forked from x/icebergs
opt base
This commit is contained in:
parent
1ec7aeff79
commit
8e7a403b35
@ -1,39 +1,29 @@
|
||||
package aaa
|
||||
|
||||
import (
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
func _role_list(m *ice.Message, userrole string) {
|
||||
m.Richs(ROLE, nil, kit.Select(mdb.FOREACH, userrole), func(key string, value ice.Map) {
|
||||
kit.Fetch(value[BLACK], func(k string, v ice.Any) {
|
||||
m.Push(ROLE, kit.Value(value, mdb.NAME))
|
||||
m.Push(mdb.ZONE, BLACK)
|
||||
m.Push(mdb.KEY, k)
|
||||
})
|
||||
kit.Fetch(value[WHITE], func(k string, v ice.Any) {
|
||||
m.Push(ROLE, kit.Value(value, mdb.NAME))
|
||||
m.Push(mdb.ZONE, WHITE)
|
||||
m.Push(mdb.KEY, k)
|
||||
})
|
||||
})
|
||||
}
|
||||
func _role_chain(arg ...string) string {
|
||||
return kit.ReplaceAll(kit.ReplaceAll(kit.Keys(arg), ice.PS, ice.PT), "..", ".")
|
||||
key := path.Join(strings.ReplaceAll(kit.Keys(arg), ice.PT, ice.PS))
|
||||
return strings.TrimPrefix(strings.TrimSuffix(strings.ReplaceAll(key, ice.PS, ice.PT), ice.PT), ice.PT)
|
||||
}
|
||||
func _role_black(m *ice.Message, userrole, chain string) {
|
||||
m.Richs(ROLE, nil, userrole, func(key string, value ice.Map) {
|
||||
list := value[BLACK].(ice.Map)
|
||||
mdb.HashSelectUpdate(m, userrole, func(value ice.Map) {
|
||||
m.Log_INSERT(ROLE, userrole, BLACK, chain)
|
||||
list := value[BLACK].(ice.Map)
|
||||
list[chain] = true
|
||||
})
|
||||
}
|
||||
func _role_white(m *ice.Message, userrole, chain string) {
|
||||
m.Richs(ROLE, nil, userrole, func(key string, value ice.Map) {
|
||||
list := value[WHITE].(ice.Map)
|
||||
mdb.HashSelectUpdate(m, userrole, func(value ice.Map) {
|
||||
m.Log_INSERT(ROLE, userrole, WHITE, chain)
|
||||
list := value[WHITE].(ice.Map)
|
||||
list[chain] = true
|
||||
})
|
||||
}
|
||||
@ -42,7 +32,7 @@ func _role_right(m *ice.Message, userrole string, keys ...string) (ok bool) {
|
||||
return true // 超级权限
|
||||
}
|
||||
|
||||
m.Richs(ROLE, nil, kit.Select(VOID, userrole), func(key string, value ice.Map) {
|
||||
mdb.HashSelectDetail(m, kit.Select(VOID, userrole), func(value ice.Map) {
|
||||
ok = true
|
||||
list := value[BLACK].(ice.Map)
|
||||
for i := 0; i < len(keys); i++ {
|
||||
@ -73,9 +63,20 @@ func _role_right(m *ice.Message, userrole string, keys ...string) (ok bool) {
|
||||
})
|
||||
return ok
|
||||
}
|
||||
|
||||
func RoleRight(m *ice.Message, userrole string, keys ...string) bool {
|
||||
return _role_right(m, userrole, kit.Split(kit.Keys(keys), ice.PT)...)
|
||||
func _role_list(m *ice.Message, userrole string) *ice.Message {
|
||||
mdb.HashSelectDetail(m, kit.Select(VOID, userrole), func(value ice.Map) {
|
||||
kit.Fetch(value[BLACK], func(k string, v ice.Any) {
|
||||
m.Push(ROLE, kit.Value(value, mdb.NAME))
|
||||
m.Push(mdb.ZONE, BLACK)
|
||||
m.Push(mdb.KEY, k)
|
||||
})
|
||||
kit.Fetch(value[WHITE], func(k string, v ice.Any) {
|
||||
m.Push(ROLE, kit.Value(value, mdb.NAME))
|
||||
m.Push(mdb.ZONE, WHITE)
|
||||
m.Push(mdb.KEY, k)
|
||||
})
|
||||
})
|
||||
return m
|
||||
}
|
||||
|
||||
const (
|
||||
@ -91,10 +92,8 @@ const (
|
||||
const ROLE = "role"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
ROLE: {Name: ROLE, Help: "角色", Value: kit.Data(mdb.SHORT, mdb.NAME)},
|
||||
}, Commands: ice.Commands{
|
||||
ROLE: {Name: "role role auto insert", Help: "角色", Actions: ice.Actions{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
ROLE: {Name: "role role auto insert", Help: "角色", Actions: ice.MergeAction(ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Rich(ROLE, nil, kit.Dict(mdb.NAME, TECH, BLACK, kit.Dict(), WHITE, kit.Dict()))
|
||||
m.Rich(ROLE, nil, kit.Dict(mdb.NAME, VOID, WHITE, kit.Dict(), BLACK, kit.Dict()))
|
||||
@ -105,17 +104,17 @@ func init() {
|
||||
m.Cmd(ROLE, WHITE, VOID, ice.USR_LOCAL_GO)
|
||||
}},
|
||||
mdb.INSERT: {Name: "insert role=void,tech zone=white,black key=", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Richs(ROLE, nil, m.Option(ROLE), func(key string, value ice.Map) {
|
||||
mdb.HashSelectUpdate(m, m.Option(ROLE), func(key string, value ice.Map) {
|
||||
m.Log_INSERT(ROLE, m.Option(ROLE), m.Option(mdb.ZONE), m.Option(mdb.KEY))
|
||||
list := value[m.Option(mdb.ZONE)].(ice.Map)
|
||||
list[m.Option(mdb.KEY)] = true
|
||||
list[_role_chain(m.Option(mdb.KEY))] = true
|
||||
})
|
||||
}},
|
||||
mdb.DELETE: {Name: "delete", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Richs(ROLE, nil, m.Option(ROLE), func(key string, value ice.Map) {
|
||||
mdb.HashSelectUpdate(m, m.Option(ROLE), func(key string, value ice.Map) {
|
||||
m.Log_DELETE(ROLE, m.Option(ROLE), m.Option(mdb.ZONE), m.Option(mdb.KEY))
|
||||
list := value[m.Option(mdb.ZONE)].(ice.Map)
|
||||
delete(list, m.Option(mdb.KEY))
|
||||
delete(list, _role_chain(m.Option(mdb.KEY)))
|
||||
})
|
||||
}},
|
||||
|
||||
@ -130,9 +129,12 @@ func init() {
|
||||
m.Echo(ice.OK)
|
||||
}
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
_role_list(m, kit.Select("", arg, 0))
|
||||
m.PushAction(mdb.DELETE)
|
||||
}, mdb.HashAction(mdb.SHORT, mdb.NAME)), Hand: func(m *ice.Message, arg ...string) {
|
||||
_role_list(m, kit.Select("", arg, 0)).PushAction(mdb.DELETE)
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
||||
func RoleRight(m *ice.Message, userrole string, arg ...string) bool {
|
||||
return m.Cmdx(ROLE, RIGHT, userrole, arg) == ice.OK
|
||||
}
|
||||
|
@ -4,54 +4,44 @@ import (
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
"shylinux.com/x/toolkits/logs"
|
||||
)
|
||||
|
||||
func _sess_check(m *ice.Message, sessid string) bool {
|
||||
func _sess_check(m *ice.Message, sessid string) {
|
||||
m.Option(ice.MSG_USERROLE, VOID)
|
||||
m.Option(ice.MSG_USERNAME, "")
|
||||
m.Option(ice.MSG_USERNICK, "")
|
||||
if sessid == "" {
|
||||
return false
|
||||
return
|
||||
}
|
||||
|
||||
m.Richs(SESS, nil, sessid, func(value ice.Map) {
|
||||
if value = kit.GetMeta(value); m.Warn(kit.Time(kit.Format(value[mdb.TIME])) < kit.Time(m.Time()), ice.ErrNotValid) {
|
||||
_source := logs.FileLineMeta(logs.FileLine(-1, 3))
|
||||
mdb.HashSelectDetail(m, sessid, func(value ice.Map) {
|
||||
if m.Warn(kit.Time(kit.Format(value[mdb.TIME])) < kit.Time(m.Time()), ice.ErrNotValid, sessid) {
|
||||
return // 会话超时
|
||||
}
|
||||
if m.Richs(USER, nil, value[USERNAME], func(value ice.Map) {
|
||||
m.Log_AUTH(
|
||||
USERROLE, m.Option(ice.MSG_USERROLE, value[USERROLE]),
|
||||
USERNAME, m.Option(ice.MSG_USERNAME, value[USERNAME]),
|
||||
USERNICK, m.Option(ice.MSG_USERNICK, value[USERNICK]),
|
||||
)
|
||||
}) == nil {
|
||||
m.Log_AUTH(
|
||||
USERROLE, m.Option(ice.MSG_USERROLE, value[USERROLE]),
|
||||
USERNAME, m.Option(ice.MSG_USERNAME, value[USERNAME]),
|
||||
USERNICK, m.Option(ice.MSG_USERNICK, value[USERNICK]),
|
||||
)
|
||||
}
|
||||
m.Log_AUTH(
|
||||
USERROLE, m.Option(ice.MSG_USERROLE, value[USERROLE]),
|
||||
USERNAME, m.Option(ice.MSG_USERNAME, value[USERNAME]),
|
||||
USERNICK, m.Option(ice.MSG_USERNICK, value[USERNICK]),
|
||||
_source,
|
||||
)
|
||||
})
|
||||
return m.Option(ice.MSG_USERNAME) != ""
|
||||
}
|
||||
func _sess_create(m *ice.Message, username string) string {
|
||||
if username == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
h := m.Cmdx(mdb.INSERT, SESS, "", mdb.HASH, mdb.TIME, m.Time(m.Conf(SESS, kit.Keym(mdb.EXPIRE))),
|
||||
USERROLE, UserRole(m, username), USERNAME, username, USERNICK, UserNick(m, username),
|
||||
IP, m.Option(ice.MSG_USERIP), UA, m.Option(ice.MSG_USERUA),
|
||||
)
|
||||
m.Event(SESS_CREATE, SESS, h, USERNAME, username)
|
||||
return h
|
||||
}
|
||||
|
||||
func SessCreate(m *ice.Message, username string) string {
|
||||
return m.Option(ice.MSG_SESSID, _sess_create(m, username))
|
||||
}
|
||||
func SessCheck(m *ice.Message, sessid string) bool {
|
||||
return _sess_check(m, sessid)
|
||||
msg := m.Cmd(USER, username)
|
||||
if msg.Length() > 0 {
|
||||
h := mdb.HashCreate(m, msg.AppendSimple(USERROLE, USERNAME, USERNICK), IP, m.Option(ice.MSG_USERIP), UA, m.Option(ice.MSG_USERUA)).Result()
|
||||
m.Event(SESS_CREATE, SESS, h, USERNAME, username)
|
||||
return h
|
||||
} else {
|
||||
h := mdb.HashCreate(m, m.OptionSimple(USERROLE, USERNAME, USERNICK), IP, m.Option(ice.MSG_USERIP), UA, m.Option(ice.MSG_USERUA)).Result()
|
||||
m.Event(SESS_CREATE, SESS, h, USERNAME, username)
|
||||
return h
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
@ -59,10 +49,11 @@ const (
|
||||
UA = "ua"
|
||||
)
|
||||
const (
|
||||
CHECK = "check"
|
||||
GRANT = "grant"
|
||||
LOGIN = "login"
|
||||
LOGOUT = "logout"
|
||||
EXPIRE = "expire"
|
||||
SESSID = "sessid"
|
||||
)
|
||||
const (
|
||||
SESS_CREATE = "sess.create"
|
||||
@ -70,15 +61,21 @@ const (
|
||||
const SESS = "sess"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
SESS: {Name: SESS, Help: "会话", Value: kit.Data(
|
||||
mdb.SHORT, "uniq", mdb.FIELD, "time,hash,userrole,username,usernick,ip,ua", mdb.EXPIRE, "720h",
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
SESS: {Name: "sess hash auto prunes", Help: "会话", Actions: ice.MergeAction(ice.Actions{
|
||||
mdb.CREATE: {Name: "create username", Help: "创建"},
|
||||
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.HashSelect(m, arg...)
|
||||
}},
|
||||
}})
|
||||
mdb.CREATE: {Name: "create username", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
|
||||
_sess_create(m, m.Option(USERNAME))
|
||||
}},
|
||||
CHECK: {Name: "check sessid", Help: "检查", Hand: func(m *ice.Message, arg ...string) {
|
||||
_sess_check(m, m.Option(SESSID))
|
||||
}},
|
||||
}, mdb.HashAction(mdb.SHORT, mdb.UNIQ, mdb.FIELD, "time,hash,userrole,username,usernick,ip,ua", mdb.EXPIRE, "720h"))},
|
||||
})
|
||||
}
|
||||
|
||||
func SessCreate(m *ice.Message, username string) string {
|
||||
return m.Option(ice.MSG_SESSID, m.Cmdx(SESS, mdb.CREATE, username))
|
||||
}
|
||||
func SessCheck(m *ice.Message, sessid string) bool {
|
||||
return m.Cmdy(SESS, CHECK, sessid).Option(ice.MSG_USERNAME) != ""
|
||||
}
|
||||
|
@ -43,8 +43,6 @@ func _totp_get(key string, num int, per int64) string {
|
||||
return kit.Format(kit.Format("%%0%dd", num), res%int64(math.Pow10(num)))
|
||||
}
|
||||
|
||||
func TOTP_GET(key string, num int, per int64) string { return _totp_get(key, num, per) }
|
||||
|
||||
const (
|
||||
SECRET = "secret"
|
||||
PERIOD = "period"
|
||||
@ -55,20 +53,15 @@ const (
|
||||
const TOTP = "totp"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
TOTP: {Name: TOTP, Help: "令牌", Value: kit.Data(
|
||||
mdb.SHORT, mdb.NAME, mdb.FIELD, "time,name,secret,period,number", mdb.LINK, "otpauth://totp/%s?secret=%s",
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
TOTP: {Name: "totp name auto create", Help: "令牌", Actions: ice.MergeAction(ice.Actions{
|
||||
mdb.CREATE: {Name: "create name=hi secret period=30 number=6", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
|
||||
if m.Option(SECRET) == "" { // 创建密钥
|
||||
m.Option(SECRET, _totp_gen(kit.Int64(m.Option(PERIOD))))
|
||||
}
|
||||
|
||||
m.Cmd(mdb.INSERT, TOTP, "", mdb.HASH, m.OptionSimple(mdb.NAME, SECRET, PERIOD, NUMBER))
|
||||
mdb.HashCreate(m, m.OptionSimple(mdb.NAME, SECRET, PERIOD, NUMBER))
|
||||
}},
|
||||
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
}, mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,name,secret,period,number", mdb.LINK, "otpauth://totp/%s?secret=%s")), Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.HashSelect(m.Spawn(), arg...).Tables(func(value ice.Maps) {
|
||||
if len(arg) > 0 {
|
||||
m.OptionFields(mdb.DETAIL)
|
||||
@ -86,5 +79,7 @@ func init() {
|
||||
}
|
||||
})
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
||||
func TOTP_GET(key string, num int, per int64) string { return _totp_get(key, num, per) }
|
||||
|
151
base/aaa/user.go
151
base/aaa/user.go
@ -4,95 +4,52 @@ import (
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
"shylinux.com/x/toolkits/logs"
|
||||
)
|
||||
|
||||
func _user_exists(m *ice.Message, name string) bool {
|
||||
return m.Richs(USER, nil, name, nil) != nil
|
||||
}
|
||||
func _user_login(m *ice.Message, name, word string) (ok bool) {
|
||||
if !_user_exists(m, name) {
|
||||
func _user_login(m *ice.Message, name, word string) {
|
||||
if m.Warn(name == "", ice.ErrNotValid, name) {
|
||||
return
|
||||
}
|
||||
if !mdb.HashSelectDetail(m, name, nil) {
|
||||
_user_create(m, VOID, name, word)
|
||||
}
|
||||
|
||||
m.Richs(USER, nil, name, func(key string, value ice.Map) {
|
||||
if ok = !m.Warn(word != "" && word != value[PASSWORD], ice.ErrNotRight); ok {
|
||||
m.Log_AUTH(
|
||||
USERROLE, m.Option(ice.MSG_USERROLE, value[USERROLE]),
|
||||
USERNAME, m.Option(ice.MSG_USERNAME, value[USERNAME]),
|
||||
USERNICK, m.Option(ice.MSG_USERNICK, value[USERNICK]),
|
||||
)
|
||||
_source := logs.FileLineMeta(logs.FileLine(-1, 3))
|
||||
mdb.HashSelectDetail(m, name, func(value ice.Map) {
|
||||
if m.Warn(word != "" && word != kit.Format(kit.Value(value, kit.Keys(mdb.EXTRA, PASSWORD))), ice.ErrNotRight) {
|
||||
return
|
||||
}
|
||||
m.Log_AUTH(
|
||||
USERROLE, m.Option(ice.MSG_USERROLE, value[USERROLE]),
|
||||
USERNAME, m.Option(ice.MSG_USERNAME, value[USERNAME]),
|
||||
USERNICK, m.Option(ice.MSG_USERNICK, value[USERNICK]),
|
||||
_source,
|
||||
)
|
||||
})
|
||||
return ok
|
||||
}
|
||||
func _user_create(m *ice.Message, role, name, word string) {
|
||||
if name == "" {
|
||||
func _user_create(m *ice.Message, name, word string, arg ...string) {
|
||||
if m.Warn(name == "", ice.ErrNotValid, name) {
|
||||
return
|
||||
}
|
||||
if word == "" {
|
||||
if m.Richs(USER, nil, name, func(key string, value ice.Map) {
|
||||
word = kit.Format(value[PASSWORD])
|
||||
}) == nil {
|
||||
word = kit.Hashs()
|
||||
}
|
||||
word = m.CmdAppend(USER, name, PASSWORD)
|
||||
}
|
||||
m.Rich(USER, nil, kit.Dict(USERROLE, role, USERNAME, name, PASSWORD, word))
|
||||
if word == "" {
|
||||
word = kit.Hashs()
|
||||
}
|
||||
mdb.HashCreate(m, USERNAME, name, PASSWORD, word, arg)
|
||||
m.Event(USER_CREATE, USER, name)
|
||||
}
|
||||
func _user_search(m *ice.Message, name, text string) {
|
||||
m.Richs(USER, nil, mdb.FOREACH, func(key string, value ice.Map) {
|
||||
if value = kit.GetMeta(value); name == "" || name == value[USERNAME] {
|
||||
m.PushSearch(kit.SimpleKV("", value[USERROLE], value[USERNAME], value[USERNICK]), value)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func UserRoot(m *ice.Message, arg ...string) *ice.Message { // password username userrole
|
||||
username := m.Option(ice.MSG_USERNAME, kit.Select(ice.Info.UserName, arg, 1))
|
||||
userrole := m.Option(ice.MSG_USERROLE, kit.Select(ROOT, arg, 2))
|
||||
if len(arg) > 0 {
|
||||
_user_create(m, userrole, username, kit.Select("", arg, 0))
|
||||
ice.Info.UserName = username
|
||||
}
|
||||
return m
|
||||
}
|
||||
func UserRole(m *ice.Message, username ice.Any) (role string) {
|
||||
if role = VOID; username == ice.Info.UserName {
|
||||
return ROOT
|
||||
}
|
||||
if m.Richs(USER, nil, kit.Format(username), func(key string, value ice.Map) {
|
||||
role = kit.Format(kit.GetMeta(value)[USERROLE])
|
||||
}) == nil && kit.Format(username) == m.Option(ice.MSG_USERNAME) {
|
||||
return m.Option(ice.MSG_USERROLE)
|
||||
}
|
||||
return
|
||||
}
|
||||
func UserNick(m *ice.Message, username ice.Any) (nick string) {
|
||||
if m.Richs(USER, nil, kit.Format(username), func(key string, value ice.Map) {
|
||||
nick = kit.Format(kit.GetMeta(value)[USERNICK])
|
||||
}) == nil && kit.Format(username) == m.Option(ice.MSG_USERNAME) {
|
||||
return m.Option(ice.MSG_USERNICK)
|
||||
}
|
||||
return
|
||||
}
|
||||
func UserZone(m *ice.Message, username ice.Any) (zone string) {
|
||||
m.Richs(USER, nil, kit.Format(username), func(key string, value ice.Map) {
|
||||
zone = kit.Format(kit.GetMeta(value)[USERZONE])
|
||||
})
|
||||
return
|
||||
}
|
||||
func UserLogin(m *ice.Message, username, password string) bool {
|
||||
return _user_login(m, username, password)
|
||||
}
|
||||
|
||||
const (
|
||||
BACKGROUND = "background"
|
||||
|
||||
AVATAR = "avatar"
|
||||
GENDER = "gender"
|
||||
MOBILE = "mobile"
|
||||
EMAIL = "email"
|
||||
|
||||
BACKGROUND = "background"
|
||||
|
||||
CITY = "city"
|
||||
COUNTRY = "country"
|
||||
LANGUAGE = "language"
|
||||
@ -114,24 +71,50 @@ const (
|
||||
const USER = "user"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
USER: {Name: USER, Help: "用户", Value: kit.Data(
|
||||
mdb.SHORT, USERNAME, mdb.FIELD, "time,userrole,username,usernick,userzone",
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
USER: {Name: "user username auto create", Help: "用户", Actions: ice.MergeAction(ice.Actions{
|
||||
mdb.SEARCH: {Name: "search type name text", Help: "搜索", Hand: func(m *ice.Message, arg ...string) {
|
||||
if arg[0] == USER {
|
||||
_user_search(m, arg[1], kit.Select("", arg, 2))
|
||||
}
|
||||
mdb.HashSelectSearch(m, arg)
|
||||
}},
|
||||
mdb.CREATE: {Name: "create userrole=void,tech username password", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
|
||||
if !_user_exists(m, m.Option(USERNAME)) {
|
||||
_user_create(m, m.Option(USERROLE), m.Option(USERNAME), m.Option(PASSWORD))
|
||||
}
|
||||
mdb.CREATE: {Name: "create username password userrole=void,tech", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
|
||||
_user_create(m, m.Option(USERNAME), m.Option(PASSWORD), m.OptionSimple(USERROLE)...)
|
||||
}},
|
||||
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.HashSelect(m, arg...)
|
||||
}},
|
||||
}})
|
||||
LOGIN: {Name: "login username password", Help: "登录", Hand: func(m *ice.Message, arg ...string) {
|
||||
_user_login(m, m.Option(USERNAME), m.Option(PASSWORD))
|
||||
}},
|
||||
}, mdb.HashAction(mdb.SHORT, USERNAME, mdb.FIELD, "time,userrole,username,usernick,userzone"))},
|
||||
})
|
||||
}
|
||||
|
||||
func UserRoot(m *ice.Message, arg ...string) *ice.Message { // password username userrole
|
||||
username := m.Option(ice.MSG_USERNAME, kit.Select(ice.Info.UserName, arg, 1))
|
||||
userrole := m.Option(ice.MSG_USERROLE, kit.Select(ROOT, arg, 2))
|
||||
if len(arg) > 0 {
|
||||
m.Cmd(USER, mdb.CREATE, username, kit.Select("", arg, 0), userrole)
|
||||
ice.Info.UserName = username
|
||||
}
|
||||
return m
|
||||
}
|
||||
func UserRole(m *ice.Message, username ice.Any) (role string) {
|
||||
if role = VOID; username == ice.Info.UserName {
|
||||
return ROOT
|
||||
}
|
||||
return UserInfo(m, username, USERROLE, ice.MSG_USERROLE)
|
||||
}
|
||||
func UserNick(m *ice.Message, username ice.Any) (nick string) {
|
||||
return UserInfo(m, username, USERNICK, ice.MSG_USERNICK)
|
||||
}
|
||||
func UserZone(m *ice.Message, username ice.Any) (zone string) {
|
||||
return UserInfo(m, username, USERZONE, ice.MSG_USERZONE)
|
||||
}
|
||||
func UserInfo(m *ice.Message, name ice.Any, key, meta string) (value string) {
|
||||
if m.Cmd(USER, name).Tables(func(val ice.Maps) {
|
||||
value = val[key]
|
||||
}).Length() == 0 && kit.Format(name) == m.Option(ice.MSG_USERNAME) {
|
||||
return m.Option(meta)
|
||||
}
|
||||
return
|
||||
}
|
||||
func UserLogin(m *ice.Message, username, password string) bool {
|
||||
return m.Cmdy(USER, LOGIN, username, password).Option(ice.MSG_USERNAME) != ""
|
||||
}
|
||||
|
@ -6,63 +6,67 @@ import (
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/ctx"
|
||||
"shylinux.com/x/icebergs/base/gdb"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
func _daemon_exec(m *ice.Message, cmd *exec.Cmd) {
|
||||
if r, ok := m.Optionv(CMD_INPUT).(io.Reader); ok {
|
||||
cmd.Stdin = r
|
||||
cmd.Stdin = r // 输入流
|
||||
}
|
||||
if w := _system_out(m, CMD_OUTPUT); w != nil {
|
||||
cmd.Stdout = w
|
||||
cmd.Stderr = w
|
||||
cmd.Stdout, cmd.Stderr = w, w
|
||||
}
|
||||
if w := _system_out(m, CMD_ERRPUT); w != nil {
|
||||
cmd.Stderr = w
|
||||
}
|
||||
|
||||
// 启动进程
|
||||
h := mdb.HashCreate(m,
|
||||
STATUS, START, ice.CMD, kit.Join(cmd.Args, ice.SP),
|
||||
DIR, cmd.Dir, ENV, kit.Select("", cmd.Env),
|
||||
m.OptionSimple(CMD_OUTPUT, CMD_ERRPUT, mdb.CACHE_CLEAR_ON_EXIT),
|
||||
).Result()
|
||||
|
||||
// 启动服务
|
||||
if e := cmd.Start(); m.Warn(e, ice.ErrNotStart, cmd.Args) {
|
||||
mdb.HashModify(m, h, STATUS, ERROR, ERROR, e)
|
||||
return // 启动失败
|
||||
}
|
||||
mdb.HashSelectUpdate(m, h, func(value ice.Map) { value[PID] = cmd.Process.Pid })
|
||||
m.Echo("%d", cmd.Process.Pid)
|
||||
|
||||
m.Go(func() {
|
||||
h := m.Cmdx(mdb.INSERT, DAEMON, "", mdb.HASH,
|
||||
STATUS, START, ice.CMD, kit.Join(cmd.Args, ice.SP),
|
||||
PID, cmd.Process.Pid, DIR, cmd.Dir, ENV, kit.Select("", cmd.Env),
|
||||
m.OptionSimple(CMD_OUTPUT, CMD_ERRPUT, mdb.CACHE_CLEAR_ON_EXIT),
|
||||
)
|
||||
|
||||
m.Go(func() { // 等待结果
|
||||
if e := cmd.Wait(); !m.Warn(e, ice.ErrNotStart, cmd.Args) && cmd.ProcessState.ExitCode() == 0 {
|
||||
m.Cost(CODE, cmd.ProcessState.ExitCode(), ctx.ARGS, cmd.Args)
|
||||
m.Cmd(mdb.MODIFY, DAEMON, "", mdb.HASH, mdb.HASH, h, STATUS, STOP)
|
||||
mdb.HashModify(m, mdb.HASH, h, STATUS, STOP)
|
||||
} else {
|
||||
if m.Conf(DAEMON, kit.Keys(mdb.HASH, h, kit.Keym(STATUS))) == START {
|
||||
m.Cmd(mdb.MODIFY, DAEMON, "", mdb.HASH, mdb.HASH, h, STATUS, ERROR, ERROR, e)
|
||||
}
|
||||
mdb.HashSelectUpdate(m, h, func(value ice.Map) {
|
||||
if value[STATUS] == START {
|
||||
value[STATUS], value[ERROR] = ERROR, e
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
status := mdb.HashSelectFields(m, h, STATUS)
|
||||
switch m.Sleep300ms(); cb := m.OptionCB(DAEMON).(type) {
|
||||
case func(string) bool:
|
||||
if !cb(m.Conf(DAEMON, kit.Keys(mdb.HASH, h, kit.Keym(STATUS)))) {
|
||||
if !cb(status) { // 拉起服务
|
||||
m.Cmdy(DAEMON, cmd.Path, cmd.Args)
|
||||
}
|
||||
case func(string):
|
||||
cb(m.Conf(DAEMON, kit.Keys(mdb.HASH, h, kit.Keym(STATUS))))
|
||||
cb(status)
|
||||
case func():
|
||||
cb()
|
||||
case nil:
|
||||
default:
|
||||
m.Error(true, ice.ErrNotImplement)
|
||||
m.ErrorNotImplement(cb)
|
||||
}
|
||||
|
||||
for _, p := range kit.Simple(CMD_INPUT, CMD_OUTPUT, CMD_ERRPUT) {
|
||||
kit.Close(m.Optionv(p))
|
||||
}
|
||||
})
|
||||
m.Sleep("100ms")
|
||||
}
|
||||
|
||||
const (
|
||||
@ -87,10 +91,10 @@ const (
|
||||
RELOAD = "reload"
|
||||
RESTART = "restart"
|
||||
|
||||
START = "start"
|
||||
STOP = "stop"
|
||||
OPEN = "open"
|
||||
CLOSE = "close"
|
||||
START = "start"
|
||||
STOP = "stop"
|
||||
BEGIN = "begin"
|
||||
END = "end"
|
||||
|
||||
@ -99,61 +103,51 @@ const (
|
||||
BACK = "back"
|
||||
FROM = "from"
|
||||
MAIN = "main"
|
||||
KILL = "kill"
|
||||
)
|
||||
|
||||
const DAEMON = "daemon"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
DAEMON: {Name: DAEMON, Help: "守护进程", Value: kit.Data(
|
||||
nfs.PATH, ice.USR_LOCAL_DAEMON, mdb.FIELD, "time,hash,status,pid,cmd,dir,env",
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
DAEMON: {Name: "daemon hash auto start prunes", Help: "守护进程", Actions: ice.MergeAction(ice.Actions{
|
||||
ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmd(mdb.PRUNES, DAEMON, "", mdb.HASH, mdb.CACHE_CLEAR_ON_EXIT, ice.TRUE)
|
||||
mdb.HashPrunesValue(m, mdb.CACHE_CLEAR_ON_EXIT, ice.TRUE)
|
||||
}},
|
||||
mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.OptionFields(m.Config(mdb.FIELD))
|
||||
m.Cmdy(mdb.PRUNES, DAEMON, "", mdb.HASH, STATUS, STOP)
|
||||
m.Cmdy(mdb.PRUNES, DAEMON, "", mdb.HASH, STATUS, ERROR)
|
||||
mdb.HashPrunesValue(m, STATUS, ERROR)
|
||||
mdb.HashPrunesValue(m, STATUS, STOP)
|
||||
}},
|
||||
START: {Name: "start cmd env dir", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Option(CMD_DIR, m.Option(DIR))
|
||||
m.Option(CMD_ENV, kit.Split(m.Option(ENV), " ="))
|
||||
m.Cmdy(DAEMON, kit.Split(m.Option(ice.CMD)))
|
||||
_daemon_exec(m, _system_cmd(m, kit.Split(m.Option(ice.CMD))...))
|
||||
}},
|
||||
RESTART: {Name: "restart", Help: "重启", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(DAEMON, STOP).Sleep3s().Cmdy(DAEMON, START)
|
||||
m.Cmdy("", STOP).Sleep3s().Cmdy("", START)
|
||||
}},
|
||||
STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.OptionFields(m.Config(mdb.FIELD))
|
||||
m.Cmd(mdb.SELECT, DAEMON, "", mdb.HASH, m.OptionSimple(mdb.HASH)).Tables(func(value ice.Maps) {
|
||||
m.Cmd(mdb.MODIFY, DAEMON, "", mdb.HASH, m.OptionSimple(mdb.HASH), STATUS, STOP)
|
||||
m.Cmdy(SYSTEM, KILL, value[PID])
|
||||
mdb.HashSelect(m, m.Option(mdb.HASH)).Tables(func(value ice.Maps) {
|
||||
mdb.HashModify(m, m.OptionSimple(mdb.HASH), STATUS, STOP)
|
||||
m.Cmd(gdb.SIGNAL, gdb.KILL, value[PID])
|
||||
})
|
||||
if IsSuccess(m) {
|
||||
m.SetAppend()
|
||||
}
|
||||
}},
|
||||
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.HashSelect(m, arg...).Set(ctx.ACTION).Tables(func(value ice.Maps) {
|
||||
}, mdb.HashAction(mdb.FIELD, "time,hash,status,pid,cmd,dir,env")), Hand: func(m *ice.Message, arg ...string) {
|
||||
if mdb.HashSelect(m, arg...).Tables(func(value ice.Maps) {
|
||||
switch value[STATUS] {
|
||||
case START:
|
||||
m.PushButton(RESTART, STOP)
|
||||
default:
|
||||
m.PushButton(mdb.REMOVE)
|
||||
}
|
||||
})
|
||||
|
||||
if len(arg) == 0 || m.Length() > 0 {
|
||||
}); len(arg) == 0 || m.Length() > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if len(arg) == 1 {
|
||||
arg = kit.Split(arg[0])
|
||||
}
|
||||
_daemon_exec(m, _system_cmd(m, arg...))
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -5,18 +5,12 @@ import (
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/aaa"
|
||||
"shylinux.com/x/icebergs/base/gdb"
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
"shylinux.com/x/toolkits/logs"
|
||||
)
|
||||
|
||||
func _forever_kill(m *ice.Message, s string) {
|
||||
if p := m.Cmdx(nfs.CAT, m.Conf("gdb.signal", kit.Keym(nfs.PATH))); p != "" {
|
||||
if s != "" {
|
||||
m.Cmd(SYSTEM, "kill", "-s", s, p)
|
||||
}
|
||||
m.Echo(p)
|
||||
}
|
||||
}
|
||||
func BinPath(arg ...string) string {
|
||||
return kit.Join(kit.Simple(arg, kit.Path(ice.BIN), kit.Path(ice.USR_LOCAL_BIN), kit.Path(ice.USR_LOCAL_GO_BIN), kit.Env(PATH)), ice.DF)
|
||||
}
|
||||
@ -24,16 +18,11 @@ func BinPath(arg ...string) string {
|
||||
const FOREVER = "forever"
|
||||
|
||||
func init() {
|
||||
const SERVE = "serve"
|
||||
const RESTART = "restart"
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
FOREVER: {Name: "forever auto", Help: "启动", Actions: ice.Actions{
|
||||
RESTART: {Name: "restart", Help: "重启", Hand: func(m *ice.Message, arg ...string) {
|
||||
_forever_kill(m, "INT")
|
||||
}},
|
||||
SERVE: {Name: "serve", Help: "服务", Hand: func(m *ice.Message, arg ...string) {
|
||||
gdb.START: {Name: "start", Help: "服务", Hand: func(m *ice.Message, arg ...string) {
|
||||
env := []string{PATH, BinPath(), HOME, kit.Select(kit.Path(""), os.Getenv(HOME))}
|
||||
for _, k := range []string{TERM, SHELL, CTX_SHY, CTX_DEV, CTX_OPS, CTX_ARG, CTX_PID, CTX_USER, CTX_SHARE, CTX_RIVER, CTX_DAEMON} {
|
||||
for _, k := range ENV_LIST {
|
||||
if kit.Env(k) != "" {
|
||||
env = append(env, k, kit.Env(k))
|
||||
}
|
||||
@ -49,24 +38,27 @@ func init() {
|
||||
|
||||
m.Cmd(FOREVER, STOP)
|
||||
m.Cmdy(FOREVER, kit.Select(os.Args[0], nfs.PWD+ice.BIN_ICE_BIN, kit.FileExists(ice.BIN_ICE_BIN)),
|
||||
SERVE, START, ice.DEV, "", aaa.USERNAME, aaa.ROOT, aaa.PASSWORD, aaa.ROOT, arg)
|
||||
"serve", START, ice.DEV, "", aaa.USERNAME, aaa.ROOT, aaa.PASSWORD, aaa.ROOT, arg)
|
||||
}},
|
||||
STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) {
|
||||
_forever_kill(m, "QUIT")
|
||||
gdb.RESTART: {Name: "restart", Help: "重启", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmd(gdb.SIGNAL, gdb.RESTART)
|
||||
}},
|
||||
gdb.STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmd(gdb.SIGNAL, gdb.STOP)
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) == 0 {
|
||||
_forever_kill(m, "")
|
||||
m.Cmdy(RUNTIME, BOOTINFO)
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
println(kit.Format("%s run %s", kit.Now(), kit.Join(arg, ice.SP)))
|
||||
logs.Println("run %s", kit.Join(arg, ice.SP))
|
||||
if m.Sleep("1s"); IsSuccess(m.Cmd(SYSTEM, arg)) {
|
||||
println(kit.Format("%s exit", kit.Now()))
|
||||
return
|
||||
logs.Println("exit")
|
||||
break
|
||||
}
|
||||
}
|
||||
}}},
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
@ -8,18 +9,9 @@ import (
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
func IsAlpine(m *ice.Message, arg ...string) bool {
|
||||
if strings.Contains(m.Conf(RUNTIME, "host.OSID"), ALPINE) {
|
||||
if len(arg) > 0 {
|
||||
m.Cmd(MIRRORS, mdb.CREATE, "cli", arg[0], "cmd", arg[1])
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const (
|
||||
OSID = "OSID"
|
||||
CMD = "cmd"
|
||||
OSID = "osid"
|
||||
ALPINE = "alpine"
|
||||
CENTOS = "centos"
|
||||
UBUNTU = "ubuntu"
|
||||
@ -28,31 +20,49 @@ const (
|
||||
const MIRRORS = "mirrors"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
MIRRORS: {Name: "mirrors cli auto", Help: "软件镜像", Actions: ice.MergeAction(ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Go(func() {
|
||||
m.Sleep("1s")
|
||||
IsAlpine(m, "curl", "system apk add curl")
|
||||
IsAlpine(m, "make", "system apk add make")
|
||||
IsAlpine(m, "gcc", "system apk add gcc")
|
||||
IsAlpine(m, "vim", "system apk add vim")
|
||||
IsAlpine(m, "tmux", "system apk add tmux")
|
||||
m.Conf(m.PrefixKey(), kit.Keys(mdb.HASH), "")
|
||||
IsAlpine(m, "curl")
|
||||
IsAlpine(m, "make")
|
||||
IsAlpine(m, "gcc")
|
||||
IsAlpine(m, "vim")
|
||||
IsAlpine(m, "tmux")
|
||||
|
||||
if IsAlpine(m, "git", "system apk add git"); !IsAlpine(m, "go", "system apk add git go") {
|
||||
m.Cmd(MIRRORS, mdb.CREATE, kit.SimpleKV("cli,cmd", "go", "install download https://golang.google.cn/dl/go1.15.5.linux-amd64.tar.gz usr/local"))
|
||||
IsAlpine(m, "git")
|
||||
mdb.ZoneInsert(m, CLI, "go", CMD, kit.Format("install download https://golang.google.cn/dl/go1.15.5.%s-%s.tar.gz usr/local", runtime.GOOS, runtime.GOARCH))
|
||||
|
||||
IsAlpine(m, "node", "nodejs")
|
||||
IsAlpine(m, "java", "openjdk8")
|
||||
IsAlpine(m, "javac", "openjdk8")
|
||||
IsAlpine(m, "mvn", "openjdk8 maven")
|
||||
IsAlpine(m, "python", "python2")
|
||||
IsAlpine(m, "python2")
|
||||
IsAlpine(m, "python3")
|
||||
}},
|
||||
mdb.INSERT: {Name: "insert cli osid cmd", Help: "添加"},
|
||||
CMD: {Name: "cmd cli osid", Help: "安装", Hand: func(m *ice.Message, arg ...string) {
|
||||
osid := kit.Select(m.Conf(RUNTIME, kit.Keys(HOST, OSID)), m.Option(OSID))
|
||||
mdb.ZoneSelectCB(m, m.Option(CLI), func(value ice.Map) {
|
||||
if osid != "" && strings.Contains(osid, kit.Format(value[OSID])) {
|
||||
m.Cmdy(kit.Split(kit.Format(value[CMD])))
|
||||
}
|
||||
|
||||
IsAlpine(m, "node", "system apk add nodejs")
|
||||
IsAlpine(m, "python", "system apk add python2")
|
||||
IsAlpine(m, "python2", "system apk add python2")
|
||||
IsAlpine(m, "python3", "system apk add python3")
|
||||
IsAlpine(m, "mvn", "system apk add openjdk8 maven")
|
||||
IsAlpine(m, "javac", "system apk add openjdk8")
|
||||
IsAlpine(m, "java", "system apk add openjdk8")
|
||||
})
|
||||
}},
|
||||
mdb.CREATE: {Name: "create cli cmd", Help: "创建"},
|
||||
}, mdb.HashAction(mdb.SHORT, "cli", mdb.FIELD, "time,cli,cmd"))},
|
||||
}})
|
||||
ALPINE: {Name: "alpine cli cmd", Help: "安装", Hand: func(m *ice.Message, arg ...string) {
|
||||
IsAlpine(m, arg...)
|
||||
}},
|
||||
}, mdb.ZoneAction(mdb.SHORT, CLI, mdb.FIELD, "time,id,osid,cmd"))},
|
||||
})
|
||||
}
|
||||
|
||||
func IsAlpine(m *ice.Message, arg ...string) bool {
|
||||
if strings.Contains(m.Conf(RUNTIME, kit.Keys(HOST, OSID)), ALPINE) {
|
||||
if len(arg) > 0 {
|
||||
mdb.ZoneInsert(m, CLI, arg[0], OSID, ALPINE, CMD, "system apk add "+kit.Select(arg[0], arg, 1))
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ func _parse_color(str string) color.Color {
|
||||
for k := range _trans_web {
|
||||
list = append(list, k)
|
||||
}
|
||||
kit.Sort(list)
|
||||
str = list[rand.Intn(len(list))]
|
||||
}
|
||||
if strings.HasPrefix(str, "#") {
|
||||
@ -93,24 +94,12 @@ func _qrcode_web(m *ice.Message, text string) {
|
||||
}
|
||||
}
|
||||
|
||||
func Color(m *ice.Message, c string, str ice.Any) string {
|
||||
wrap, color := `<span style="color:%s">%v</span>`, c
|
||||
if m.IsCliUA() {
|
||||
wrap, color = "\033[3%sm%v\033[0m", _parse_cli_color(c)
|
||||
}
|
||||
return fmt.Sprintf(wrap, color, str)
|
||||
}
|
||||
func ColorRed(m *ice.Message, str ice.Any) string { return Color(m, RED, str) }
|
||||
func ColorGreen(m *ice.Message, str ice.Any) string { return Color(m, GREEN, str) }
|
||||
func ColorYellow(m *ice.Message, str ice.Any) string { return Color(m, YELLOW, str) }
|
||||
|
||||
const (
|
||||
FG = "fg"
|
||||
BG = "bg"
|
||||
SIZE = "size"
|
||||
|
||||
FG = "fg"
|
||||
BG = "bg"
|
||||
DARK = 255
|
||||
LIGHT = 127
|
||||
SIZE = "size"
|
||||
)
|
||||
const (
|
||||
COLOR = "color"
|
||||
@ -129,7 +118,7 @@ const (
|
||||
const QRCODE = "qrcode"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
QRCODE: {Name: "qrcode text@key fg@key bg@key size auto", Help: "二维码", Actions: ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
ice.AddRender(ice.RENDER_QRCODE, func(m *ice.Message, cmd string, args ...ice.Any) string {
|
||||
@ -138,26 +127,32 @@ func init() {
|
||||
}},
|
||||
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {
|
||||
switch arg[0] {
|
||||
case "text":
|
||||
m.Push("text", "hi")
|
||||
m.Push("text", "hello")
|
||||
m.Push("text", "world")
|
||||
case "fg", "bg":
|
||||
m.Push("color", "red")
|
||||
m.Push("color", "green")
|
||||
m.Push("color", "blue")
|
||||
case mdb.TEXT:
|
||||
m.Push(arg[0], "hi", "hello", "world")
|
||||
case FG, BG:
|
||||
m.Push(arg[0], RED, GREEN, BLUE)
|
||||
}
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Option(SIZE, kit.Select("240", arg, 3))
|
||||
m.Option(BG, kit.Select(WHITE, arg, 2))
|
||||
m.Option(FG, kit.Select(BLUE, arg, 1))
|
||||
|
||||
if m.IsCliUA() {
|
||||
_qrcode_cli(m, kit.Select(ice.Info.Domain, arg, 0))
|
||||
_qrcode_cli(m, kit.Select(kit.Select(ice.Info.Make.Domain, ice.Info.Domain), arg, 0))
|
||||
} else {
|
||||
_qrcode_web(m, kit.Select(m.Option(ice.MSG_USERWEB), arg, 0))
|
||||
}
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
||||
func Color(m *ice.Message, c string, str ice.Any) string {
|
||||
wrap, color := `<span style="color:%s">%v</span>`, c
|
||||
if m.IsCliUA() {
|
||||
wrap, color = "\033[3%sm%v\033[0m", _parse_cli_color(c)
|
||||
}
|
||||
return fmt.Sprintf(wrap, color, str)
|
||||
}
|
||||
func ColorRed(m *ice.Message, str ice.Any) string { return Color(m, RED, str) }
|
||||
func ColorGreen(m *ice.Message, str ice.Any) string { return Color(m, GREEN, str) }
|
||||
func ColorYellow(m *ice.Message, str ice.Any) string { return Color(m, YELLOW, str) }
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/aaa"
|
||||
"shylinux.com/x/icebergs/base/ctx"
|
||||
"shylinux.com/x/icebergs/base/gdb"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
@ -25,42 +26,49 @@ func _runtime_init(m *ice.Message) {
|
||||
m.Conf(RUNTIME, kit.Keys(HOST, GOOS), runtime.GOOS)
|
||||
m.Conf(RUNTIME, kit.Keys(HOST, PID), os.Getpid())
|
||||
m.Conf(RUNTIME, kit.Keys(HOST, HOME), kit.Env(HOME))
|
||||
m.Conf(RUNTIME, kit.Keys(HOST, MAXPROCS), runtime.GOMAXPROCS(0))
|
||||
|
||||
// 启动信息 boot
|
||||
if name, e := os.Hostname(); e == nil {
|
||||
m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME), kit.Select(name, kit.Env("HOSTNAME")))
|
||||
// 启动目录 boot
|
||||
m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME), kit.Env("HOSTNAME"))
|
||||
if name, e := os.Hostname(); e == nil && name != "" {
|
||||
m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME), name)
|
||||
}
|
||||
if name, e := os.Getwd(); e == nil {
|
||||
name = path.Base(kit.Select(name, kit.Env("PWD")))
|
||||
name = kit.Slice(strings.Split(name, ice.PS), -1)[0]
|
||||
name = kit.Slice(strings.Split(name, "\\"), -1)[0]
|
||||
m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME), name)
|
||||
m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME), path.Base(kit.Env("PWD")))
|
||||
if name, e := os.Getwd(); e == nil && name != "" {
|
||||
m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME), path.Base(name))
|
||||
}
|
||||
|
||||
m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME), kit.Select(kit.UserName(), kit.Select(kit.Env("WORKSPACE_GIT_USERNAME"), kit.Env(CTX_USER))))
|
||||
ice.Info.HostName = m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME))
|
||||
ice.Info.PathName = m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME))
|
||||
ice.Info.UserName = m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME))
|
||||
aaa.UserRoot(ice.Pulse)
|
||||
|
||||
// 启动次数 boot
|
||||
// 启动程序 boot
|
||||
m.Conf(RUNTIME, kit.Keys(BOOT, mdb.COUNT), kit.Int(m.Conf(RUNTIME, kit.Keys(BOOT, mdb.COUNT)))+1)
|
||||
bin := _system_find(m, os.Args[0])
|
||||
m.Conf(RUNTIME, kit.Keys(BOOT, ice.BIN), bin)
|
||||
if s, e := os.Stat(bin); e == nil {
|
||||
m.Conf(RUNTIME, kit.Keys(BOOT, "size"), kit.FmtSize(s.Size()))
|
||||
m.Conf(RUNTIME, kit.Keys(BOOT, nfs.SIZE), kit.FmtSize(s.Size()))
|
||||
if f, e := os.Open(bin); e == nil {
|
||||
defer f.Close()
|
||||
m.Conf(RUNTIME, kit.Keys(BOOT, "hash"), kit.Hashs(f))
|
||||
m.Conf(RUNTIME, kit.Keys(BOOT, mdb.HASH), kit.Hashs(f))
|
||||
}
|
||||
}
|
||||
|
||||
// 环境变量 conf
|
||||
for _, k := range []string{CTX_SHY, CTX_DEV, CTX_OPS, CTX_ARG, CTX_PID, CTX_USER, CTX_SHARE, CTX_RIVER, CTX_DAEMON} {
|
||||
m.Conf(RUNTIME, kit.Keys(CONF, k), kit.Env(k))
|
||||
for _, k := range ENV_LIST {
|
||||
switch m.Conf(RUNTIME, kit.Keys(CONF, k), kit.Env(k)); k {
|
||||
case CTX_PID:
|
||||
ice.Info.PidPath = kit.Select("var/run/ice.pid", kit.Env(k))
|
||||
case CTX_SHARE:
|
||||
ice.Info.CtxShare = kit.Env(k)
|
||||
case CTX_RIVER:
|
||||
ice.Info.CtxRiver = kit.Env(k)
|
||||
}
|
||||
}
|
||||
|
||||
osid := ""
|
||||
// 系统版本 osid
|
||||
osid := runtime.GOOS
|
||||
m.Cmd(nfs.CAT, "/etc/os-release", func(text string) {
|
||||
if ls := kit.Split(text, "="); len(ls) > 1 {
|
||||
switch ls[0] {
|
||||
@ -119,11 +127,11 @@ const (
|
||||
WINDOWS = "windows"
|
||||
)
|
||||
const (
|
||||
SHELL = "SHELL"
|
||||
TERM = "TERM"
|
||||
USER = "USER"
|
||||
HOME = "HOME"
|
||||
PATH = "PATH"
|
||||
HOME = "HOME"
|
||||
USER = "USER"
|
||||
TERM = "TERM"
|
||||
SHELL = "SHELL"
|
||||
)
|
||||
const (
|
||||
CTX_SHY = "ctx_shy"
|
||||
@ -131,9 +139,9 @@ const (
|
||||
CTX_OPS = "ctx_ops"
|
||||
CTX_POD = "ctx_pod"
|
||||
CTX_ARG = "ctx_arg"
|
||||
CTX_PID = "ctx_pid"
|
||||
CTX_LOG = "ctx_log"
|
||||
|
||||
CTX_PID = "ctx_pid"
|
||||
CTX_LOG = "ctx_log"
|
||||
CTX_USER = "ctx_user"
|
||||
CTX_SHARE = "ctx_share"
|
||||
CTX_RIVER = "ctx_river"
|
||||
@ -141,37 +149,37 @@ const (
|
||||
|
||||
MAKE_DOMAIN = "make.domain"
|
||||
)
|
||||
|
||||
var ENV_LIST = []string{
|
||||
TERM, SHELL, CTX_SHY, CTX_DEV, CTX_OPS, CTX_ARG, CTX_PID, CTX_USER, CTX_SHARE, CTX_RIVER, CTX_DAEMON,
|
||||
}
|
||||
|
||||
const (
|
||||
HOSTNAME = "hostname"
|
||||
PATHNAME = "pathname"
|
||||
USERNAME = "username"
|
||||
)
|
||||
const (
|
||||
MAXPROCS = "maxprocs"
|
||||
IFCONFIG = "ifconfig"
|
||||
HOSTINFO = "hostinfo"
|
||||
USERINFO = "userinfo"
|
||||
PROCINFO = "procinfo"
|
||||
PROCKILL = "prockill"
|
||||
BOOTINFO = "bootinfo"
|
||||
DISKINFO = "diskinfo"
|
||||
BOOTINFO = "bootinfo"
|
||||
MAXPROCS = "maxprocs"
|
||||
)
|
||||
const RUNTIME = "runtime"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
RUNTIME: {Name: RUNTIME, Help: "运行环境", Value: kit.Dict()},
|
||||
}, Commands: ice.Commands{
|
||||
RUNTIME: {Name: "runtime info=ifconfig,hostinfo,hostname,userinfo,procinfo,bootinfo,diskinfo,env,file,route auto", Help: "运行环境", Actions: ice.Actions{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
RUNTIME: {Name: "runtime info=ifconfig,hostinfo,hostname,userinfo,procinfo,diskinfo,bootinfo,api,cli,cmd,env auto", Help: "运行环境", Actions: ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmd(RUNTIME, MAXPROCS, "1")
|
||||
_runtime_init(m)
|
||||
}},
|
||||
MAXPROCS: {Name: "maxprocs", Help: "最大并发", Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) > 0 {
|
||||
runtime.GOMAXPROCS(kit.Int(m.Conf(RUNTIME, kit.Keys(HOST, "GOMAXPROCS"), kit.Select("1", arg, 0))))
|
||||
cs := m.Target().Configs
|
||||
if _, ok := cs[RUNTIME]; !ok {
|
||||
cs[RUNTIME] = &ice.Config{Value: kit.Dict()}
|
||||
}
|
||||
m.Echo("%d", runtime.GOMAXPROCS(0))
|
||||
_runtime_init(m)
|
||||
}},
|
||||
IFCONFIG: {Name: "ifconfig", Help: "网卡配置", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy("tcp.host")
|
||||
@ -193,13 +201,37 @@ func init() {
|
||||
m.StatusTimeCount()
|
||||
}},
|
||||
PROCKILL: {Name: "prockill", Help: "结束进程", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(SYSTEM, KILL, m.Option("PID"))
|
||||
m.Cmdy(gdb.SIGNAL, gdb.STOP, m.Option("PID"))
|
||||
m.ProcessRefresh30ms()
|
||||
}},
|
||||
DISKINFO: {Name: "diskinfo", Help: "磁盘信息", Hand: func(m *ice.Message, arg ...string) {
|
||||
_runtime_diskinfo(m)
|
||||
}},
|
||||
"env": {Name: "env", Help: "环境变量", Hand: func(m *ice.Message, arg ...string) {
|
||||
MAXPROCS: {Name: "maxprocs", Help: "最大并发", Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) > 0 {
|
||||
runtime.GOMAXPROCS(kit.Int(m.Conf(RUNTIME, kit.Keys(HOST, MAXPROCS), kit.Select("1", arg, 0))))
|
||||
}
|
||||
m.Echo("%d", runtime.GOMAXPROCS(0))
|
||||
}},
|
||||
API: {Name: "api", Help: "接口命令", Hand: func(m *ice.Message, arg ...string) {
|
||||
for k, v := range ice.Info.Route {
|
||||
m.Push(nfs.PATH, k)
|
||||
m.Push(nfs.FILE, v)
|
||||
}
|
||||
m.Sort(nfs.PATH).StatusTimeCount()
|
||||
}},
|
||||
CLI: {Name: "cli", Help: "文件模块", Hand: func(m *ice.Message, arg ...string) {
|
||||
for k, v := range ice.Info.File {
|
||||
m.Push(nfs.FILE, k)
|
||||
m.Push(mdb.NAME, v)
|
||||
}
|
||||
m.Sort(nfs.FILE).StatusTimeCount()
|
||||
}},
|
||||
CMD: {Name: "cmd", Help: "模块命令", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.OptionFields(ctx.INDEX, mdb.NAME, mdb.HELP)
|
||||
m.Cmdy(ctx.COMMAND, mdb.SEARCH, ctx.COMMAND).StatusTimeCount()
|
||||
}},
|
||||
ENV: {Name: "env", Help: "环境变量", Hand: func(m *ice.Message, arg ...string) {
|
||||
for _, v := range os.Environ() {
|
||||
ls := strings.SplitN(v, "=", 2)
|
||||
m.Push(mdb.NAME, ls[0])
|
||||
@ -207,22 +239,6 @@ func init() {
|
||||
}
|
||||
m.StatusTimeCount()
|
||||
}},
|
||||
"file": {Name: "file", Help: "模块文件", Hand: func(m *ice.Message, arg ...string) {
|
||||
for k, v := range ice.Info.File {
|
||||
m.Push(nfs.FILE, k)
|
||||
m.Push(mdb.NAME, v)
|
||||
}
|
||||
m.Sort(nfs.FILE)
|
||||
m.StatusTimeCount()
|
||||
}},
|
||||
"route": {Name: "route", Help: "接口命令", Hand: func(m *ice.Message, arg ...string) {
|
||||
for k, v := range ice.Info.Route {
|
||||
m.Push(nfs.PATH, k)
|
||||
m.Push(nfs.FILE, v)
|
||||
}
|
||||
m.Sort(nfs.PATH)
|
||||
m.StatusTimeCount()
|
||||
}},
|
||||
MAKE_DOMAIN: {Name: "make.domain", Help: "编译主机", Hand: func(m *ice.Message, arg ...string) {
|
||||
if os.Getenv(CTX_DEV) == "" || os.Getenv(CTX_POD) == "" {
|
||||
m.Echo(m.Conf(RUNTIME, MAKE_DOMAIN))
|
||||
@ -234,8 +250,7 @@ func init() {
|
||||
if len(arg) > 0 && arg[0] == BOOTINFO {
|
||||
arg = arg[1:]
|
||||
}
|
||||
m.Cmdy(ctx.CONFIG, RUNTIME, arg)
|
||||
m.DisplayStoryJSON()
|
||||
m.Cmdy(ctx.CONFIG, RUNTIME, arg).DisplayStoryJSON()
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -12,43 +12,38 @@ import (
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
"shylinux.com/x/toolkits/file"
|
||||
)
|
||||
|
||||
func _system_cmd(m *ice.Message, arg ...string) *exec.Cmd {
|
||||
// 定制目录
|
||||
if text := kit.ReadFile(ice.ETC_PATH); len(text) > 0 {
|
||||
if file := _system_find(m, arg[0], strings.Split(text, ice.NL)...); file != "" {
|
||||
m.Debug("cmd: %v", file)
|
||||
arg[0] = file
|
||||
m.Log_SELECT("etc path cmd", file)
|
||||
arg[0] = file // 配置目录
|
||||
}
|
||||
}
|
||||
// 环境变量
|
||||
env := kit.Simple(m.Optionv(CMD_ENV))
|
||||
for i := 0; i < len(env)-1; i += 2 {
|
||||
if env[i] == PATH {
|
||||
if file := _system_find(m, arg[0], strings.Split(env[i+1], ice.DF)...); file != "" {
|
||||
m.Debug("cmd: %v", file)
|
||||
arg[0] = file
|
||||
m.Log_SELECT("env path cmd", file)
|
||||
arg[0] = file // 环境变量
|
||||
}
|
||||
}
|
||||
}
|
||||
// 自动安装
|
||||
if _system_find(m, arg[0]) == "" {
|
||||
if cmds := m.Cmd(MIRRORS, arg[0]).Append("cmd"); cmds != "" {
|
||||
m.Cmd(kit.Split(cmds))
|
||||
if file := _system_find(m, arg[0]); file != "" {
|
||||
m.Debug("cmd: %v", file)
|
||||
arg[0] = file
|
||||
}
|
||||
m.Cmd(MIRRORS, CMD, arg[0])
|
||||
if file := _system_find(m, arg[0]); file != "" {
|
||||
m.Log_SELECT("mirrors cmd", file)
|
||||
arg[0] = file // 软件镜像
|
||||
}
|
||||
}
|
||||
|
||||
cmd := exec.Command(arg[0], arg[1:]...)
|
||||
|
||||
// 运行目录
|
||||
if cmd.Dir = m.Option(CMD_DIR); len(cmd.Dir) > 0 {
|
||||
if m.Log_EXPORT(CMD_DIR, cmd.Dir); !kit.FileExists(cmd.Dir) {
|
||||
nfs.MkdirAll(m, cmd.Dir)
|
||||
file.MkdirAll(cmd.Dir, ice.MOD_DIR)
|
||||
}
|
||||
}
|
||||
// 环境变量
|
||||
@ -61,13 +56,11 @@ func _system_cmd(m *ice.Message, arg ...string) *exec.Cmd {
|
||||
return cmd
|
||||
}
|
||||
func _system_out(m *ice.Message, out string) io.Writer {
|
||||
defer func() { m.Warn(recover(), "output", out) }()
|
||||
|
||||
if w, ok := m.Optionv(out).(io.Writer); ok {
|
||||
return w
|
||||
} else if m.Option(out) == "" {
|
||||
return nil
|
||||
} else if f, p, e := kit.Create(m.Option(out)); m.Assert(e) {
|
||||
} else if f, p, e := file.CreateFile(m.Option(out)); m.Assert(e) {
|
||||
m.Log_EXPORT(out, p)
|
||||
m.Optionv(out, f)
|
||||
return f
|
||||
@ -95,20 +88,18 @@ func _system_find(m *ice.Message, bin string, dir ...string) string {
|
||||
return ""
|
||||
}
|
||||
func _system_exec(m *ice.Message, cmd *exec.Cmd) {
|
||||
// 输入流
|
||||
if r, ok := m.Optionv(CMD_INPUT).(io.Reader); ok {
|
||||
cmd.Stdin = r
|
||||
cmd.Stdin = r // 输入流
|
||||
}
|
||||
|
||||
// 输出流
|
||||
if w := _system_out(m, CMD_OUTPUT); w != nil {
|
||||
cmd.Stdout, cmd.Stderr = w, w
|
||||
cmd.Stdout, cmd.Stderr = w, w // 输出流
|
||||
if w := _system_out(m, CMD_ERRPUT); w != nil {
|
||||
cmd.Stderr = w
|
||||
}
|
||||
} else {
|
||||
out := bytes.NewBuffer(make([]byte, 0, ice.MOD_BUFS))
|
||||
err := bytes.NewBuffer(make([]byte, 0, ice.MOD_BUFS))
|
||||
cmd.Stdout, cmd.Stderr = out, err
|
||||
defer func() {
|
||||
m.Push(CMD_OUT, out.String())
|
||||
m.Push(CMD_ERR, err.String())
|
||||
@ -116,7 +107,6 @@ func _system_exec(m *ice.Message, cmd *exec.Cmd) {
|
||||
m.SetAppend()
|
||||
}
|
||||
}()
|
||||
cmd.Stdout, cmd.Stderr = out, err
|
||||
}
|
||||
|
||||
// 执行命令
|
||||
@ -126,16 +116,6 @@ func _system_exec(m *ice.Message, cmd *exec.Cmd) {
|
||||
|
||||
m.Push(mdb.TIME, m.Time()).Push(CODE, int(cmd.ProcessState.ExitCode()))
|
||||
}
|
||||
func IsSuccess(m *ice.Message) bool {
|
||||
return m.Append(CODE) == "0" || m.Append(CODE) == ""
|
||||
}
|
||||
func SystemFind(m *ice.Message, bin string, dir ...string) string {
|
||||
if text := kit.ReadFile(ice.ETC_PATH); len(text) > 0 {
|
||||
dir = append(dir, strings.Split(text, ice.NL)...)
|
||||
}
|
||||
dir = append(dir, strings.Split(kit.Env(PATH), ice.DF)...)
|
||||
return _system_find(m, bin, dir...)
|
||||
}
|
||||
|
||||
const (
|
||||
CMD_DIR = "cmd_dir"
|
||||
@ -145,16 +125,14 @@ const (
|
||||
CMD_OUTPUT = "cmd_output"
|
||||
CMD_ERRPUT = "cmd_errput"
|
||||
|
||||
CMD_OUT = "cmd_out"
|
||||
CMD_ERR = "cmd_err"
|
||||
CMD_OUT = "cmd_out"
|
||||
)
|
||||
|
||||
const SYSTEM = "system"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
SYSTEM: {Name: SYSTEM, Help: "系统命令", Value: kit.Data(mdb.FIELD, "time,id,cmd")},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
SYSTEM: {Name: "system cmd run", Help: "系统命令", Actions: ice.Actions{
|
||||
nfs.FIND: {Name: "find", Help: "查找", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Echo(_system_find(m, arg[0], arg[1:]...))
|
||||
@ -168,37 +146,28 @@ func init() {
|
||||
m.Cmdy(nfs.CAT, ice.ETC_PATH)
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) == 0 {
|
||||
mdb.ListSelect(m, arg...)
|
||||
return
|
||||
}
|
||||
// m.Grow(SYSTEM, "", kit.Dict(mdb.TIME, m.Time(), ice.CMD, kit.Join(arg, ice.SP)))
|
||||
|
||||
if len(arg) == 1 {
|
||||
arg = kit.Split(arg[0])
|
||||
}
|
||||
if kit.Ext(arg[0]) == nfs.SH && arg[0] != nfs.SH && kit.FileExists(path.Join(ice.SRC, arg[0])) {
|
||||
arg = []string{nfs.SH, path.Join(ice.SRC, arg[0])}
|
||||
}
|
||||
_system_exec(m, _system_cmd(m, arg...))
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
||||
type buffer struct {
|
||||
m *ice.Message
|
||||
n string
|
||||
}
|
||||
|
||||
func (b *buffer) Write(buf []byte) (int, error) {
|
||||
if b.m.IsCliUA() {
|
||||
print(string(buf))
|
||||
} else {
|
||||
b.m.PushNoticeGrow(string(buf))
|
||||
}
|
||||
return len(buf), nil
|
||||
}
|
||||
func (b *buffer) Close() error { return nil }
|
||||
func PushStream(m *ice.Message) {
|
||||
m.Option(CMD_OUTPUT, &buffer{m: m, n: m.Option(ice.MSG_DAEMON)})
|
||||
m.Option(CMD_OUTPUT, file.NewWriteCloser(func(buf []byte) (int, error) {
|
||||
m.PushNoticeGrow(string(buf))
|
||||
return len(buf), nil
|
||||
}, func() error { m.PushNoticeToast("done"); return nil }))
|
||||
}
|
||||
|
||||
func IsSuccess(m *ice.Message) bool {
|
||||
return m.Append(CODE) == "0" || m.Append(CODE) == ""
|
||||
}
|
||||
func SystemFind(m *ice.Message, bin string, dir ...string) string {
|
||||
if text := kit.ReadFile(ice.ETC_PATH); len(text) > 0 {
|
||||
dir = append(dir, strings.Split(text, ice.NL)...)
|
||||
}
|
||||
dir = append(dir, strings.Split(kit.Env(PATH), ice.DF)...)
|
||||
return _system_find(m, bin, dir...)
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
func _command_list(m *ice.Message, name string) {
|
||||
if kit.FileExists(path.Join(ice.SRC, name)) {
|
||||
if nfs.ExistsFile(m, path.Join(ice.SRC, name)) {
|
||||
switch kit.Ext(name) {
|
||||
case nfs.JS:
|
||||
m.Push(DISPLAY, ice.FileURI(name))
|
||||
@ -22,8 +22,8 @@ func _command_list(m *ice.Message, name string) {
|
||||
name = ice.GetFileCmd(name)
|
||||
|
||||
default:
|
||||
if file, msg := name, m.Cmd(mdb.RENDER, kit.Ext(name)); msg.Length() > 0 {
|
||||
m.Push(ARGS, kit.Format(kit.List(file)))
|
||||
if msg := m.Cmd(mdb.RENDER, kit.Ext(name)); msg.Length() > 0 {
|
||||
m.Push(ARGS, kit.Format(kit.List(name)))
|
||||
name = kit.Keys(msg.Append(mdb.TEXT), msg.Append(mdb.NAME))
|
||||
}
|
||||
}
|
||||
@ -68,10 +68,45 @@ func _command_search(m *ice.Message, kind, name, text string) {
|
||||
kit.SimpleKV("", s.Cap(ice.CTX_FOLLOW), cmd.Name, cmd.Help),
|
||||
CONTEXT, s.Cap(ice.CTX_FOLLOW), COMMAND, key,
|
||||
INDEX, kit.Keys(s.Cap(ice.CTX_FOLLOW), key),
|
||||
mdb.HELP, cmd.Help,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
const (
|
||||
INDEX = "index"
|
||||
ARGS = "args"
|
||||
STYLE = "style"
|
||||
DISPLAY = "display"
|
||||
ACTION = "action"
|
||||
|
||||
CAN_PLUGIN = "can.plugin"
|
||||
)
|
||||
const COMMAND = "command"
|
||||
|
||||
func init() {
|
||||
Index.MergeCommands(ice.Commands{
|
||||
COMMAND: {Name: "command key auto", Help: "命令", Actions: ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmd(aaa.ROLE, aaa.WHITE, aaa.VOID, m.Prefix(COMMAND))
|
||||
m.Cmd(aaa.ROLE, aaa.WHITE, aaa.VOID, COMMAND)
|
||||
}},
|
||||
mdb.SEARCH: {Name: "search type name text", Help: "搜索", Hand: func(m *ice.Message, arg ...string) {
|
||||
if arg[0] == m.CommandKey() || len(arg) > 1 && arg[1] != "" {
|
||||
_command_search(m, arg[0], kit.Select("", arg, 1), kit.Select("", arg, 2))
|
||||
}
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) == 0 {
|
||||
arg = append(arg, "")
|
||||
}
|
||||
for _, key := range arg {
|
||||
_command_list(m, key)
|
||||
}
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
||||
func CmdAction(args ...ice.Any) ice.Actions {
|
||||
return ice.Actions{ice.CTX_INIT: mdb.AutoConfig(args...),
|
||||
COMMAND: {Name: "command", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
|
||||
@ -90,37 +125,3 @@ func CmdAction(args ...ice.Any) ice.Actions {
|
||||
}},
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
INDEX = "index"
|
||||
ARGS = "args"
|
||||
STYLE = "style"
|
||||
DISPLAY = "display"
|
||||
ACTION = "action"
|
||||
|
||||
CAN_PLUGIN = "can.plugin"
|
||||
)
|
||||
const COMMAND = "command"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
COMMAND: {Name: "command key auto", Help: "命令", Actions: ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmd(aaa.ROLE, aaa.WHITE, aaa.VOID, m.Prefix(COMMAND))
|
||||
m.Cmd(aaa.ROLE, aaa.WHITE, aaa.VOID, COMMAND)
|
||||
}},
|
||||
mdb.SEARCH: {Name: "search type name text", Help: "搜索", Hand: func(m *ice.Message, arg ...string) {
|
||||
if arg[0] == m.CommandKey() || len(arg) > 1 && arg[1] != "" {
|
||||
_command_search(m, arg[0], kit.Select("", arg, 1), kit.Select("", arg, 2))
|
||||
}
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) == 0 {
|
||||
arg = append(arg, "")
|
||||
}
|
||||
for _, key := range arg {
|
||||
_command_list(m, key)
|
||||
}
|
||||
}},
|
||||
}})
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package ctx
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
@ -10,23 +9,12 @@ import (
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
"shylinux.com/x/toolkits/miss"
|
||||
)
|
||||
|
||||
func _config_list(m *ice.Message) {
|
||||
for k, v := range m.Source().Configs {
|
||||
if k[0] == '/' || k[0] == '_' {
|
||||
continue // 内部配置
|
||||
}
|
||||
|
||||
m.Push(mdb.KEY, k)
|
||||
m.Push(mdb.NAME, v.Name)
|
||||
m.Push(mdb.VALUE, kit.Format(v.Value))
|
||||
}
|
||||
m.Sort(mdb.KEY)
|
||||
}
|
||||
func _config_save(m *ice.Message, name string, arg ...string) {
|
||||
name = path.Join(m.Config(nfs.PATH), name)
|
||||
if f, p, e := kit.Create(name); m.Assert(e) {
|
||||
name = path.Join(ice.VAR_CONF, name)
|
||||
if f, p, e := miss.CreateFile(name); m.Assert(e) {
|
||||
defer f.Close()
|
||||
|
||||
msg := m.Spawn(m.Source())
|
||||
@ -39,16 +27,16 @@ func _config_save(m *ice.Message, name string, arg ...string) {
|
||||
|
||||
// 保存配置
|
||||
if s, e := json.MarshalIndent(data, "", " "); m.Assert(e) {
|
||||
if n, e := f.Write(s); m.Assert(e) {
|
||||
m.Log_EXPORT(CONFIG, name, nfs.FILE, p, nfs.SIZE, n)
|
||||
if _, e := f.Write(s); m.Assert(e) {
|
||||
// m.Log_EXPORT(CONFIG, name, nfs.FILE, p, nfs.SIZE, n)
|
||||
}
|
||||
}
|
||||
m.Echo(p)
|
||||
}
|
||||
}
|
||||
func _config_load(m *ice.Message, name string, arg ...string) {
|
||||
name = path.Join(m.Config(nfs.PATH), name)
|
||||
if f, e := os.Open(name); e == nil {
|
||||
name = path.Join(ice.VAR_CONF, name)
|
||||
if f, e := miss.OpenFile(name); e == nil {
|
||||
defer f.Close()
|
||||
|
||||
msg := m.Spawn(m.Source())
|
||||
@ -58,7 +46,7 @@ func _config_load(m *ice.Message, name string, arg ...string) {
|
||||
// 加载配置
|
||||
for k, v := range data {
|
||||
msg.Search(k, func(p *ice.Context, s *ice.Context, key string) {
|
||||
m.Log_IMPORT(CONFIG, kit.Keys(s.Name, key), nfs.FILE, name)
|
||||
// m.Log_IMPORT(CONFIG, kit.Keys(s.Name, key), nfs.FILE, name)
|
||||
if s.Configs[key] == nil {
|
||||
s.Configs[key] = &ice.Config{}
|
||||
}
|
||||
@ -83,11 +71,17 @@ func _config_make(m *ice.Message, key string, arg ...string) {
|
||||
m.Echo(kit.Formats(msg.Confv(key)))
|
||||
}
|
||||
}
|
||||
func _config_rich(m *ice.Message, key string, sub string, arg ...string) {
|
||||
m.Rich(key, sub, kit.Data(arg))
|
||||
}
|
||||
func _config_grow(m *ice.Message, key string, sub string, arg ...string) {
|
||||
m.Grow(key, sub, kit.Dict(arg))
|
||||
func _config_list(m *ice.Message) {
|
||||
for k, v := range m.Source().Configs {
|
||||
if k[0] == '/' || k[0] == '_' {
|
||||
continue // 内部配置
|
||||
}
|
||||
|
||||
m.Push(mdb.KEY, k)
|
||||
m.Push(mdb.NAME, v.Name)
|
||||
m.Push(mdb.VALUE, kit.Format(v.Value))
|
||||
}
|
||||
m.Sort(mdb.KEY)
|
||||
}
|
||||
|
||||
const (
|
||||
@ -99,9 +93,7 @@ const (
|
||||
const CONFIG = "config"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
CONFIG: {Name: CONFIG, Help: "配置", Value: kit.Data(nfs.PATH, ice.VAR_CONF)},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
CONFIG: {Name: "config key auto reset", Help: "配置", Actions: ice.Actions{
|
||||
SAVE: {Name: "save", Help: "保存", Hand: func(m *ice.Message, arg ...string) {
|
||||
_config_save(m, arg[0], arg[1:]...)
|
||||
@ -110,10 +102,10 @@ func init() {
|
||||
_config_load(m, arg[0], arg[1:]...)
|
||||
}},
|
||||
RICH: {Name: "rich", Help: "富有", Hand: func(m *ice.Message, arg ...string) {
|
||||
_config_rich(m, arg[0], arg[1], arg[2:]...)
|
||||
m.Cmdy(mdb.INSERT, arg[0], arg[1], mdb.HASH, arg[2:])
|
||||
}},
|
||||
GROW: {Name: "grow", Help: "成长", Hand: func(m *ice.Message, arg ...string) {
|
||||
_config_grow(m, arg[0], arg[1], arg[2:]...)
|
||||
m.Cmdy(mdb.INSERT, arg[0], arg[1], mdb.LIST, arg[2:])
|
||||
}},
|
||||
"list": {Name: "list", Help: "列表", Hand: func(m *ice.Message, arg ...string) {
|
||||
list := []ice.Any{}
|
||||
@ -134,5 +126,5 @@ func init() {
|
||||
_config_make(m, arg[0], arg[1:]...)
|
||||
m.DisplayStoryJSON()
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
@ -19,35 +20,20 @@ func _context_list(m *ice.Message, sub *ice.Context, name string) {
|
||||
m.Push(mdb.HELP, s.Help)
|
||||
})
|
||||
}
|
||||
func Inputs(m *ice.Message, field string) bool {
|
||||
switch strings.TrimPrefix(field, "extra.") {
|
||||
case ice.POD:
|
||||
m.Cmdy("route")
|
||||
case ice.CTX:
|
||||
m.Cmdy(CONTEXT)
|
||||
case ice.CMD:
|
||||
m.Cmdy(CONTEXT, kit.Select(m.Option(ice.CTX), m.Option(kit.Keys(mdb.EXTRA, ice.CTX))), COMMAND)
|
||||
case ice.ARG:
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
const CONTEXT = "context"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
CONTEXT: {Name: "context name=web action=context,command,config key auto spide", Help: "模块", Actions: ice.MergeAction(ice.Actions{
|
||||
"spide": {Name: "spide", Help: "架构图", Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) == 0 || arg[1] == CONTEXT { // 模块列表
|
||||
m.Cmdy(CONTEXT, kit.Select(ice.ICE, arg, 0), CONTEXT)
|
||||
m.Display("/plugin/story/spide.js?prefix=spide", "root", kit.Select(ice.ICE, arg, 0), "split", ice.PT)
|
||||
m.DisplayStorySpide("prefix", m.ActionKey(), nfs.ROOT, kit.Select(ice.ICE, arg, 0), "split", ice.PT)
|
||||
|
||||
} else if index := kit.Keys(arg[1]); strings.HasSuffix(index, arg[2]) { // 命令列表
|
||||
m.Cmdy(CONTEXT, index, COMMAND).Tables(func(value ice.Maps) {
|
||||
m.Push("file", arg[1])
|
||||
m.Push(nfs.FILE, arg[1])
|
||||
})
|
||||
|
||||
} else { // 命令详情
|
||||
@ -72,5 +58,20 @@ func init() {
|
||||
}
|
||||
})
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
func Inputs(m *ice.Message, field string) bool {
|
||||
switch strings.TrimPrefix(field, "extra.") {
|
||||
case ice.POD:
|
||||
m.Cmdy("route")
|
||||
case ice.CTX:
|
||||
m.Cmdy(CONTEXT)
|
||||
case ice.CMD:
|
||||
m.Cmdy(CONTEXT, kit.Select(m.Option(ice.CTX), m.Option(kit.Keys(mdb.EXTRA, ice.CTX))), COMMAND)
|
||||
case ice.ARG:
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
const MESSAGE = "message"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
MESSAGE: {Name: "message", Help: "消息", Hand: func(m *ice.Message, arg ...string) {
|
||||
t := reflect.TypeOf(m)
|
||||
for i := 0; i < t.NumMethod(); i++ {
|
||||
@ -22,5 +22,5 @@ func init() {
|
||||
m.Push(mdb.TEXT, strings.Split(p, ice.ICEBERGS+"/")[1])
|
||||
}
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -6,33 +6,19 @@ import (
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
func _event_listen(m *ice.Message, event string, cmd string) {
|
||||
m.Cmdy(mdb.INSERT, EVENT, "", mdb.HASH, EVENT, event)
|
||||
m.Cmdy(mdb.INSERT, EVENT, "", mdb.ZONE, event, ice.CMD, cmd)
|
||||
}
|
||||
func _event_action(m *ice.Message, event string, arg ...string) {
|
||||
mdb.ZoneSelect(m, event).Tables(func(value ice.Maps) {
|
||||
m.Cmd(kit.Split(value[ice.CMD]), event, arg).Cost(EVENT, event, ice.ARG, arg)
|
||||
})
|
||||
}
|
||||
|
||||
const EVENT = "event"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
EVENT: {Name: EVENT, Help: "事件流", Value: kit.Data(mdb.SHORT, EVENT, mdb.FIELD, "time,id,cmd")},
|
||||
}, Commands: ice.Commands{
|
||||
EVENT: {Name: "event event id auto listen", Help: "事件流", Actions: ice.MergeAction(ice.Actions{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
EVENT: {Name: "event event id auto listen happen", Help: "事件流", Actions: ice.MergeAction(ice.Actions{
|
||||
LISTEN: {Name: "listen event cmd", Help: "监听", Hand: func(m *ice.Message, arg ...string) {
|
||||
_event_listen(m, m.Option(EVENT), m.Option(ice.CMD))
|
||||
mdb.ZoneInsert(m, m.OptionSimple(EVENT, ice.CMD))
|
||||
}},
|
||||
HAPPEN: {Name: "happen event arg", Help: "触发", Hand: func(m *ice.Message, arg ...string) {
|
||||
_event_action(m, m.Option(EVENT), arg[2:]...)
|
||||
mdb.ZoneSelect(m, m.Option(EVENT)).Tables(func(value ice.Maps) {
|
||||
m.Cmd(kit.Split(value[ice.CMD]), m.Option(EVENT), arg[2:]).Cost()
|
||||
})
|
||||
}},
|
||||
}, mdb.ZoneAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
if mdb.ZoneSelect(m, arg...); len(arg) == 0 {
|
||||
m.PushAction(HAPPEN, mdb.REMOVE)
|
||||
}
|
||||
}},
|
||||
}})
|
||||
}, mdb.ZoneAction(mdb.SHORT, EVENT, mdb.FIELD, "time,id,cmd"))},
|
||||
})
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package gdb
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
@ -10,48 +11,56 @@ import (
|
||||
|
||||
type Frame struct {
|
||||
s chan os.Signal
|
||||
t time.Duration
|
||||
e chan bool
|
||||
}
|
||||
|
||||
func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server {
|
||||
return &Frame{}
|
||||
}
|
||||
func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server {
|
||||
list := []string{}
|
||||
for k := range ice.Info.File {
|
||||
if strings.HasPrefix(k, ice.Info.Make.Path+ice.PS) {
|
||||
list = append(list, k)
|
||||
}
|
||||
}
|
||||
for _, k := range list {
|
||||
ice.Info.File["/require/"+strings.TrimPrefix(k, ice.Info.Make.Path+ice.PS)] = ice.Info.File[k]
|
||||
delete(ice.Info.File, k)
|
||||
}
|
||||
|
||||
f.s = make(chan os.Signal, ice.MOD_CHAN)
|
||||
f.e = make(chan bool, 1)
|
||||
return f
|
||||
}
|
||||
func (f *Frame) Start(m *ice.Message, arg ...string) bool {
|
||||
f.t = kit.Duration(m.Conf(TIMER, kit.Keym(TICK)))
|
||||
t := kit.Duration(m.Conf(TIMER, kit.Keym(TICK)))
|
||||
enable := m.Conf(TIMER, kit.Keym("enable")) == ice.TRUE
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-f.e:
|
||||
return true
|
||||
case <-time.Tick(t):
|
||||
if enable {
|
||||
m.Cmd(TIMER, HAPPEN)
|
||||
}
|
||||
|
||||
// case <-time.Tick(f.t):
|
||||
// // m.Cmd(TIMER, ACTION)
|
||||
|
||||
case s := <-f.s:
|
||||
case s, ok := <-f.s:
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
m.Cmd(SIGNAL, HAPPEN, SIGNAL, s)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
func (f *Frame) Close(m *ice.Message, arg ...string) bool {
|
||||
f.e <- true
|
||||
close(f.s)
|
||||
return true
|
||||
}
|
||||
|
||||
const GDB = "gdb"
|
||||
|
||||
var Index = &ice.Context{Name: GDB, Help: "事件模块", Commands: ice.Commands{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Load(TIMER)
|
||||
}},
|
||||
ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Save(TIMER)
|
||||
}},
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { m.Load(TIMER, ROUTINE) }},
|
||||
ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) { m.Save(TIMER, ROUTINE) }},
|
||||
}}
|
||||
|
||||
func init() { ice.Index.Register(Index, &Frame{}, ROUTINE, SIGNAL, EVENT, TIMER) }
|
||||
func init() { ice.Index.Register(Index, &Frame{}, SIGNAL, TIMER, EVENT, ROUTINE) }
|
||||
|
@ -4,31 +4,43 @@ import (
|
||||
"path"
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/cli"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
"shylinux.com/x/toolkits/logs"
|
||||
)
|
||||
|
||||
const ROUTINE = "routine"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
ROUTINE: {Name: ROUTINE, Help: "协程池", Value: kit.Data(mdb.SHORT, "time,hash,status,fileline")},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
ROUTINE: {Name: "routine hash auto prunes", Help: "协程池", Actions: ice.MergeAction(ice.Actions{
|
||||
mdb.CREATE: {Name: "create fileline status", Help: "创建"},
|
||||
mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.OptionFields(m.Config(mdb.SHORT))
|
||||
m.Cmdy(mdb.PRUNES, ROUTINE, "", mdb.HASH, cli.STATUS, cli.STOP)
|
||||
m.Cmdy(mdb.PRUNES, ROUTINE, "", mdb.HASH, cli.STATUS, cli.ERROR)
|
||||
mdb.CREATE: {Name: "create name", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Go(func() {
|
||||
cb := m.OptionCB(ROUTINE)
|
||||
h := mdb.HashCreate(m, m.OptionSimple(mdb.NAME), mdb.STATUS, START, ice.CMD, logs.FileLine(cb, 100)).Result()
|
||||
defer func() {
|
||||
if e := recover(); e == nil {
|
||||
mdb.HashModify(m, mdb.HASH, h, mdb.STATUS, STOP)
|
||||
} else {
|
||||
mdb.HashModify(m, mdb.HASH, h, mdb.STATUS, ERROR, ERROR, e)
|
||||
}
|
||||
}()
|
||||
switch cb := cb.(type) {
|
||||
case []string:
|
||||
m.Cmd(kit.Split(kit.Join(cb)))
|
||||
case string:
|
||||
m.Cmd(kit.Split(cb))
|
||||
case func():
|
||||
cb()
|
||||
default:
|
||||
m.ErrorNotImplement(cb)
|
||||
}
|
||||
})
|
||||
}},
|
||||
"inner": {Name: "inner", Help: "源码", Hand: func(m *ice.Message, arg ...string) {
|
||||
ls := kit.Split(m.Option("fileline"), ":")
|
||||
ls := kit.Split(m.Option(ice.CMD), ":")
|
||||
m.ProcessCommand("inner", []string{path.Dir(ls[0]), path.Base(ls[0]), ls[1]}, arg...)
|
||||
}},
|
||||
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.HashSelect(m, arg...)
|
||||
m.PushAction("inner", mdb.REMOVE)
|
||||
}},
|
||||
}})
|
||||
}, mdb.HashActionStatus(mdb.FIELD, "time,hash,name,status,cmd", mdb.ACTION, "inner"))},
|
||||
})
|
||||
}
|
||||
|
@ -1,23 +1,22 @@
|
||||
package gdb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path"
|
||||
"syscall"
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/cli"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
log "shylinux.com/x/toolkits/logs"
|
||||
"shylinux.com/x/toolkits/logs"
|
||||
)
|
||||
|
||||
func _signal_listen(m *ice.Message, s int, arg ...string) {
|
||||
if f, ok := m.Target().Server().(*Frame); ok {
|
||||
m.Cmdy(mdb.INSERT, SIGNAL, "", mdb.HASH, arg)
|
||||
signal.Notify(f.s, syscall.Signal(s))
|
||||
mdb.HashCreate(m, SIGNAL, s, arg)
|
||||
}
|
||||
}
|
||||
func _signal_action(m *ice.Message, arg ...string) {
|
||||
@ -25,6 +24,65 @@ func _signal_action(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(kit.Split(value[ice.CMD]))
|
||||
})
|
||||
}
|
||||
func _signal_process(m *ice.Message, p string, s os.Signal) {
|
||||
if p == "" {
|
||||
p = m.Cmdx(nfs.CAT, ice.Info.PidPath)
|
||||
}
|
||||
if p == "" {
|
||||
p = kit.Format(os.Getpid())
|
||||
}
|
||||
if p, e := os.FindProcess(kit.Int(p)); e == nil {
|
||||
p.Signal(s)
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
PID = "pid"
|
||||
)
|
||||
const (
|
||||
LISTEN = ice.LISTEN
|
||||
HAPPEN = ice.HAPPEN
|
||||
|
||||
START = ice.START
|
||||
RESTART = ice.RESTART
|
||||
STOP = ice.STOP
|
||||
ERROR = ice.ERROR
|
||||
KILL = "kill"
|
||||
)
|
||||
const SIGNAL = "signal"
|
||||
|
||||
func init() {
|
||||
Index.MergeCommands(ice.Commands{
|
||||
SIGNAL: {Name: "signal signal auto listen", Help: "信号器", Actions: ice.MergeAction(ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
_signal_listen(m, 2, mdb.NAME, "重启", ice.CMD, "exit 1")
|
||||
_signal_listen(m, 3, mdb.NAME, "退出", ice.CMD, "exit 0")
|
||||
if f, p, e := logs.CreateFile(ice.Info.PidPath); !m.Warn(e) {
|
||||
defer f.Close()
|
||||
fmt.Fprint(f, os.Getpid())
|
||||
m.Log_CREATE(nfs.FILE, p)
|
||||
}
|
||||
}},
|
||||
LISTEN: {Name: "listen signal name cmd", Help: "监听", Hand: func(m *ice.Message, arg ...string) {
|
||||
_signal_listen(m, kit.Int(m.Option(SIGNAL)), arg...)
|
||||
}},
|
||||
HAPPEN: {Name: "happen signal", Help: "触发", Hand: func(m *ice.Message, arg ...string) {
|
||||
_signal_action(m, m.Option(SIGNAL))
|
||||
}},
|
||||
RESTART: {Name: "restart pid", Help: "触发", Hand: func(m *ice.Message, arg ...string) {
|
||||
_signal_process(m, m.Option(PID), syscall.SIGINT)
|
||||
}},
|
||||
STOP: {Name: "stop pid", Help: "触发", Hand: func(m *ice.Message, arg ...string) {
|
||||
_signal_process(m, m.Option(PID), syscall.SIGQUIT)
|
||||
}},
|
||||
KILL: {Name: "kill pid signal", Help: "触发", Hand: func(m *ice.Message, arg ...string) {
|
||||
_signal_process(m, m.Option(PID), syscall.Signal(kit.Int(kit.Select("9", m.Option(SIGNAL)))))
|
||||
}},
|
||||
}, mdb.HashAction(mdb.SHORT, SIGNAL, mdb.FIELD, "time,signal,name,cmd", mdb.ACTION, HAPPEN)), Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.HashSelect(m, arg...).Sort(SIGNAL)
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
||||
func SignalNotify(m *ice.Message, sig int, cb func()) {
|
||||
ch := make(chan os.Signal)
|
||||
@ -37,39 +95,3 @@ func SignalNotify(m *ice.Message, sig int, cb func()) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const (
|
||||
LISTEN = ice.LISTEN
|
||||
HAPPEN = ice.HAPPEN
|
||||
)
|
||||
const SIGNAL = "signal"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
SIGNAL: {Name: SIGNAL, Help: "信号器", Value: kit.Data(
|
||||
mdb.SHORT, SIGNAL, mdb.FIELD, "time,signal,name,cmd", nfs.PATH, path.Join(ice.VAR_RUN, "ice.pid"),
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
SIGNAL: {Name: "signal signal auto listen", Help: "信号器", Actions: ice.MergeAction(ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
if log.LogDisable {
|
||||
return // 禁用日志
|
||||
}
|
||||
m.Cmd(nfs.SAVE, kit.Select(m.Config(nfs.PATH), m.Conf(cli.RUNTIME, kit.Keys(cli.CONF, cli.CTX_PID))),
|
||||
m.Conf(cli.RUNTIME, kit.Keys(cli.HOST, cli.PID)))
|
||||
|
||||
m.Cmd(SIGNAL, LISTEN, SIGNAL, "3", mdb.NAME, "退出", ice.CMD, "exit 0")
|
||||
m.Cmd(SIGNAL, LISTEN, SIGNAL, "2", mdb.NAME, "重启", ice.CMD, "exit 1")
|
||||
}},
|
||||
LISTEN: {Name: "listen signal name cmd", Help: "监听", Hand: func(m *ice.Message, arg ...string) {
|
||||
_signal_listen(m, kit.Int(m.Option(SIGNAL)), arg...)
|
||||
}},
|
||||
HAPPEN: {Name: "happen signal", Help: "触发", Hand: func(m *ice.Message, arg ...string) {
|
||||
_signal_action(m, m.Option(SIGNAL))
|
||||
}},
|
||||
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.HashSelect(m, arg...).Sort(SIGNAL)
|
||||
m.PushAction(HAPPEN, mdb.REMOVE)
|
||||
}},
|
||||
}})
|
||||
}
|
||||
|
@ -4,62 +4,43 @@ import (
|
||||
"time"
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/cli"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
func _timer_action(m *ice.Message, arg ...string) {
|
||||
now := time.Now().UnixNano()
|
||||
m.OptionFields(m.Config(mdb.FIELD))
|
||||
|
||||
m.Richs(TIMER, "", mdb.FOREACH, func(key string, value ice.Map) {
|
||||
if value = kit.GetMeta(value); value[cli.STATUS] == cli.STOP {
|
||||
func _timer_action(m *ice.Message, now time.Time, arg ...string) {
|
||||
mdb.HashSelects(m).Tables(func(value ice.Maps) {
|
||||
if value[mdb.COUNT] == "0" {
|
||||
return
|
||||
}
|
||||
|
||||
order := kit.Int(value[ORDER])
|
||||
if n := kit.Time(kit.Format(value[NEXT])); now > n && order > 0 {
|
||||
m.Logs(TIMER, mdb.KEY, key, ORDER, order)
|
||||
|
||||
msg := m.Cmd(value[ice.CMD])
|
||||
m.Grow(TIMER, kit.Keys(mdb.HASH, key), kit.Dict(ice.RES, msg.Result()))
|
||||
if value[ORDER] = kit.Format(order - 1); order > 1 {
|
||||
value[NEXT] = msg.Time(value[INTERVAL])
|
||||
}
|
||||
if kit.Time(value[mdb.TIME]) > kit.Int64(now) {
|
||||
return
|
||||
}
|
||||
m.Cmd(ROUTINE, mdb.CREATE, mdb.NAME, "some", kit.Keycb(ROUTINE), value[ice.CMD])
|
||||
mdb.HashModify(m, mdb.HASH, value[mdb.HASH], mdb.COUNT, kit.Int(value[mdb.COUNT])-1, mdb.TIME, m.Time(value[INTERVAL]))
|
||||
})
|
||||
}
|
||||
|
||||
const (
|
||||
DELAY = "delay"
|
||||
INTERVAL = "interval"
|
||||
ORDER = "order"
|
||||
NEXT = "next"
|
||||
TICK = "tick"
|
||||
)
|
||||
const TIMER = "timer"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
TIMER: {Name: TIMER, Help: "定时器", Value: kit.Data(
|
||||
mdb.FIELD, "time,hash,delay,interval,order,next,cmd", TICK, "1s",
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
TIMER: {Name: "timer hash id auto create action prunes", Help: "定时器", Actions: ice.MergeAction(ice.Actions{
|
||||
mdb.CREATE: {Name: "create delay=10ms interval=10s order=3 cmd=runtime", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(mdb.INSERT, TIMER, "", mdb.HASH, DELAY, "10ms", INTERVAL, "10m", ORDER, 1, NEXT, m.Time(m.Option(DELAY)), arg)
|
||||
}},
|
||||
Index.MergeCommands(ice.Commands{
|
||||
TIMER: {Name: "timer hash auto create prunes", Help: "定时器", Actions: ice.MergeAction(ice.Actions{
|
||||
mdb.CREATE: {Name: "create name=hi delay=10ms interval=10s count=3 cmd=runtime", Help: "创建"},
|
||||
mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.OptionFields(m.Config(mdb.FIELD))
|
||||
m.Cmdy(mdb.PRUNES, TIMER, "", mdb.HASH, ORDER, 0)
|
||||
mdb.HashPrunesValue(m, mdb.COUNT, "0")
|
||||
}},
|
||||
HAPPEN: {Name: "happen", Help: "执行", Hand: func(m *ice.Message, arg ...string) {
|
||||
_timer_action(m, arg...)
|
||||
_timer_action(m, time.Now(), arg...)
|
||||
}},
|
||||
}, mdb.ZoneAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Fields(len(arg), m.Config(mdb.FIELD), "time,id,res")
|
||||
mdb.ZoneSelect(m, arg...)
|
||||
}},
|
||||
}})
|
||||
RESTART: {Name: "restart count=3", Help: "重启", Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.HashModify(m, m.OptionSimple(mdb.HashShort(m)), arg)
|
||||
}},
|
||||
}, mdb.HashAction(mdb.FIELD, "time,hash,name,delay,interval,count,cmd", TICK, "10s"))},
|
||||
})
|
||||
}
|
||||
|
@ -385,9 +385,7 @@ const (
|
||||
const MATRIX = "matrix"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
MATRIX: {Name: MATRIX, Help: "魔方矩阵", Value: kit.Data()},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
MATRIX: {Name: "matrix hash npage text auto", Help: "魔方矩阵", Actions: ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
// _lex_load(m.Load())
|
||||
@ -399,7 +397,7 @@ func init() {
|
||||
case func(string, *Matrix):
|
||||
cb(h, mat)
|
||||
default:
|
||||
m.Error(true, ice.ErrNotImplement)
|
||||
m.ErrorNotImplement(cb)
|
||||
}
|
||||
m.Echo(h)
|
||||
}},
|
||||
@ -538,5 +536,5 @@ func init() {
|
||||
m.Push("word", string(word))
|
||||
})
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
package lex
|
||||
|
||||
const REGEXP = "regexp"
|
||||
const PREFIX = "prefix"
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"strings"
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
@ -34,18 +35,17 @@ func _split_deep(stack []int, text string) ([]int, int) {
|
||||
func _split_list(m *ice.Message, file string, arg ...string) ice.Map {
|
||||
const DEEP = "_deep"
|
||||
stack, deep := []int{}, 0
|
||||
list := kit.List(kit.Data(DEEP, -1))
|
||||
line := ""
|
||||
list, line := kit.List(kit.Data(DEEP, -1)), ""
|
||||
m.Cmd(nfs.CAT, file, func(text string) {
|
||||
if strings.HasPrefix(strings.TrimSpace(text), "# ") {
|
||||
return // 注释
|
||||
}
|
||||
if strings.TrimSpace(text) == "" {
|
||||
return // 空行
|
||||
}
|
||||
if line += text; strings.Count(text, "`")%2 == 1 {
|
||||
return // 多行
|
||||
}
|
||||
if strings.HasPrefix(strings.TrimSpace(text), "# ") {
|
||||
return // 注释
|
||||
}
|
||||
|
||||
stack, deep = _split_deep(stack, text)
|
||||
data := kit.Data(DEEP, deep)
|
||||
@ -61,8 +61,9 @@ func _split_list(m *ice.Message, file string, arg ...string) ice.Map {
|
||||
ls = cb(ls, data)
|
||||
case func([]string):
|
||||
cb(ls)
|
||||
case nil:
|
||||
default:
|
||||
m.Error(true, ice.ErrNotImplement)
|
||||
m.ErrorNotImplement(cb)
|
||||
}
|
||||
|
||||
// 参数字段
|
||||
@ -80,7 +81,7 @@ func _split_list(m *ice.Message, file string, arg ...string) ice.Map {
|
||||
// 查找节点
|
||||
for i := len(list) - 1; i >= 0; i-- {
|
||||
if deep > kit.Int(kit.Value(list[i], kit.Keym(DEEP))) {
|
||||
kit.Value(list[i], "list.-2", data)
|
||||
kit.Value(list[i], kit.Keys(mdb.LIST, "-2"), data)
|
||||
list = append(list, data)
|
||||
break
|
||||
}
|
||||
@ -90,9 +91,6 @@ func _split_list(m *ice.Message, file string, arg ...string) ice.Map {
|
||||
})
|
||||
return list[0].(ice.Map)
|
||||
}
|
||||
func Split(m *ice.Message, arg ...string) ice.Map {
|
||||
return kit.Value(_split_list(m, arg[0], arg[1:]...), "list.0").(ice.Map)
|
||||
}
|
||||
|
||||
const (
|
||||
SPLIT_SPACE = "split.space"
|
||||
@ -103,17 +101,17 @@ const (
|
||||
const SPLIT = "split"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
SPLIT: {Name: "split", Help: "解析", Value: kit.Data()},
|
||||
}, Commands: ice.Commands{
|
||||
SPLIT: {Name: "split path key auto", Help: "解析", Hand: func(m *ice.Message, arg ...string) {
|
||||
Index.MergeCommands(ice.Commands{
|
||||
SPLIT: {Name: "split path key auto", Help: "分词", Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) == 0 || strings.HasSuffix(arg[0], ice.PS) {
|
||||
m.Cmdy(nfs.DIR, arg)
|
||||
return
|
||||
}
|
||||
|
||||
m.Echo(kit.Format(_split_list(m, arg[0], kit.Split(kit.Join(arg[1:]))...)))
|
||||
m.DisplayStoryJSON()
|
||||
m.Echo(kit.Format(_split_list(m, arg[0], kit.Split(kit.Join(arg[1:]))...))).DisplayStoryJSON()
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
||||
func Split(m *ice.Message, arg ...string) ice.Map {
|
||||
return kit.Value(_split_list(m, arg[0], arg[1:]...), kit.Keys(mdb.LIST, "0")).(ice.Map)
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package log
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
@ -9,7 +10,7 @@ import (
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
log "shylinux.com/x/toolkits/logs"
|
||||
"shylinux.com/x/toolkits/logs"
|
||||
)
|
||||
|
||||
type Log struct {
|
||||
@ -25,6 +26,13 @@ func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server
|
||||
return &Frame{}
|
||||
}
|
||||
func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server {
|
||||
switch strings.Split(os.Getenv("TERM"), "-")[0] {
|
||||
case "xterm", "screen":
|
||||
ice.Info.Colors = true
|
||||
default:
|
||||
ice.Info.Colors = false
|
||||
}
|
||||
|
||||
f.p = make(chan *Log, ice.MOD_BUFS)
|
||||
ice.Info.Log = func(msg *ice.Message, p, l, s string) {
|
||||
f.p <- &Log{m: msg, p: p, l: l, s: s}
|
||||
@ -36,7 +44,7 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool {
|
||||
select {
|
||||
case l, ok := <-f.p:
|
||||
if !ok {
|
||||
break
|
||||
return true
|
||||
}
|
||||
|
||||
file := kit.Select(BENCH, m.Conf(SHOW, kit.Keys(l.l, FILE)))
|
||||
@ -124,9 +132,6 @@ var Index = &ice.Context{Name: "log", Help: "日志模块", Configs: ice.Configs
|
||||
SHOW: {Name: SHOW, Help: "日志分流", Value: kit.Dict()},
|
||||
}, Commands: ice.Commands{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
if log.LogDisable {
|
||||
return // 禁用日志
|
||||
}
|
||||
if !strings.Contains(ice.Getenv("ctx_daemon"), "log") {
|
||||
return // 没有日志
|
||||
}
|
||||
@ -140,7 +145,7 @@ var Index = &ice.Context{Name: "log", Help: "日志模块", Configs: ice.Configs
|
||||
m.Conf(SHOW, kit.Keys(k, FILE), key)
|
||||
})
|
||||
// 日志文件
|
||||
if f, p, e := kit.Create(kit.Format(value[nfs.PATH])); m.Assert(e) {
|
||||
if f, p, e := logs.CreateFile(kit.Format(value[nfs.PATH])); m.Assert(e) {
|
||||
m.Cap(ice.CTX_STREAM, path.Base(p))
|
||||
value[FILE] = bufio.NewWriter(f)
|
||||
m.Log_CREATE(nfs.FILE, p)
|
||||
|
@ -2,31 +2,10 @@ package mdb
|
||||
|
||||
import (
|
||||
ice "shylinux.com/x/icebergs"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
const ENGINE = "engine"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
ENGINE: {Name: ENGINE, Help: "引擎", Value: kit.Data(SHORT, TYPE, FIELD, "time,type,name,text")},
|
||||
}, Commands: ice.Commands{
|
||||
ENGINE: {Name: "engine type name text auto", Help: "引擎", Actions: ice.MergeAction(ice.Actions{
|
||||
CREATE: {Name: "create type name text", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Option(NAME, kit.Select(m.Option(TYPE), m.Option(NAME)))
|
||||
m.Option(TYPE, kit.Ext(m.Option(TYPE)))
|
||||
m.Cmdy(INSERT, m.PrefixKey(), "", HASH, m.OptionSimple("type,name,text"))
|
||||
}},
|
||||
}, HashAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) > 1 {
|
||||
m.Cmdy(SELECT, m.PrefixKey(), "", HASH, m.Config(SHORT), arg, func(value ice.Map) {
|
||||
m.Cmdy(kit.Keys(value[TEXT], value[NAME]), m.CommandKey(), arg[0], arg[1], kit.Select("", arg, 2), kit.Slice(arg, 3))
|
||||
})
|
||||
return
|
||||
}
|
||||
if HashSelect(m, arg...); len(arg) == 0 {
|
||||
m.Sort(TYPE)
|
||||
}
|
||||
}},
|
||||
}})
|
||||
Index.MergeCommands(ice.Commands{ENGINE: {Name: "engine type name text auto", Help: "引擎", Actions: RenderAction()}})
|
||||
}
|
||||
|
301
base/mdb/hash.go
301
base/mdb/hash.go
@ -2,27 +2,34 @@ package mdb
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
"shylinux.com/x/toolkits/miss"
|
||||
)
|
||||
|
||||
func _hash_fields(m *ice.Message) []string {
|
||||
return kit.Split(kit.Select("time,hash,type,name,text", m.OptionFields()))
|
||||
return kit.Split(kit.Select(HASH_FIELD, m.OptionFields()))
|
||||
}
|
||||
func _hash_select_fields(m *ice.Message, prefix, chain string, key string, field string) (value string) {
|
||||
defer m.RLock(prefix, chain)()
|
||||
m.Richs(prefix, chain, key, func(h string, v Map) {
|
||||
if field == HASH {
|
||||
value = h
|
||||
} else {
|
||||
value = kit.Format(v[field])
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
func _hash_inputs(m *ice.Message, prefix, chain string, field, value string) {
|
||||
defer m.RLock(prefix, chain)()
|
||||
|
||||
list := map[string]int{}
|
||||
m.Richs(prefix, chain, FOREACH, func(key string, val ice.Map) {
|
||||
if val = kit.GetMeta(val); kit.Format(val[COUNT]) != "" {
|
||||
list[kit.Format(val[field])] = kit.Int(val[COUNT])
|
||||
} else {
|
||||
list[kit.Format(val[field])]++
|
||||
}
|
||||
m.Richs(prefix, chain, FOREACH, func(val Map) {
|
||||
val = kit.GetMeta(val)
|
||||
list[kit.Format(val[field])] += kit.Int(kit.Select("1", val[COUNT]))
|
||||
})
|
||||
for k, i := range list {
|
||||
m.Push(field, k)
|
||||
@ -30,18 +37,30 @@ func _hash_inputs(m *ice.Message, prefix, chain string, field, value string) {
|
||||
}
|
||||
m.SortIntR(COUNT)
|
||||
}
|
||||
func _hash_insert(m *ice.Message, prefix, chain string, arg ...string) {
|
||||
func _hash_insert(m *ice.Message, prefix, chain string, arg ...string) string {
|
||||
defer m.Lock(prefix, chain)()
|
||||
|
||||
if m.Option(ice.MSG_DOMAIN) != "" {
|
||||
m.Conf(prefix, kit.Keys(chain, kit.Keym(SHORT)), m.Conf(prefix, kit.Keym(SHORT)))
|
||||
if value := m.Confm(prefix, kit.Keys(HASH, arg[1])); value != nil {
|
||||
value = kit.GetMeta(value)
|
||||
for i := 2; i < len(arg)-1; i += 2 {
|
||||
kit.Value(value, arg[i], arg[i+1])
|
||||
}
|
||||
return arg[1]
|
||||
}
|
||||
|
||||
m.Log_INSERT(KEY, path.Join(prefix, chain), arg[0], arg[1])
|
||||
if expire := m.Conf(prefix, kit.Keys(chain, kit.Keym(EXPIRE))); expire != "" {
|
||||
arg = kit.Simple(TIME, m.Time(expire), arg)
|
||||
}
|
||||
|
||||
m.Echo(m.Rich(prefix, chain, kit.Data(arg)))
|
||||
if m.Option(ice.MSG_DOMAIN) != "" {
|
||||
m.Conf(prefix, kit.Keys(chain, kit.Keym(SHORT)), m.Conf(prefix, kit.Keym(SHORT)))
|
||||
}
|
||||
if m.Optionv(TARGET) != nil {
|
||||
m.Echo(m.Rich(prefix, chain, kit.Data(arg, TARGET, m.Optionv(TARGET))))
|
||||
} else {
|
||||
m.Echo(m.Rich(prefix, chain, kit.Data(arg)))
|
||||
}
|
||||
return m.Result()
|
||||
}
|
||||
func _hash_delete(m *ice.Message, prefix, chain, field, value string) {
|
||||
defer m.Lock(prefix, chain)()
|
||||
@ -49,7 +68,7 @@ func _hash_delete(m *ice.Message, prefix, chain, field, value string) {
|
||||
if field != HASH {
|
||||
field, value = HASH, kit.Select(kit.Hashs(value), m.Option(HASH))
|
||||
}
|
||||
m.Richs(prefix, chain, value, func(key string, val ice.Map) {
|
||||
m.Richs(prefix, chain, value, func(key string, val Map) {
|
||||
m.Log_DELETE(KEY, path.Join(prefix, chain), field, value, VALUE, kit.Format(val))
|
||||
m.Conf(prefix, kit.Keys(chain, HASH, key), "")
|
||||
})
|
||||
@ -57,15 +76,9 @@ func _hash_delete(m *ice.Message, prefix, chain, field, value string) {
|
||||
func _hash_modify(m *ice.Message, prefix, chain string, field, value string, arg ...string) {
|
||||
defer m.Lock(prefix, chain)()
|
||||
|
||||
m.Richs(prefix, chain, value, func(key string, val ice.Map) {
|
||||
val = kit.GetMeta(val)
|
||||
m.Richs(prefix, chain, value, func(key string, val Map) {
|
||||
m.Log_MODIFY(KEY, path.Join(prefix, chain), field, value, arg)
|
||||
for i := 0; i < len(arg); i += 2 {
|
||||
if arg[i] == field {
|
||||
continue
|
||||
}
|
||||
kit.Value(val, arg[i], kit.Select("", arg, i+1))
|
||||
}
|
||||
_mdb_modify(m, val, field, arg...)
|
||||
})
|
||||
}
|
||||
func _hash_select(m *ice.Message, prefix, chain, field, value string) {
|
||||
@ -75,19 +88,8 @@ func _hash_select(m *ice.Message, prefix, chain, field, value string) {
|
||||
value = RANDOMS
|
||||
}
|
||||
fields := _hash_fields(m)
|
||||
m.Richs(prefix, chain, value, func(key string, val ice.Map) {
|
||||
switch val = kit.GetMeta(val); cb := m.OptionCB(SELECT).(type) {
|
||||
case func(fields []string, value ice.Map):
|
||||
cb(fields, val)
|
||||
case func(value ice.Map):
|
||||
cb(val)
|
||||
default:
|
||||
if m.OptionFields() == DETAIL {
|
||||
m.Push(DETAIL, val)
|
||||
} else {
|
||||
m.Push(key, val, fields)
|
||||
}
|
||||
}
|
||||
m.Richs(prefix, chain, value, func(key string, value Map) {
|
||||
_mdb_select(m, key, value, fields, nil)
|
||||
})
|
||||
if !m.FieldsIsDetail() {
|
||||
m.SortTimeR(TIME)
|
||||
@ -97,9 +99,9 @@ func _hash_prunes(m *ice.Message, prefix, chain string, arg ...string) {
|
||||
defer m.RLock(prefix, chain)()
|
||||
|
||||
fields := _hash_fields(m)
|
||||
m.Richs(prefix, chain, FOREACH, func(key string, val ice.Map) {
|
||||
m.Richs(prefix, chain, FOREACH, func(key string, val Map) {
|
||||
switch val = kit.GetMeta(val); cb := m.OptionCB(PRUNES).(type) {
|
||||
case func(string, ice.Map) bool:
|
||||
case func(string, Map) bool:
|
||||
if !cb(key, val) {
|
||||
return
|
||||
}
|
||||
@ -116,7 +118,7 @@ func _hash_prunes(m *ice.Message, prefix, chain string, arg ...string) {
|
||||
func _hash_export(m *ice.Message, prefix, chain, file string) {
|
||||
defer m.Lock(prefix, chain)()
|
||||
|
||||
f, p, e := kit.Create(kit.Keys(file, JSON))
|
||||
f, p, e := miss.CreateFile(kit.Keys(file, JSON))
|
||||
m.Assert(e)
|
||||
defer f.Close()
|
||||
|
||||
@ -131,13 +133,11 @@ func _hash_export(m *ice.Message, prefix, chain, file string) {
|
||||
func _hash_import(m *ice.Message, prefix, chain, file string) {
|
||||
defer m.Lock(prefix, chain)()
|
||||
|
||||
f, e := os.Open(kit.Keys(file, JSON))
|
||||
if m.Warn(e) {
|
||||
return
|
||||
}
|
||||
f, e := miss.OpenFile(kit.Keys(file, JSON))
|
||||
m.Assert(e)
|
||||
defer f.Close()
|
||||
|
||||
list := ice.Map{}
|
||||
list := Map{}
|
||||
m.Assert(json.NewDecoder(f).Decode(&list))
|
||||
|
||||
count := 0
|
||||
@ -157,41 +157,12 @@ func _hash_import(m *ice.Message, prefix, chain, file string) {
|
||||
m.Echo("%d", count)
|
||||
}
|
||||
|
||||
const (
|
||||
HASH_FIELD = "time,hash,type,name,text"
|
||||
)
|
||||
const HASH = "hash"
|
||||
|
||||
func AutoConfig(args ...ice.Any) *ice.Action {
|
||||
return &ice.Action{Hand: func(m *ice.Message, arg ...string) {
|
||||
if cs := m.Target().Configs; cs[m.CommandKey()] == nil && len(args) > 0 {
|
||||
cs[m.CommandKey()] = &ice.Config{Value: kit.Data(args...)}
|
||||
m.Load(m.CommandKey())
|
||||
}
|
||||
|
||||
inputs := []ice.Any{}
|
||||
kit.Fetch(kit.Split(m.Config(FIELD)), func(i int, k string) {
|
||||
switch k {
|
||||
case TIME, HASH, ID:
|
||||
return
|
||||
}
|
||||
inputs = append(inputs, k)
|
||||
})
|
||||
|
||||
cs := m.Target().Commands
|
||||
if cs[m.CommandKey()] == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if cs[m.CommandKey()].Actions[INSERT] != nil {
|
||||
if cs[m.CommandKey()].Meta[INSERT] == nil {
|
||||
m.Design(INSERT, "添加", append([]ice.Any{ZONE}, inputs...)...)
|
||||
}
|
||||
} else if cs[m.CommandKey()].Actions[CREATE] != nil {
|
||||
if cs[m.CommandKey()].Meta[CREATE] == nil {
|
||||
m.Design(CREATE, "创建", inputs...)
|
||||
}
|
||||
}
|
||||
}}
|
||||
}
|
||||
func HashAction(args ...ice.Any) ice.Actions {
|
||||
func HashAction(args ...Any) ice.Actions {
|
||||
return ice.Actions{ice.CTX_INIT: AutoConfig(args...),
|
||||
INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) { HashInputs(m, arg) }},
|
||||
CREATE: {Name: "create", Help: "创建", Hand: func(m *ice.Message, arg ...string) { HashCreate(m, arg) }},
|
||||
@ -203,93 +174,149 @@ func HashAction(args ...ice.Any) ice.Actions {
|
||||
IMPORT: {Name: "import", Help: "导入", Hand: func(m *ice.Message, arg ...string) { HashImport(m, arg) }},
|
||||
}
|
||||
}
|
||||
func HashActionStatus(args ...ice.Any) ice.Actions {
|
||||
func HashActionStatus(args ...Any) ice.Actions {
|
||||
list := HashAction(args...)
|
||||
list[PRUNES] = &ice.Action{Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.OptionFields(m.Config(FIELD))
|
||||
m.Cmdy(PRUNES, m.PrefixKey(), "", HASH, STATUS, "error")
|
||||
m.Cmdy(PRUNES, m.PrefixKey(), "", HASH, STATUS, "close")
|
||||
m.Cmdy(PRUNES, m.PrefixKey(), "", HASH, STATUS, ice.ERROR)
|
||||
m.Cmdy(PRUNES, m.PrefixKey(), "", HASH, STATUS, ice.CLOSE)
|
||||
m.Cmdy(PRUNES, m.PrefixKey(), "", HASH, STATUS, ice.STOP)
|
||||
m.Cmdy(PRUNES, m.PrefixKey(), "", HASH, STATUS, ice.END)
|
||||
m.Tables(func(value ice.Maps) { HashRemove(m, HASH, value[HASH]) })
|
||||
}}
|
||||
return list
|
||||
}
|
||||
|
||||
func HashInputs(m *ice.Message, arg ...ice.Any) *ice.Message {
|
||||
return m.Cmdy(INPUTS, m.PrefixKey(), "", HASH, kit.Simple(arg...))
|
||||
func HashShort(m *ice.Message) string {
|
||||
return kit.Select(HASH, m.Config(SHORT), m.Config(SHORT) != UNIQ)
|
||||
}
|
||||
func HashCreate(m *ice.Message, arg ...ice.Any) *ice.Message {
|
||||
field := m.Config(FIELD)
|
||||
args := kit.Simple(arg...)
|
||||
for i := 0; i < len(args); i += 2 {
|
||||
if !strings.Contains(field, args[i]) {
|
||||
args[i] = kit.Keys("extra", args[i])
|
||||
}
|
||||
}
|
||||
return m.Cmdy(INSERT, m.PrefixKey(), "", HASH, args)
|
||||
func HashField(m *ice.Message) string { return kit.Select(HASH_FIELD, m.Config(FIELD)) }
|
||||
func HashArgs(m *ice.Message, arg ...Any) []string {
|
||||
return _mdb_args(m, HashField(m), arg...)
|
||||
}
|
||||
func HashRemove(m *ice.Message, arg ...ice.Any) *ice.Message {
|
||||
m.OptionFields(m.Config(FIELD))
|
||||
defer m.Event(kit.Keys(m.CommandKey(), REMOVE), m.CommandKey(), m.Option(m.Config(SHORT)))
|
||||
return m.Cmd(DELETE, m.PrefixKey(), "", HASH, kit.Simple(arg...))
|
||||
func HashInputs(m *ice.Message, arg ...Any) *ice.Message {
|
||||
return m.Cmdy(INPUTS, m.PrefixKey(), "", HASH, HashArgs(m, arg))
|
||||
}
|
||||
func HashModify(m *ice.Message, arg ...ice.Any) *ice.Message {
|
||||
field := m.Config(FIELD)
|
||||
args := kit.Simple(arg...)
|
||||
for i := 0; i < len(args); i += 2 {
|
||||
if !strings.Contains(field, args[i]) {
|
||||
args[i] = kit.Keys("extra", args[i])
|
||||
}
|
||||
}
|
||||
return m.Cmd(MODIFY, m.PrefixKey(), "", HASH, args)
|
||||
func HashCreate(m *ice.Message, arg ...Any) *ice.Message {
|
||||
return m.Cmdy(INSERT, m.PrefixKey(), "", HASH, HashArgs(m, arg...))
|
||||
}
|
||||
func HashRemove(m *ice.Message, arg ...Any) *ice.Message {
|
||||
return m.Cmdy(DELETE, m.PrefixKey(), "", HASH, m.OptionSimple(HashShort(m)), arg)
|
||||
}
|
||||
func HashModify(m *ice.Message, arg ...Any) *ice.Message {
|
||||
return m.Cmd(MODIFY, m.PrefixKey(), "", HASH, m.OptionSimple(HashShort(m)), HashArgs(m, arg...))
|
||||
}
|
||||
func HashSelect(m *ice.Message, arg ...string) *ice.Message {
|
||||
m.Fields(len(arg), m.Config(FIELD))
|
||||
m.Cmdy(SELECT, m.PrefixKey(), "", HASH, m.Config(SHORT), arg)
|
||||
m.PushAction(m.Config("action"), REMOVE)
|
||||
m.StatusTimeCount()
|
||||
return m
|
||||
}
|
||||
func HashPrunes(m *ice.Message, cb func(ice.Maps) bool) *ice.Message {
|
||||
_key := func(m *ice.Message) string {
|
||||
if m.Config(HASH) == UNIQ {
|
||||
return HASH
|
||||
}
|
||||
if m.Config(SHORT) == UNIQ {
|
||||
return HASH
|
||||
}
|
||||
return kit.Select(HASH, m.Config(SHORT))
|
||||
m.Fields(len(kit.Slice(arg, 0, 1)), HashField(m))
|
||||
m.Cmdy(SELECT, m.PrefixKey(), "", HASH, HashShort(m), arg)
|
||||
if m.PushAction(m.Config(ACTION), REMOVE); !m.FieldsIsDetail() {
|
||||
return m.StatusTimeCount()
|
||||
} else {
|
||||
return m.StatusTime()
|
||||
}
|
||||
}
|
||||
func HashPrunes(m *ice.Message, cb func(Maps) bool) *ice.Message {
|
||||
expire := kit.Time(kit.Select(m.Time("-72h"), m.Option(EXPIRE)))
|
||||
m.Cmd(m.CommandKey()).Tables(func(value ice.Maps) {
|
||||
if kit.Time(value[TIME]) > expire {
|
||||
return
|
||||
m.Cmd(m.CommandKey()).Tables(func(value Maps) {
|
||||
if cb != nil && !cb(value) || kit.Time(value[TIME]) < expire {
|
||||
HashRemove(m, HashShort(m), value[HashShort(m)])
|
||||
}
|
||||
if cb != nil && cb(value) {
|
||||
return
|
||||
}
|
||||
m.OptionFields(m.Config(FIELD))
|
||||
m.Cmdy(DELETE, m.PrefixKey(), "", HASH, _key(m), value[_key(m)])
|
||||
})
|
||||
return m
|
||||
}
|
||||
func HashExport(m *ice.Message, arg ...ice.Any) *ice.Message {
|
||||
m.OptionFields(m.Config(FIELD))
|
||||
return m.Cmd(EXPORT, m.PrefixKey(), "", HASH, kit.Simple(arg...))
|
||||
func HashExport(m *ice.Message, arg ...Any) *ice.Message {
|
||||
return m.Cmdy(EXPORT, m.PrefixKey(), "", HASH, arg)
|
||||
}
|
||||
func HashImport(m *ice.Message, arg ...ice.Any) *ice.Message {
|
||||
return m.Cmd(IMPORT, m.PrefixKey(), "", HASH, kit.Simple(arg...))
|
||||
func HashImport(m *ice.Message, arg ...Any) *ice.Message {
|
||||
return m.Cmdy(IMPORT, m.PrefixKey(), "", HASH, arg)
|
||||
}
|
||||
|
||||
func HashCache(m *ice.Message, h string, add func() ice.Any) ice.Any {
|
||||
func HashTarget(m *ice.Message, h string, add func() Any) Any {
|
||||
defer m.Lock()()
|
||||
|
||||
p := m.Confv(m.PrefixKey(), kit.Keys(HASH, h, "_cache"))
|
||||
if pp, ok := p.(ice.Map); ok && len(pp) == 0 {
|
||||
p := m.Confv(m.PrefixKey(), kit.Keys(HASH, h, TARGET))
|
||||
if pp, ok := p.(Map); ok && len(pp) == 0 {
|
||||
p = nil
|
||||
}
|
||||
|
||||
if add != nil && p == nil {
|
||||
if p == nil && add != nil {
|
||||
p = add()
|
||||
m.Confv(m.PrefixKey(), kit.Keys(HASH, h, "_cache"), p) // 添加
|
||||
m.Confv(m.PrefixKey(), kit.Keys(HASH, h, TARGET), p)
|
||||
}
|
||||
return p
|
||||
}
|
||||
func HashPrunesValue(m *ice.Message, field, value string) {
|
||||
m.OptionFields(m.Config(FIELD))
|
||||
m.Cmdy(PRUNES, m.PrefixKey(), "", HASH, field, value)
|
||||
}
|
||||
func HashSelectFields(m *ice.Message, key string, field string) (value string) {
|
||||
HashSelectDetail(m, key, func(h string, val ice.Map) {
|
||||
if field == HASH {
|
||||
value = h
|
||||
} else {
|
||||
value = kit.Format(val[field])
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
func HashSelectDetail(m *ice.Message, key string, cb Any) bool {
|
||||
defer m.RLock(m.PrefixKey(), "")()
|
||||
has := false
|
||||
m.Richs(m.PrefixKey(), nil, key, func(key string, value Map) {
|
||||
hashSelect(m, key, value, cb)
|
||||
has = true
|
||||
})
|
||||
return has
|
||||
}
|
||||
func HashSelectUpdate(m *ice.Message, key string, cb Any) *ice.Message {
|
||||
defer m.Lock(m.PrefixKey(), "")()
|
||||
m.Richs(m.PrefixKey(), nil, key, func(key string, value Map) {
|
||||
hashSelect(m, key, value, cb)
|
||||
})
|
||||
return m
|
||||
}
|
||||
func HashSelectSearch(m *ice.Message, args []string, keys ...string) *ice.Message {
|
||||
if len(keys) == 0 {
|
||||
ls := kit.Split(m.Config(FIELD))
|
||||
for _, k := range ls {
|
||||
switch k {
|
||||
case TIME, HASH:
|
||||
default:
|
||||
keys = append(keys, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
if args[0] == m.CommandKey() {
|
||||
HashSelectValue(m, func(value ice.Map) {
|
||||
if args[1] == "" || args[1] == value[keys[1]] {
|
||||
m.PushSearch(kit.SimpleKV("", value[keys[0]], value[keys[1]], value[keys[2]]), value)
|
||||
}
|
||||
})
|
||||
}
|
||||
return m
|
||||
}
|
||||
func HashSelectValue(m *ice.Message, cb Any) *ice.Message {
|
||||
defer m.RLock(m.PrefixKey(), "")()
|
||||
m.Richs(m.PrefixKey(), nil, FOREACH, func(key string, value Map) {
|
||||
hashSelect(m, key, value, cb)
|
||||
})
|
||||
return m
|
||||
}
|
||||
func HashSelects(m *ice.Message, arg ...string) *ice.Message {
|
||||
m.OptionFields(m.Config(FIELD))
|
||||
return HashSelect(m, arg...)
|
||||
}
|
||||
func hashSelect(m *ice.Message, key string, value Map, cb Any) *ice.Message {
|
||||
switch value = kit.GetMeta(value); cb := cb.(type) {
|
||||
case func(string, Map):
|
||||
cb(key, value)
|
||||
case func(Map):
|
||||
cb(value)
|
||||
case func(Any):
|
||||
cb(value[TARGET])
|
||||
case nil:
|
||||
default:
|
||||
m.ErrorNotImplement(cb)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
145
base/mdb/list.go
145
base/mdb/list.go
@ -2,24 +2,23 @@ package mdb
|
||||
|
||||
import (
|
||||
"encoding/csv"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
"shylinux.com/x/toolkits/miss"
|
||||
)
|
||||
|
||||
func _list_fields(m *ice.Message) []string {
|
||||
return kit.Split(kit.Select("time,id,type,name,text", m.OptionFields()))
|
||||
return kit.Split(kit.Select(LIST_FIELD, m.OptionFields()))
|
||||
}
|
||||
func _list_inputs(m *ice.Message, prefix, chain string, field, value string) {
|
||||
defer m.RLock(prefix, chain)()
|
||||
|
||||
list := map[string]int{}
|
||||
m.Grows(prefix, chain, "", "", func(index int, val ice.Map) {
|
||||
if val = kit.GetMeta(val); kit.Format(val[COUNT]) != "" {
|
||||
list[kit.Format(val[field])] = kit.Int(val[COUNT])
|
||||
} else {
|
||||
list[kit.Format(val[field])]++
|
||||
}
|
||||
m.Grows(prefix, chain, "", "", func(val ice.Map) {
|
||||
val = kit.GetMeta(val)
|
||||
list[kit.Format(val[field])] += kit.Int(kit.Select("1", val[COUNT]))
|
||||
})
|
||||
for k, i := range list {
|
||||
m.Push(field, k)
|
||||
@ -28,43 +27,34 @@ func _list_inputs(m *ice.Message, prefix, chain string, field, value string) {
|
||||
m.SortIntR(COUNT)
|
||||
}
|
||||
func _list_insert(m *ice.Message, prefix, chain string, arg ...string) {
|
||||
defer m.Lock(prefix, chain)()
|
||||
|
||||
m.Log_INSERT(KEY, path.Join(prefix, chain), arg[0], arg[1])
|
||||
m.Echo("%d", m.Grow(prefix, chain, kit.Dict(arg)))
|
||||
}
|
||||
func _list_delete(m *ice.Message, prefix, chain, field, value string) {
|
||||
}
|
||||
func _list_modify(m *ice.Message, prefix, chain string, field, value string, arg ...string) {
|
||||
defer m.Lock(prefix, chain)()
|
||||
|
||||
m.Grows(prefix, chain, field, value, func(index int, val ice.Map) {
|
||||
val = kit.GetMeta(val)
|
||||
m.Log_MODIFY(KEY, path.Join(prefix, chain), field, value, arg)
|
||||
for i := 0; i < len(arg); i += 2 {
|
||||
if arg[i] == field {
|
||||
continue
|
||||
}
|
||||
kit.Value(val, arg[i], kit.Select("", arg, i+1))
|
||||
}
|
||||
_mdb_modify(m, val, field, arg...)
|
||||
})
|
||||
}
|
||||
func _list_select(m *ice.Message, prefix, chain, field, value string) {
|
||||
defer m.RLock(prefix, chain)()
|
||||
|
||||
if value == "" {
|
||||
field = ""
|
||||
}
|
||||
fields := _list_fields(m)
|
||||
m.Grows(prefix, chain, kit.Select(m.Option(ice.CACHE_FIELD), field), kit.Select(m.Option(ice.CACHE_VALUE), value), func(index int, val ice.Map) {
|
||||
switch val = kit.GetMeta(val); cb := m.OptionCB(SELECT).(type) {
|
||||
case func(fields []string, value ice.Map):
|
||||
cb(fields, val)
|
||||
default:
|
||||
if m.OptionFields() == DETAIL {
|
||||
m.Push(DETAIL, val)
|
||||
} else {
|
||||
m.Push("", val, fields)
|
||||
}
|
||||
}
|
||||
m.Grows(prefix, chain, kit.Select(m.Option(ice.CACHE_FIELD), field), kit.Select(m.Option(ice.CACHE_VALUE), value), func(value ice.Map) {
|
||||
_mdb_select(m, "", value, fields, nil)
|
||||
})
|
||||
}
|
||||
func _list_export(m *ice.Message, prefix, chain, file string) {
|
||||
f, p, e := kit.Create(kit.Keys(file, CSV))
|
||||
defer m.RLock(prefix, chain)()
|
||||
|
||||
f, p, e := miss.CreateFile(kit.Keys(file, CSV))
|
||||
m.Assert(e)
|
||||
defer f.Close()
|
||||
|
||||
@ -72,7 +62,7 @@ func _list_export(m *ice.Message, prefix, chain, file string) {
|
||||
defer w.Flush()
|
||||
|
||||
count := 0
|
||||
head := kit.Split(m.OptionFields())
|
||||
head := kit.Split(m.Config(FIELD))
|
||||
m.Grows(prefix, chain, "", "", func(index int, val ice.Map) {
|
||||
if val = kit.GetMeta(val); index == 0 {
|
||||
if len(head) == 0 || head[0] == ice.CACHE_DETAIL { // 默认表头
|
||||
@ -98,7 +88,9 @@ func _list_export(m *ice.Message, prefix, chain, file string) {
|
||||
m.Echo(p)
|
||||
}
|
||||
func _list_import(m *ice.Message, prefix, chain, file string) {
|
||||
f, e := os.Open(kit.Keys(file, CSV))
|
||||
defer m.RLock(prefix, chain)()
|
||||
|
||||
f, e := miss.OpenFile(kit.Keys(file, CSV))
|
||||
m.Assert(e)
|
||||
defer f.Close()
|
||||
|
||||
@ -128,55 +120,102 @@ func _list_import(m *ice.Message, prefix, chain, file string) {
|
||||
m.Log_IMPORT(KEY, kit.Keys(prefix, chain), COUNT, count)
|
||||
m.Echo("%d", count)
|
||||
}
|
||||
func _list_prunes(m *ice.Message, prefix, chain string, arg ...string) {
|
||||
}
|
||||
|
||||
const (
|
||||
LIST_FIELD = "time,id,type,name,text"
|
||||
)
|
||||
const LIST = "list"
|
||||
|
||||
func ListAction(args ...ice.Any) ice.Actions {
|
||||
return ice.Actions{ice.CTX_INIT: AutoConfig(args...),
|
||||
INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(INPUTS, m.PrefixKey(), "", LIST, arg)
|
||||
m.Cmdy(INPUTS, m.PrefixKey(), "", LIST, ListArgs(m, arg))
|
||||
}},
|
||||
INSERT: {Name: "insert type=go name=hi text=hello", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(INSERT, m.PrefixKey(), "", LIST, arg)
|
||||
INSERT: {Name: "insert", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(INSERT, m.PrefixKey(), "", LIST, ListArgs(m, arg))
|
||||
}},
|
||||
DELETE: {Name: "delete", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(DELETE, m.PrefixKey(), "", LIST, m.OptionSimple(ID), arg)
|
||||
}},
|
||||
MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(MODIFY, m.PrefixKey(), "", LIST, m.OptionSimple(ID), arg)
|
||||
m.Cmdy(MODIFY, m.PrefixKey(), "", LIST, m.OptionSimple(ID), ListArgs(m, arg))
|
||||
}},
|
||||
EXPORT: {Name: "export", Help: "导出", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Option(ice.CACHE_LIMIT, "-1")
|
||||
m.OptionFields(m.Config(FIELD))
|
||||
m.Cmdy(EXPORT, m.PrefixKey(), "", LIST)
|
||||
m.Conf(m.PrefixKey(), LIST, "")
|
||||
m.Config(COUNT, 0)
|
||||
}},
|
||||
IMPORT: {Name: "import", Help: "导入", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(IMPORT, m.PrefixKey(), "", LIST, arg)
|
||||
SELECT: {Name: "select", Help: "列表", Hand: func(m *ice.Message, arg ...string) {
|
||||
ListSelect(m, arg...)
|
||||
}},
|
||||
PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(PRUNES, m.PrefixKey(), "", LIST, arg)
|
||||
}},
|
||||
EXPORT: {Name: "export", Help: "导出", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(EXPORT, m.PrefixKey(), "", LIST, arg)
|
||||
}},
|
||||
IMPORT: {Name: "import", Help: "导入", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(IMPORT, m.PrefixKey(), "", LIST, arg)
|
||||
}},
|
||||
PREV: {Name: "prev", Help: "上一页", Hand: func(m *ice.Message, arg ...string) {
|
||||
PrevPage(m, m.Config(COUNT), kit.Slice(arg, 1)...)
|
||||
}},
|
||||
NEXT: {Name: "next", Help: "下一页", Hand: func(m *ice.Message, arg ...string) {
|
||||
NextPage(m, m.Config(COUNT), kit.Slice(arg, 1)...)
|
||||
}},
|
||||
SELECT: {Name: "select", Help: "列表", Hand: func(m *ice.Message, arg ...string) {
|
||||
ListSelect(m, arg...)
|
||||
NextPageLimit(m, m.Config(COUNT), kit.Slice(arg, 1)...)
|
||||
}},
|
||||
}
|
||||
}
|
||||
func ListField(m *ice.Message) string { return kit.Select(LIST_FIELD, m.Config(FIELD)) }
|
||||
func ListArgs(m *ice.Message, arg ...ice.Any) []string {
|
||||
return _mdb_args(m, ListField(m), arg...)
|
||||
}
|
||||
func ListSelect(m *ice.Message, arg ...string) *ice.Message {
|
||||
m.OptionPage(kit.Slice(arg, 1)...)
|
||||
m.Fields(len(kit.Slice(arg, 0, 1)), m.Config(FIELD))
|
||||
m.Cmdy(SELECT, m.PrefixKey(), "", LIST, ID, arg)
|
||||
if !m.FieldsIsDetail() {
|
||||
m.Fields(len(kit.Slice(arg, 0, 1)), ListField(m))
|
||||
if m.Cmdy(SELECT, m.PrefixKey(), "", LIST, ID, arg); !m.FieldsIsDetail() {
|
||||
m.StatusTimeCountTotal(m.Config(COUNT))
|
||||
} else {
|
||||
m.StatusTime()
|
||||
}
|
||||
return m
|
||||
}
|
||||
func PrevPageLimit(m *ice.Message, total string, arg ...string) {
|
||||
if kit.Int(kit.Select("0", arg, 1)) > 0 {
|
||||
PrevPage(m, total, arg...)
|
||||
} else {
|
||||
m.Toast("已经是最前一页啦!")
|
||||
m.ProcessHold()
|
||||
}
|
||||
}
|
||||
func PrevPage(m *ice.Message, total string, arg ...string) {
|
||||
limit, offend := kit.Select("10", arg, 0), kit.Select("0", arg, 1)
|
||||
offends := kit.Int(offend) - kit.Int(limit)
|
||||
if total != "0" && (offends <= -kit.Int(total) || offends >= kit.Int(total)) {
|
||||
m.Toast("已经是最前一页啦!")
|
||||
m.ProcessHold()
|
||||
return
|
||||
}
|
||||
if offends == 0 {
|
||||
m.ProcessRewrite("offend", "")
|
||||
} else {
|
||||
m.ProcessRewrite("offend", offends)
|
||||
}
|
||||
|
||||
}
|
||||
func NextPage(m *ice.Message, total string, arg ...string) {
|
||||
limit, offend := kit.Select("10", arg, 0), kit.Select("0", arg, 1)
|
||||
offends := kit.Int(offend) + kit.Int(limit)
|
||||
if total != "0" && (offends <= -kit.Int(total) || offends >= kit.Int(total)) {
|
||||
m.Toast("已经是最后一页啦!")
|
||||
m.ProcessHold()
|
||||
return
|
||||
}
|
||||
if offends == 0 {
|
||||
m.ProcessRewrite("offend", "")
|
||||
} else {
|
||||
m.ProcessRewrite("offend", offends)
|
||||
}
|
||||
}
|
||||
func NextPageLimit(m *ice.Message, total string, arg ...string) {
|
||||
if kit.Int(kit.Select("0", arg, 1)) < 0 {
|
||||
NextPage(m, total, arg...)
|
||||
} else {
|
||||
m.Toast("已经是最后一页啦!")
|
||||
m.ProcessHold()
|
||||
}
|
||||
}
|
||||
|
200
base/mdb/mdb.go
200
base/mdb/mdb.go
@ -8,26 +8,73 @@ import (
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
type Any = interface{}
|
||||
type Map = map[string]Any
|
||||
type Maps = map[string]string
|
||||
|
||||
func _domain_chain(m *ice.Message, chain string) string {
|
||||
return kit.Keys(m.Option(ice.MSG_DOMAIN), chain)
|
||||
}
|
||||
func _file_name(m *ice.Message, arg ...string) string {
|
||||
if len(arg) > 3 && strings.Contains(arg[3], ice.PS) {
|
||||
return arg[3]
|
||||
}
|
||||
return path.Join(ice.USR_LOCAL_EXPORT, m.Option(ice.MSG_DOMAIN), path.Join(arg[:2]...), arg[2])
|
||||
return kit.Select(path.Join(ice.USR_LOCAL_EXPORT, m.Option(ice.MSG_DOMAIN), path.Join(arg[:2]...), arg[2]), arg, 3)
|
||||
}
|
||||
func _domain_chain(m *ice.Message, chain string) string {
|
||||
return kit.Keys(m.Option(ice.MSG_DOMAIN), chain)
|
||||
func _mdb_args(m *ice.Message, field string, arg ...Any) []string {
|
||||
args := kit.Simple(arg...)
|
||||
for i := 0; i < len(args); i += 2 {
|
||||
if !strings.Contains(field, args[i]) && !strings.HasPrefix(args[i], EXTRA) {
|
||||
args[i] = kit.Keys(EXTRA, args[i])
|
||||
}
|
||||
}
|
||||
return args
|
||||
}
|
||||
func _mdb_modify(m *ice.Message, val ice.Map, field string, arg ...string) {
|
||||
val = kit.GetMeta(val)
|
||||
for i := 0; i < len(arg); i += 2 {
|
||||
if arg[i] == field {
|
||||
continue
|
||||
}
|
||||
kit.Value(val, arg[i], kit.Select("", arg, i+1))
|
||||
}
|
||||
}
|
||||
func _mdb_select(m *ice.Message, key string, value ice.Map, fields []string, val ice.Map) {
|
||||
switch value = kit.GetMeta(value); cb := m.OptionCB(SELECT).(type) {
|
||||
case func(string, []string, ice.Map, ice.Map):
|
||||
cb(key, fields, value, val)
|
||||
case func([]string, ice.Map):
|
||||
cb(fields, value)
|
||||
case func(string, ice.Map, ice.Map):
|
||||
cb(key, value, val)
|
||||
case func(string, ice.Map):
|
||||
cb(key, value)
|
||||
case func(ice.Map):
|
||||
cb(value)
|
||||
case func(Any):
|
||||
cb(value[TARGET])
|
||||
case func(ice.Maps):
|
||||
res := ice.Maps{}
|
||||
for k, v := range value {
|
||||
res[k] = kit.Format(v)
|
||||
}
|
||||
cb(res)
|
||||
case nil:
|
||||
if m.FieldsIsDetail() {
|
||||
m.Push(ice.CACHE_DETAIL, value)
|
||||
} else {
|
||||
m.Push(key, value, fields, val)
|
||||
}
|
||||
default:
|
||||
m.ErrorNotImplement(cb)
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
CSV = "csv"
|
||||
JSON = "json"
|
||||
)
|
||||
const (
|
||||
DICT = kit.MDB_DICT
|
||||
META = kit.MDB_META
|
||||
UNIQ = kit.MDB_UNIQ
|
||||
|
||||
UNIQ = kit.MDB_UNIQ
|
||||
FOREACH = kit.MDB_FOREACH
|
||||
RANDOMS = kit.MDB_RANDOMS
|
||||
)
|
||||
@ -36,7 +83,6 @@ const (
|
||||
ID = kit.MDB_ID
|
||||
KEY = kit.MDB_KEY
|
||||
TIME = kit.MDB_TIME
|
||||
// ZONE = kit.MDB_ZONE
|
||||
TYPE = kit.MDB_TYPE
|
||||
NAME = kit.MDB_NAME
|
||||
TEXT = kit.MDB_TEXT
|
||||
@ -71,6 +117,7 @@ const (
|
||||
const (
|
||||
DETAIL = "detail"
|
||||
RANDOM = "random"
|
||||
ACTION = "action"
|
||||
|
||||
INPUTS = "inputs"
|
||||
CREATE = "create"
|
||||
@ -91,103 +138,70 @@ const (
|
||||
PREV = "prev"
|
||||
PAGE = "page"
|
||||
OFFEND = "offend"
|
||||
|
||||
JSON = "json"
|
||||
CSV = "csv"
|
||||
)
|
||||
const (
|
||||
CACHE_CLEAR_ON_EXIT = "cache.clear.on.exit"
|
||||
|
||||
SOURCE = "_source"
|
||||
TARGET = "_target"
|
||||
)
|
||||
|
||||
func PrevPageLimit(m *ice.Message, total string, arg ...string) {
|
||||
if kit.Int(kit.Select("0", arg, 1)) > 0 {
|
||||
PrevPage(m, total, arg...)
|
||||
} else {
|
||||
m.Toast("已经是最前一页啦!")
|
||||
m.ProcessHold()
|
||||
}
|
||||
}
|
||||
func PrevPage(m *ice.Message, total string, arg ...string) {
|
||||
limit, offend := kit.Select("10", arg, 0), kit.Select("0", arg, 1)
|
||||
offends := kit.Int(offend) - kit.Int(limit)
|
||||
if total != "0" && (offends <= -kit.Int(total) || offends >= kit.Int(total)) {
|
||||
m.Toast("已经是最前一页啦!")
|
||||
m.ProcessHold()
|
||||
return
|
||||
}
|
||||
if offends == 0 {
|
||||
m.ProcessRewrite("offend", "")
|
||||
} else {
|
||||
m.ProcessRewrite("offend", offends)
|
||||
}
|
||||
|
||||
}
|
||||
func NextPage(m *ice.Message, total string, arg ...string) {
|
||||
limit, offend := kit.Select("10", arg, 0), kit.Select("0", arg, 1)
|
||||
offends := kit.Int(offend) + kit.Int(limit)
|
||||
if total != "0" && (offends <= -kit.Int(total) || offends >= kit.Int(total)) {
|
||||
m.Toast("已经是最后一页啦!")
|
||||
m.ProcessHold()
|
||||
return
|
||||
}
|
||||
if offends == 0 {
|
||||
m.ProcessRewrite("offend", "")
|
||||
} else {
|
||||
m.ProcessRewrite("offend", offends)
|
||||
}
|
||||
}
|
||||
func NextPageLimit(m *ice.Message, total string, arg ...string) {
|
||||
if kit.Int(kit.Select("0", arg, 1)) < 0 {
|
||||
NextPage(m, total, arg...)
|
||||
} else {
|
||||
m.Toast("已经是最后一页啦!")
|
||||
m.ProcessHold()
|
||||
}
|
||||
}
|
||||
|
||||
const MDB = "mdb"
|
||||
|
||||
var Index = &ice.Context{Name: MDB, Help: "数据模块", Commands: ice.Commands{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {}},
|
||||
ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) {}},
|
||||
INPUTS: {Name: "inputs key sub type field value", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
|
||||
switch arg[3] {
|
||||
switch arg[3] = strings.TrimPrefix(arg[3], "extra."); arg[3] {
|
||||
case ice.POD:
|
||||
m.Cmdy("route")
|
||||
case ice.CTX:
|
||||
m.Cmdy("context")
|
||||
case ice.CMD:
|
||||
m.Cmdy("context", kit.Select(m.Option(ice.CTX), m.Option(kit.Keys(EXTRA, ice.CTX))), "command")
|
||||
case "index":
|
||||
m.OptionFields(arg[3])
|
||||
m.Cmdy("command", "search", "command", "", "")
|
||||
}
|
||||
switch arg[2] {
|
||||
case ZONE: // inputs key sub type zone field value
|
||||
_list_inputs(m, arg[0], _domain_chain(m, kit.Keys(arg[1], kit.KeyHash(arg[3]))), kit.Select(NAME, arg, 4), kit.Select("", arg, 5))
|
||||
case HASH:
|
||||
_hash_inputs(m, arg[0], _domain_chain(m, arg[1]), kit.Select(NAME, arg, 3), kit.Select("", arg, 4))
|
||||
case LIST:
|
||||
_list_inputs(m, arg[0], _domain_chain(m, arg[1]), kit.Select(NAME, arg, 3), kit.Select("", arg, 4))
|
||||
m.OptionFields(arg[0])
|
||||
m.Cmdy("command", SEARCH, "command", kit.Select("", arg, 1))
|
||||
default:
|
||||
switch arg[2] {
|
||||
case ZONE: // inputs key sub type zone field value
|
||||
_zone_inputs(m, arg[0], _domain_chain(m, arg[1]), arg[3], kit.Select(NAME, arg, 4), kit.Select("", arg, 5))
|
||||
case HASH:
|
||||
_hash_inputs(m, arg[0], _domain_chain(m, arg[1]), kit.Select(NAME, arg, 3), kit.Select("", arg, 4))
|
||||
case LIST:
|
||||
_list_inputs(m, arg[0], _domain_chain(m, arg[1]), kit.Select(NAME, arg, 3), kit.Select("", arg, 4))
|
||||
}
|
||||
}
|
||||
}},
|
||||
INSERT: {Name: "insert key sub type arg...", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
|
||||
defer m.ProcessRefresh3ms()
|
||||
switch arg[2] {
|
||||
case ZONE: // insert key sub type zone arg...
|
||||
_list_insert(m, arg[0], _domain_chain(m, kit.Keys(arg[1], kit.KeyHash(arg[3]))), arg[4:]...)
|
||||
_zone_insert(m, arg[0], _domain_chain(m, arg[1]), arg[3], arg[4:]...)
|
||||
case HASH:
|
||||
_hash_insert(m, arg[0], _domain_chain(m, arg[1]), arg[3:]...)
|
||||
case LIST:
|
||||
_list_insert(m, arg[0], _domain_chain(m, arg[1]), arg[3:]...)
|
||||
}
|
||||
m.ProcessRefresh3ms()
|
||||
}},
|
||||
DELETE: {Name: "delete key sub type field value", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
|
||||
defer m.ProcessRefresh3ms()
|
||||
switch arg[2] {
|
||||
case ZONE: // delete key sub type zone field value
|
||||
_list_delete(m, arg[0], _domain_chain(m, kit.Keys(arg[1], kit.KeyHash(arg[3]))), arg[4], arg[5])
|
||||
// _list_delete(m, arg[0], _domain_chain(m, kit.Keys(arg[1], kit.KeyHash(arg[3]))), arg[4], arg[5])
|
||||
case HASH:
|
||||
_hash_delete(m, arg[0], _domain_chain(m, arg[1]), arg[3], arg[4])
|
||||
case LIST:
|
||||
_list_delete(m, arg[0], _domain_chain(m, arg[1]), arg[3], arg[4])
|
||||
// _list_delete(m, arg[0], _domain_chain(m, arg[1]), arg[3], arg[4])
|
||||
}
|
||||
m.ProcessRefresh3ms()
|
||||
}},
|
||||
MODIFY: {Name: "modify key sub type field value arg...", Help: "编辑", Hand: func(m *ice.Message, arg ...string) {
|
||||
switch arg[2] {
|
||||
case ZONE: // modify key sub type zone id field value
|
||||
_list_modify(m, arg[0], _domain_chain(m, kit.Keys(arg[1], kit.KeyHash(arg[3]))), ID, arg[4], arg[5:]...)
|
||||
_zone_modify(m, arg[0], _domain_chain(m, arg[1]), arg[3], arg[4], arg[5:]...)
|
||||
case HASH:
|
||||
_hash_modify(m, arg[0], _domain_chain(m, arg[1]), arg[3], arg[4], arg[5:]...)
|
||||
case LIST:
|
||||
@ -207,14 +221,12 @@ var Index = &ice.Context{Name: MDB, Help: "数据模块", Commands: ice.Commands
|
||||
PRUNES: {Name: "prunes key sub type [field value]...", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
|
||||
switch arg[2] {
|
||||
case ZONE: // prunes key sub type zone field value
|
||||
_list_prunes(m, arg[0], _domain_chain(m, kit.Keys(arg[1], kit.KeyHash(arg[3]))), arg[4:]...)
|
||||
// _list_prunes(m, arg[0], _domain_chain(m, kit.Keys(arg[1], kit.KeyHash(arg[3]))), arg[4:]...)
|
||||
case HASH:
|
||||
_hash_prunes(m, arg[0], _domain_chain(m, arg[1]), arg[3:]...)
|
||||
m.Tables(func(value ice.Maps) {
|
||||
_hash_delete(m, arg[0], _domain_chain(m, arg[1]), HASH, value[HASH])
|
||||
})
|
||||
m.Tables(func(value ice.Maps) { _hash_delete(m, arg[0], _domain_chain(m, arg[1]), HASH, value[HASH]) })
|
||||
case LIST:
|
||||
_list_prunes(m, arg[0], _domain_chain(m, arg[1]), arg[3:]...)
|
||||
// _list_prunes(m, arg[0], _domain_chain(m, arg[1]), arg[3:]...)
|
||||
}
|
||||
}},
|
||||
EXPORT: {Name: "export key sub type file", Help: "导出", Hand: func(m *ice.Message, arg ...string) {
|
||||
@ -223,10 +235,12 @@ var Index = &ice.Context{Name: MDB, Help: "数据模块", Commands: ice.Commands
|
||||
}
|
||||
switch file := _file_name(m, arg...); arg[2] {
|
||||
case ZONE:
|
||||
m.OptionFields(ZoneShort(m), m.Config(FIELD))
|
||||
_zone_export(m, arg[0], _domain_chain(m, arg[1]), file)
|
||||
case HASH:
|
||||
_hash_export(m, arg[0], _domain_chain(m, arg[1]), file)
|
||||
case LIST:
|
||||
m.OptionFields(m.Config(FIELD))
|
||||
_list_export(m, arg[0], _domain_chain(m, arg[1]), file)
|
||||
}
|
||||
}},
|
||||
@ -249,3 +263,35 @@ func init() {
|
||||
SEARCH, ENGINE, PLUGIN, RENDER,
|
||||
)
|
||||
}
|
||||
func AutoConfig(args ...ice.Any) *ice.Action {
|
||||
return &ice.Action{Hand: func(m *ice.Message, arg ...string) {
|
||||
if cs := m.Target().Configs; cs[m.CommandKey()] == nil && len(args) > 0 {
|
||||
cs[m.CommandKey()] = &ice.Config{Value: kit.Data(args...)}
|
||||
m.Load(m.CommandKey())
|
||||
}
|
||||
|
||||
inputs := []ice.Any{}
|
||||
kit.Fetch(kit.Split(m.Config(FIELD)), func(i int, k string) {
|
||||
switch k {
|
||||
case TIME, HASH, ID:
|
||||
return
|
||||
}
|
||||
inputs = append(inputs, k)
|
||||
})
|
||||
|
||||
cs := m.Target().Commands
|
||||
if cs[m.CommandKey()] == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if cs[m.CommandKey()].Actions[INSERT] != nil {
|
||||
if cs[m.CommandKey()].Meta[INSERT] == nil {
|
||||
m.Design(INSERT, "添加", append([]ice.Any{ZONE}, inputs...)...)
|
||||
}
|
||||
} else if cs[m.CommandKey()].Actions[CREATE] != nil {
|
||||
if cs[m.CommandKey()].Meta[CREATE] == nil {
|
||||
m.Design(CREATE, "创建", inputs...)
|
||||
}
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
@ -2,34 +2,10 @@ package mdb
|
||||
|
||||
import (
|
||||
ice "shylinux.com/x/icebergs"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
const PLUGIN = "plugin"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
PLUGIN: {Name: PLUGIN, Help: "插件", Value: kit.Data(SHORT, TYPE, FIELD, "time,type,name,text")},
|
||||
}, Commands: ice.Commands{
|
||||
PLUGIN: {Name: "plugin type name text auto", Help: "插件", Actions: ice.Actions{
|
||||
CREATE: {Name: "create type name text", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Option(NAME, kit.Select(m.Option(TYPE), m.Option(NAME)))
|
||||
m.Option(TYPE, kit.Ext(m.Option(TYPE)))
|
||||
m.Cmdy(INSERT, m.PrefixKey(), "", HASH, m.OptionSimple("type,name,text"))
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) > 1 {
|
||||
m.Cmdy(SELECT, m.PrefixKey(), "", HASH, m.Config(SHORT), arg, func(value ice.Map) {
|
||||
m.Cmdy(kit.Keys(value[TEXT], value[NAME]), m.CommandKey(), arg[0], arg[1], kit.Select("", arg, 2), kit.Slice(arg, 3))
|
||||
})
|
||||
return
|
||||
}
|
||||
if HashSelect(m, arg...); len(arg) == 0 {
|
||||
m.Sort(TYPE)
|
||||
} else if len(arg) == 1 {
|
||||
m.DisplayStoryJSON()
|
||||
m.Echo(kit.Formats(m.Confv(m.Append(NAME), "meta.plug")))
|
||||
}
|
||||
}},
|
||||
}})
|
||||
Index.MergeCommands(ice.Commands{PLUGIN: {Name: "plugin type name text auto", Help: "插件", Actions: RenderAction()}})
|
||||
}
|
||||
|
@ -8,28 +8,31 @@ import (
|
||||
const RENDER = "render"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
RENDER: {Name: RENDER, Help: "渲染", Value: kit.Data(SHORT, TYPE, FIELD, "time,type,name,text")},
|
||||
}, Commands: ice.Commands{
|
||||
RENDER: {Name: "render type name text auto", Help: "渲染", Actions: ice.Actions{
|
||||
CREATE: {Name: "create type name text", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Option(NAME, kit.Select(m.Option(TYPE), m.Option(NAME)))
|
||||
m.Option(TYPE, kit.Ext(m.Option(TYPE)))
|
||||
m.Cmdy(INSERT, m.PrefixKey(), "", HASH, m.OptionSimple("type,name,text"))
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) > 1 {
|
||||
m.Cmdy(SELECT, m.PrefixKey(), "", HASH, m.Config(SHORT), arg, func(value ice.Map) {
|
||||
m.Cmdy(kit.Keys(value[TEXT], value[NAME]), m.CommandKey(), arg[0], arg[1], kit.Select("", arg, 2), kit.Slice(arg, 3))
|
||||
})
|
||||
return
|
||||
}
|
||||
if HashSelect(m, arg...); len(arg) == 0 {
|
||||
m.Sort(TYPE)
|
||||
} else if len(arg) == 1 {
|
||||
m.DisplayStoryJSON()
|
||||
m.Echo(kit.Formats(m.Confv(m.Append(NAME), "meta.plug")))
|
||||
Index.MergeCommands(ice.Commands{RENDER: {Name: "render type name text auto", Help: "渲染", Actions: RenderAction()}})
|
||||
}
|
||||
|
||||
func RenderAction(args ...ice.Any) ice.Actions {
|
||||
return ice.MergeAction(ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
if cs := m.Target().Configs; cs[m.CommandKey()] == nil {
|
||||
cs[m.CommandKey()] = &ice.Config{Value: kit.Data(SHORT, TYPE)}
|
||||
}
|
||||
}},
|
||||
}})
|
||||
CREATE: {Name: "create type name text", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Option(TYPE, kit.Ext(m.Option(TYPE)))
|
||||
m.Option(NAME, kit.Select(m.Option(TYPE), m.Option(NAME)))
|
||||
m.Cmdy(INSERT, m.PrefixKey(), "", HASH, m.OptionSimple("type,name,text"))
|
||||
}},
|
||||
SELECT: {Name: "select type name text auto", Help: "渲染", Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) > 1 {
|
||||
for _, k := range kit.Split(arg[0]) {
|
||||
HashSelect(m.Spawn(ice.OptionFields("")), k).Tables(func(value ice.Maps) {
|
||||
m.Cmdy(kit.Keys(value[TEXT], value[NAME]), m.CommandKey(), k, arg[1], kit.Select("", arg, 2), kit.Slice(arg, 3))
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
HashSelect(m, arg...)
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
@ -2,32 +2,10 @@ package mdb
|
||||
|
||||
import (
|
||||
ice "shylinux.com/x/icebergs"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
const SEARCH = "search"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
SEARCH: {Name: SEARCH, Help: "搜索", Value: kit.Data(SHORT, TYPE, FIELD, "time,type,name,text")},
|
||||
}, Commands: ice.Commands{
|
||||
SEARCH: {Name: "search type name text auto", Help: "搜索", Actions: ice.Actions{
|
||||
CREATE: {Name: "create type name text", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Option(NAME, kit.Select(m.Option(TYPE), m.Option(NAME)))
|
||||
m.Option(TYPE, kit.Ext(m.Option(TYPE)))
|
||||
m.Cmdy(INSERT, m.PrefixKey(), "", HASH, m.OptionSimple("type,name,text"))
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) > 1 {
|
||||
m.Cmdy(SELECT, m.PrefixKey(), "", HASH, m.Config(SHORT), kit.Slice(arg, 0, 1), func(value ice.Map) {
|
||||
m.OptionFields(kit.Select("ctx,cmd,type,name,text", kit.Select(m.OptionFields())))
|
||||
m.Cmdy(kit.Keys(value[TEXT], value[NAME]), m.CommandKey(), arg[0], arg[1], kit.Select("", arg, 2), kit.Slice(arg, 3))
|
||||
})
|
||||
return
|
||||
}
|
||||
if HashSelect(m, arg...); len(arg) == 0 {
|
||||
m.Sort(TYPE)
|
||||
}
|
||||
}},
|
||||
}})
|
||||
Index.MergeCommands(ice.Commands{SEARCH: {Name: "search type name text auto", Help: "搜索", Actions: RenderAction()}})
|
||||
}
|
||||
|
202
base/mdb/zone.go
202
base/mdb/zone.go
@ -2,63 +2,62 @@ package mdb
|
||||
|
||||
import (
|
||||
"encoding/csv"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
"shylinux.com/x/toolkits/logs"
|
||||
"shylinux.com/x/toolkits/miss"
|
||||
)
|
||||
|
||||
func _zone_fields(m *ice.Message) []string {
|
||||
return kit.Split(kit.Select("zone,id,time,type,name,text", m.OptionFields()))
|
||||
return kit.Split(kit.Select(ZONE_FIELD, m.OptionFields()))
|
||||
}
|
||||
func _zone_inputs(m *ice.Message, prefix, chain, zone string, field, value string) {
|
||||
if field == m.Conf(prefix, kit.Keys(chain, kit.Keym(SHORT))) {
|
||||
_hash_inputs(m, prefix, chain, field, value)
|
||||
return
|
||||
}
|
||||
h := _hash_select_fields(m, prefix, chain, zone, HASH)
|
||||
defer m.RLock(prefix, chain)()
|
||||
_list_inputs(m, prefix, _domain_chain(m, kit.Keys(chain, HASH, h)), field, value)
|
||||
}
|
||||
func _zone_insert(m *ice.Message, prefix, chain, zone string, arg ...string) {
|
||||
h := _hash_select_fields(m, prefix, chain, zone, HASH)
|
||||
if h == "" {
|
||||
h = _hash_insert(m, prefix, chain, m.Conf(prefix, kit.Keys(chain, kit.Keym(SHORT))), zone)
|
||||
}
|
||||
m.Assert(h != "")
|
||||
defer m.Lock(prefix, chain)()
|
||||
_list_insert(m, prefix, _domain_chain(m, kit.Keys(chain, HASH, h)), arg...)
|
||||
}
|
||||
func _zone_modify(m *ice.Message, prefix, chain, zone, id string, arg ...string) {
|
||||
h := _hash_select_fields(m, prefix, chain, zone, HASH)
|
||||
m.Assert(h != "")
|
||||
defer m.RLock(prefix, chain)()
|
||||
_list_modify(m, prefix, _domain_chain(m, kit.Keys(chain, HASH, h)), ID, id, arg...)
|
||||
}
|
||||
func _zone_select(m *ice.Message, prefix, chain, zone string, id string) {
|
||||
if zone == "" {
|
||||
_hash_select(m, prefix, chain, HASH, FOREACH)
|
||||
return
|
||||
}
|
||||
if zone == RANDOM {
|
||||
zone = RANDOMS
|
||||
}
|
||||
|
||||
fields := _zone_fields(m)
|
||||
cb := m.OptionCB(SELECT)
|
||||
m.Richs(prefix, chain, kit.Select(FOREACH, zone), func(key string, val ice.Map) {
|
||||
if val = kit.GetMeta(val); zone == "" {
|
||||
if m.OptionFields() == DETAIL {
|
||||
m.Push(DETAIL, val)
|
||||
} else {
|
||||
m.Push(key, val, fields)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
m.Grows(prefix, kit.Keys(chain, HASH, key), ID, id, func(index int, value ice.Map) {
|
||||
switch value = kit.GetMeta(value); cb := cb.(type) {
|
||||
case func(string, []string, ice.Map, ice.Map):
|
||||
cb(key, fields, value, val)
|
||||
case func(string, ice.Map, ice.Map):
|
||||
cb(key, value, val)
|
||||
case func(string, ice.Map):
|
||||
cb(key, value)
|
||||
case func(ice.Map):
|
||||
cb(value)
|
||||
case func(ice.Maps):
|
||||
res := ice.Maps{}
|
||||
for k, v := range value {
|
||||
res[k] = kit.Format(v)
|
||||
}
|
||||
cb(res)
|
||||
default:
|
||||
if m.FieldsIsDetail() {
|
||||
m.Push(DETAIL, value)
|
||||
} else {
|
||||
m.Push(key, value, fields, val)
|
||||
}
|
||||
}
|
||||
defer m.RLock(prefix, chain)()
|
||||
m.Richs(prefix, chain, kit.Select(FOREACH, zone), func(key string, val Map) {
|
||||
chain := kit.Keys(chain, HASH, key)
|
||||
defer m.RLock(prefix, chain)()
|
||||
m.Grows(prefix, chain, ID, id, func(value ice.Map) {
|
||||
_mdb_select(m, key, value, fields, val)
|
||||
})
|
||||
})
|
||||
}
|
||||
func _zone_export(m *ice.Message, prefix, chain, file string) {
|
||||
f, p, e := kit.Create(kit.Keys(file, CSV))
|
||||
f, p, e := miss.CreateFile(kit.Keys(file, CSV))
|
||||
m.Assert(e)
|
||||
defer f.Close()
|
||||
|
||||
@ -66,21 +65,24 @@ func _zone_export(m *ice.Message, prefix, chain, file string) {
|
||||
defer w.Flush()
|
||||
|
||||
fields := _zone_fields(m)
|
||||
fields = append(fields, EXTRA)
|
||||
if kit.IndexOf(fields, EXTRA) == -1 {
|
||||
fields = append(fields, EXTRA)
|
||||
}
|
||||
w.Write(fields)
|
||||
|
||||
keys := []string{}
|
||||
m.Richs(prefix, chain, FOREACH, func(key string, val ice.Map) {
|
||||
keys = append(keys, key)
|
||||
})
|
||||
sort.Strings(keys)
|
||||
m.Richs(prefix, chain, FOREACH, func(key string, val ice.Map) { keys = append(keys, key) })
|
||||
kit.Sort(keys)
|
||||
|
||||
count := 0
|
||||
defer m.Lock(prefix, chain)()
|
||||
for _, key := range keys {
|
||||
m.Richs(prefix, chain, key, func(key string, val ice.Map) {
|
||||
val = kit.GetMeta(val)
|
||||
|
||||
m.Grows(prefix, kit.Keys(chain, HASH, key), "", "", func(index int, value ice.Map) {
|
||||
chain := kit.Keys(chain, HASH, key)
|
||||
defer m.RLock(prefix, chain)()
|
||||
m.Grows(prefix, chain, "", "", func(value ice.Map) {
|
||||
value = kit.GetMeta(value)
|
||||
|
||||
list := []string{}
|
||||
@ -98,10 +100,8 @@ func _zone_export(m *ice.Message, prefix, chain, file string) {
|
||||
m.Echo(p)
|
||||
}
|
||||
func _zone_import(m *ice.Message, prefix, chain, file string) {
|
||||
f, e := os.Open(kit.Keys(file, CSV))
|
||||
if m.Warn(e) {
|
||||
return
|
||||
}
|
||||
f, e := miss.OpenFile(kit.Keys(file, CSV))
|
||||
m.Assert(e)
|
||||
defer f.Close()
|
||||
|
||||
r := csv.NewReader(f)
|
||||
@ -111,6 +111,7 @@ func _zone_import(m *ice.Message, prefix, chain, file string) {
|
||||
list := ice.Maps{}
|
||||
zkey := kit.Select(head[0], m.OptionFields())
|
||||
|
||||
defer m.Lock(prefix, chain)()
|
||||
for {
|
||||
line, e := r.Read()
|
||||
if e != nil {
|
||||
@ -135,7 +136,11 @@ func _zone_import(m *ice.Message, prefix, chain, file string) {
|
||||
list[zone] = m.Rich(prefix, chain, kit.Data(zkey, zone))
|
||||
}
|
||||
|
||||
m.Grow(prefix, kit.Keys(chain, HASH, list[zone]), data)
|
||||
func() {
|
||||
chain := kit.Keys(chain, HASH, list[zone])
|
||||
defer m.Lock(prefix, chain)()
|
||||
m.Grow(prefix, chain, data)
|
||||
}()
|
||||
count++
|
||||
}
|
||||
|
||||
@ -143,61 +148,36 @@ func _zone_import(m *ice.Message, prefix, chain, file string) {
|
||||
m.Echo("%d", count)
|
||||
}
|
||||
|
||||
const (
|
||||
ZONE_FIELD = "zone,id,time,type,name,text"
|
||||
)
|
||||
const ZONE = "zone"
|
||||
|
||||
func ZoneAction(args ...ice.Any) ice.Actions {
|
||||
_zone := func(m *ice.Message) string { return kit.Select(ZONE, m.Config(SHORT)) }
|
||||
|
||||
return ice.Actions{ice.CTX_INIT: AutoConfig(args...),
|
||||
INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
|
||||
arg[0] = strings.TrimPrefix(arg[0], "extra.")
|
||||
arg[0] = kit.Select(arg[0], m.Config(kit.Keys(ALIAS, arg[0])))
|
||||
switch arg[0] {
|
||||
case ice.POD:
|
||||
m.Cmdy("route")
|
||||
case ice.CTX:
|
||||
m.Cmdy("context")
|
||||
case ice.CMD:
|
||||
m.Cmdy("context", kit.Select(m.Option(ice.CTX), m.Option(kit.Keys(EXTRA, ice.CTX))), "command")
|
||||
case ice.ARG:
|
||||
|
||||
case "index":
|
||||
m.OptionFields(arg[0])
|
||||
m.Cmdy("command", SEARCH, "command", kit.Select("", arg, 1))
|
||||
|
||||
case _zone(m):
|
||||
m.Cmdy(INPUTS, m.PrefixKey(), "", HASH, arg)
|
||||
default:
|
||||
m.Cmdy(INPUTS, m.PrefixKey(), "", ZONE, m.Option(_zone(m)), arg)
|
||||
}
|
||||
ZoneInputs(m, arg)
|
||||
}},
|
||||
CREATE: {Name: "create zone", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(INSERT, m.PrefixKey(), "", HASH, arg)
|
||||
ZoneCreate(m, arg)
|
||||
}},
|
||||
REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(DELETE, m.PrefixKey(), "", HASH, m.OptionSimple(_zone(m)), arg)
|
||||
ZoneRemove(m, arg)
|
||||
}},
|
||||
INSERT: {Name: "insert", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) == 0 {
|
||||
arg = m.OptionSimple(_zone(m), m.Config(FIELD))
|
||||
}
|
||||
m.Cmdy(INSERT, m.PrefixKey(), "", HASH, _zone(m), arg[1])
|
||||
m.Cmdy(INSERT, m.PrefixKey(), "", ZONE, m.Option(_zone(m)), arg[2:])
|
||||
ZoneInsert(m, arg)
|
||||
}},
|
||||
MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(MODIFY, m.PrefixKey(), "", ZONE, m.Option(_zone(m)), m.Option(ID), arg)
|
||||
ZoneModify(m, arg)
|
||||
}},
|
||||
PLUGIN: {Name: "plugin extra.pod extra.ctx extra.cmd extra.arg", Help: "插件", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(MODIFY, m.PrefixKey(), "", ZONE, m.Option(_zone(m)), m.Option(ID), arg)
|
||||
SELECT: {Name: "select", Help: "列表", Hand: func(m *ice.Message, arg ...string) {
|
||||
ZoneSelect(m, arg...)
|
||||
}},
|
||||
EXPORT: {Name: "export", Help: "导出", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Option(ice.CACHE_LIMIT, "-1")
|
||||
m.OptionFields(_zone(m), m.Config(FIELD))
|
||||
m.Cmdy(EXPORT, m.PrefixKey(), "", ZONE)
|
||||
ZoneExport(m, arg)
|
||||
}},
|
||||
IMPORT: {Name: "import", Help: "导入", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.OptionFields(_zone(m))
|
||||
m.Cmdy(IMPORT, m.PrefixKey(), "", ZONE)
|
||||
ZoneImport(m, arg)
|
||||
}},
|
||||
PREV: {Name: "prev", Help: "上一页", Hand: func(m *ice.Message, arg ...string) {
|
||||
PrevPage(m, arg[0], arg[1:]...)
|
||||
@ -205,28 +185,56 @@ func ZoneAction(args ...ice.Any) ice.Actions {
|
||||
NEXT: {Name: "next", Help: "下一页", Hand: func(m *ice.Message, arg ...string) {
|
||||
NextPageLimit(m, arg[0], arg[1:]...)
|
||||
}},
|
||||
SELECT: {Name: "select", Help: "列表", Hand: func(m *ice.Message, arg ...string) {
|
||||
ZoneSelect(m, arg...)
|
||||
}},
|
||||
}
|
||||
}
|
||||
func ZoneShort(m *ice.Message) string {
|
||||
return kit.Select(ZONE, m.Config(SHORT), m.Config(SHORT) != UNIQ)
|
||||
}
|
||||
func ZoneField(m *ice.Message) string { return kit.Select(ZONE_FIELD, m.Config(FIELD)) }
|
||||
func ZoneArgs(m *ice.Message, arg ...Any) []string {
|
||||
return _mdb_args(m, ZoneField(m), arg...)
|
||||
}
|
||||
|
||||
func ZoneInputs(m *ice.Message, arg ...Any) {
|
||||
m.Cmdy(INPUTS, m.PrefixKey(), "", ZONE, ZoneArgs(m, arg...))
|
||||
}
|
||||
func ZoneCreate(m *ice.Message, arg ...Any) {
|
||||
m.Cmdy(INSERT, m.PrefixKey(), "", HASH, arg)
|
||||
}
|
||||
func ZoneRemove(m *ice.Message, arg ...Any) {
|
||||
m.Cmdy(DELETE, m.PrefixKey(), "", HASH, m.OptionSimple(ZoneShort(m)), arg)
|
||||
}
|
||||
func ZoneInsert(m *ice.Message, arg ...Any) {
|
||||
args := kit.Simple(arg...)
|
||||
m.Cmdy(INSERT, m.PrefixKey(), "", ZONE, args[1], ZoneArgs(m, args[2:]))
|
||||
}
|
||||
func ZoneModify(m *ice.Message, arg ...Any) {
|
||||
m.Cmdy(MODIFY, m.PrefixKey(), "", ZONE, m.Option(ZoneShort(m)), m.Option(ID), ZoneArgs(m, arg...))
|
||||
}
|
||||
func ZoneSelect(m *ice.Message, arg ...string) *ice.Message {
|
||||
arg = kit.Slice(arg, 0, 2)
|
||||
m.Fields(len(arg), kit.Fields(TIME, m.Config(SHORT), COUNT), m.Config(FIELD))
|
||||
if m.Cmdy(SELECT, m.PrefixKey(), "", ZONE, arg); kit.Select("", arg, 0) == "" {
|
||||
if m.Cmdy(SELECT, m.PrefixKey(), "", ZONE, arg, logs.FileLineMeta(logs.FileLine(-1, 3))); len(arg) == 0 {
|
||||
if m.Config(SHORT) != "" {
|
||||
m.Sort(m.Config(SHORT))
|
||||
}
|
||||
m.PushAction(REMOVE)
|
||||
}
|
||||
if len(arg) == 0 {
|
||||
m.PushAction(m.Config(ACTION), REMOVE)
|
||||
m.StatusTimeCount()
|
||||
}
|
||||
if len(arg) == 1 {
|
||||
m.StatusTimeCountTotal(m.Conf(m.PrefixKey(), kit.Keys(HASH, kit.Hashs(arg[0]), kit.Keym("count"))))
|
||||
} else if len(arg) == 1 {
|
||||
m.StatusTimeCountTotal(m.Conf("", kit.Keys(HASH, HashSelectFields(m, arg[0], HASH), kit.Keym(COUNT))))
|
||||
}
|
||||
return m
|
||||
}
|
||||
func ZoneExport(m *ice.Message, arg ...Any) {
|
||||
m.Cmdy(EXPORT, m.PrefixKey(), "", ZONE, arg)
|
||||
}
|
||||
func ZoneImport(m *ice.Message, arg ...Any) {
|
||||
m.Cmdy(IMPORT, m.PrefixKey(), "", ZONE, arg)
|
||||
}
|
||||
func ZoneSelectPage(m *ice.Message, arg ...string) *ice.Message {
|
||||
m.OptionPages(kit.Slice(arg, 2)...)
|
||||
return ZoneSelect(m, arg...)
|
||||
}
|
||||
func ZoneSelectAll(m *ice.Message, arg ...string) *ice.Message {
|
||||
m.Option(ice.CACHE_LIMIT, "-1")
|
||||
return ZoneSelect(m, arg...)
|
||||
|
111
base/nfs/cat.go
111
base/nfs/cat.go
@ -4,78 +4,41 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/aaa"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
type ReadCloser struct {
|
||||
r io.Reader
|
||||
}
|
||||
|
||||
func (r *ReadCloser) Read(buf []byte) (int, error) {
|
||||
return r.r.Read(buf)
|
||||
}
|
||||
func (r *ReadCloser) Close() error {
|
||||
if c, ok := r.r.(io.Closer); ok {
|
||||
return c.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func NewReadCloser(r io.Reader) *ReadCloser {
|
||||
return &ReadCloser{r: r}
|
||||
}
|
||||
|
||||
var rewriteList = []ice.Any{}
|
||||
|
||||
func AddRewrite(cb ice.Any) { rewriteList = append(rewriteList, cb) }
|
||||
|
||||
func _cat_right(m *ice.Message, name string) bool {
|
||||
return aaa.RoleRight(m, m.Option(ice.MSG_USERROLE), strings.Split(name, ice.PS)...)
|
||||
}
|
||||
func _cat_find(m *ice.Message, name string) io.ReadCloser {
|
||||
func _cat_find(m *ice.Message, name string) (io.ReadCloser, error) {
|
||||
if m.Option(CAT_CONTENT) != "" {
|
||||
return NewReadCloser(bytes.NewBufferString(m.Option(CAT_CONTENT)))
|
||||
return NewReadCloser(bytes.NewBufferString(m.Option(CAT_CONTENT))), nil
|
||||
}
|
||||
|
||||
// 模块回调
|
||||
for _, h := range rewriteList {
|
||||
switch h := h.(type) {
|
||||
case func(m *ice.Message, name string) io.ReadCloser:
|
||||
if r := h(m, name); r != nil {
|
||||
return r
|
||||
}
|
||||
case func(m *ice.Message, name string) []byte:
|
||||
if b := h(m, name); b != nil {
|
||||
return NewReadCloser(bytes.NewBuffer(b))
|
||||
}
|
||||
case func(m *ice.Message, name string) string:
|
||||
if s := h(m, name); s != "" {
|
||||
return NewReadCloser(bytes.NewBufferString(s))
|
||||
}
|
||||
default:
|
||||
m.Error(true, ice.ErrNotImplement)
|
||||
return OpenFile(m, path.Join(m.Option(DIR_ROOT), name))
|
||||
}
|
||||
func _cat_size(m *ice.Message, p string) (nline int) {
|
||||
if f, e := OpenFile(m, p); m.Warn(e) {
|
||||
defer f.Close()
|
||||
for bio := bufio.NewScanner(f); bio.Scan(); nline++ {
|
||||
bio.Text()
|
||||
}
|
||||
}
|
||||
|
||||
// 本地文件
|
||||
if f, e := os.Open(path.Join(m.Option(DIR_ROOT), name)); e == nil {
|
||||
return f
|
||||
return nline
|
||||
}
|
||||
func _cat_hash(m *ice.Message, p string) string {
|
||||
if f, e := OpenFile(m, p); !m.Warn(e) {
|
||||
defer f.Close()
|
||||
return kit.Hashs(f)
|
||||
}
|
||||
return nil
|
||||
return ""
|
||||
}
|
||||
func _cat_list(m *ice.Message, name string) {
|
||||
if m.Warn(!_cat_right(m, name), ice.ErrNotRight) {
|
||||
if !m.Right(m, name) {
|
||||
return // 没有权限
|
||||
}
|
||||
|
||||
f := _cat_find(m, name)
|
||||
if m.Warn(f == nil, ice.ErrNotFound, name) {
|
||||
f, e := _cat_find(m, name)
|
||||
if m.Warn(e, ice.ErrNotFound, name) {
|
||||
return // 没有文件
|
||||
}
|
||||
defer f.Close()
|
||||
@ -97,15 +60,15 @@ func _cat_list(m *ice.Message, name string) {
|
||||
for bio := bufio.NewScanner(f); bio.Scan(); {
|
||||
cb(bio.Text())
|
||||
}
|
||||
|
||||
case func([]string, string):
|
||||
for bio := bufio.NewScanner(f); bio.Scan(); {
|
||||
cb(kit.Split(bio.Text()), bio.Text())
|
||||
}
|
||||
|
||||
default:
|
||||
buf := make([]byte, ice.MOD_BUFS)
|
||||
for begin := 0; true; {
|
||||
if n, e := f.Read(buf[begin:]); !m.Warn(e, ice.ErrNotFound, name) {
|
||||
case nil:
|
||||
buf, begin := make([]byte, ice.MOD_BUFS), 0
|
||||
for {
|
||||
if n, e := f.Read(buf[begin:]); !m.Warn(e, ice.ErrNotValid, name) {
|
||||
m.Log_IMPORT(FILE, name, SIZE, n)
|
||||
if begin += n; begin < len(buf) {
|
||||
buf = buf[:begin]
|
||||
@ -117,6 +80,8 @@ func _cat_list(m *ice.Message, name string) {
|
||||
}
|
||||
}
|
||||
m.Echo(string(buf))
|
||||
default:
|
||||
m.ErrorNotImplement(cb)
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,6 +90,7 @@ const (
|
||||
TEMPLATE = "template"
|
||||
WEBSITE = "website"
|
||||
|
||||
STDIO = "stdio"
|
||||
SOURCE = "source"
|
||||
SCRIPT = "script"
|
||||
BINARY = "binary"
|
||||
@ -155,15 +121,15 @@ const (
|
||||
YML = "yml"
|
||||
ZML = "zml"
|
||||
|
||||
PNG = "png"
|
||||
JPG = "jpg"
|
||||
MP4 = "mp4"
|
||||
|
||||
PWD = "./"
|
||||
PS = ice.PS
|
||||
PT = ice.PT
|
||||
)
|
||||
|
||||
const (
|
||||
PATH = "path"
|
||||
FILE = "file"
|
||||
LINE = "line"
|
||||
SIZE = "size"
|
||||
)
|
||||
const CAT = "cat"
|
||||
|
||||
func init() {
|
||||
@ -177,20 +143,13 @@ func init() {
|
||||
),
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
CAT: {Name: "cat path auto", Help: "文件", Actions: ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmd(mdb.RENDER, mdb.CREATE, m.CommandKey(), m.PrefixKey())
|
||||
}},
|
||||
mdb.RENDER: {Name: "render type name text", Help: "渲染", Hand: func(m *ice.Message, arg ...string) {
|
||||
_cat_list(m, path.Join(arg[2], arg[1]))
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
CAT: {Name: "cat path auto", Help: "文件", Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) == 0 || strings.HasSuffix(arg[0], ice.PS) {
|
||||
m.Cmdy(DIR, arg)
|
||||
return
|
||||
}
|
||||
if m.Option(DIR_ROOT) != "" {
|
||||
m.Info("dir_root: %v", m.Option(DIR_ROOT))
|
||||
m.Log_SELECT(DIR_ROOT, m.Option(DIR_ROOT))
|
||||
}
|
||||
_cat_list(m, arg[0])
|
||||
}},
|
||||
|
263
base/nfs/dir.go
263
base/nfs/dir.go
@ -1,9 +1,6 @@
|
||||
package nfs
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/sha1"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
@ -15,57 +12,38 @@ import (
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
func _dir_size(m *ice.Message, p string) int {
|
||||
if ls, e := ReadDir(m, p); !m.Warn(e) {
|
||||
return len(ls)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
func _dir_hash(m *ice.Message, p string) string {
|
||||
if ls, e := ReadDir(m, p); !m.Warn(e) {
|
||||
meta := []string{}
|
||||
for _, s := range ls {
|
||||
meta = append(meta, kit.Format("%s%d%s", s.Name(), s.Size(), s.ModTime()))
|
||||
}
|
||||
return kit.Hashs(meta)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
func _dir_list(m *ice.Message, root string, name string, level int, deep bool, dir_type string, dir_reg *regexp.Regexp, fields []string) *ice.Message {
|
||||
if !_cat_right(m, path.Join(root, name)) {
|
||||
if !m.Right(m, path.Join(root, name)) {
|
||||
return m // 没有权限
|
||||
}
|
||||
|
||||
if len(ice.Info.Pack) > 0 && m.Option(DIR_PACK) == ice.TRUE {
|
||||
for k, b := range ice.Info.Pack {
|
||||
p := strings.TrimPrefix(k, root)
|
||||
if !strings.HasPrefix(p, name) {
|
||||
if p = strings.TrimPrefix(k, root+ice.PS); !strings.HasPrefix(p, name) {
|
||||
if p = strings.TrimPrefix(k, ice.PS); !strings.HasPrefix(p, name) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m.Debug("dir binpack %s", p)
|
||||
for _, field := range fields {
|
||||
switch field {
|
||||
case PATH:
|
||||
m.Push(field, p)
|
||||
case SIZE:
|
||||
m.Push(field, len(b))
|
||||
default:
|
||||
m.Push(field, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
return m // 打包文件
|
||||
}
|
||||
|
||||
list, e := ioutil.ReadDir(path.Join(root, name))
|
||||
list, e := ReadDir(m, path.Join(root, name))
|
||||
if e != nil { // 单个文件
|
||||
ls, _ := ioutil.ReadDir(path.Dir(path.Join(root, name)))
|
||||
for _, k := range ls {
|
||||
if k.Name() == path.Base(name) {
|
||||
list = append(list, k)
|
||||
ls, _ := ReadDir(m, path.Dir(path.Join(root, name)))
|
||||
for _, s := range ls {
|
||||
if s.Name() == path.Base(name) {
|
||||
list = append(list, s)
|
||||
}
|
||||
}
|
||||
name = path.Dir(name)
|
||||
}
|
||||
|
||||
// 文件排序
|
||||
for i := 0; i < len(list)-1; i++ {
|
||||
for j := i + 1; j < len(list); j++ {
|
||||
if list[i].Name() > list[j].Name() {
|
||||
list[i], list[j] = list[j], list[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, f := range list {
|
||||
if f.Name() == ice.PT || f.Name() == ".." {
|
||||
continue
|
||||
@ -74,7 +52,7 @@ func _dir_list(m *ice.Message, root string, name string, level int, deep bool, d
|
||||
continue
|
||||
}
|
||||
|
||||
p := path.Join(root, name, f.Name())
|
||||
p, pp := path.Join(root, name, f.Name()), path.Join(name, f.Name())
|
||||
isDir := f.IsDir() || kit.IsDir(p)
|
||||
if !(dir_type == TYPE_CAT && isDir || dir_type == TYPE_DIR && !isDir) && (dir_reg == nil || dir_reg.MatchString(f.Name())) {
|
||||
switch cb := m.OptionCB(DIR).(type) {
|
||||
@ -86,7 +64,7 @@ func _dir_list(m *ice.Message, root string, name string, level int, deep bool, d
|
||||
continue
|
||||
case nil:
|
||||
default:
|
||||
m.Error(true, "what: %v: %v", ice.ErrNotImplement, cb)
|
||||
m.ErrorNotImplement(cb)
|
||||
}
|
||||
|
||||
for _, field := range fields {
|
||||
@ -96,78 +74,54 @@ func _dir_list(m *ice.Message, root string, name string, level int, deep bool, d
|
||||
case mdb.TYPE:
|
||||
m.Push(field, kit.Select(CAT, DIR, isDir))
|
||||
|
||||
case "tree":
|
||||
case TREE:
|
||||
if level == 0 {
|
||||
m.Push(field, f.Name())
|
||||
} else {
|
||||
m.Push(field, strings.Repeat("| ", level-1)+"|-"+f.Name())
|
||||
}
|
||||
case "full":
|
||||
m.Push(field, path.Join(root, name, f.Name())+kit.Select("", ice.PS, isDir))
|
||||
case FULL:
|
||||
m.Push(field, p+kit.Select("", ice.PS, isDir))
|
||||
case PATH:
|
||||
m.Push(field, path.Join(name, f.Name())+kit.Select("", ice.PS, isDir))
|
||||
m.Push(field, pp+kit.Select("", ice.PS, isDir))
|
||||
case FILE:
|
||||
m.Push(field, f.Name()+kit.Select("", ice.PS, isDir))
|
||||
case mdb.NAME:
|
||||
case NAME:
|
||||
m.Push(field, f.Name())
|
||||
|
||||
case SIZE:
|
||||
if isDir {
|
||||
if ls, e := ioutil.ReadDir(path.Join(root, name, f.Name())); e == nil {
|
||||
m.Push(field, len(ls))
|
||||
} else {
|
||||
m.Push(field, 0)
|
||||
}
|
||||
m.Push(field, _dir_size(m, p))
|
||||
} else {
|
||||
m.Push(field, kit.FmtSize(f.Size()))
|
||||
}
|
||||
case LINE:
|
||||
if isDir {
|
||||
if ls, e := ioutil.ReadDir(path.Join(root, name, f.Name())); e == nil {
|
||||
m.Push(field, len(ls))
|
||||
} else {
|
||||
m.Push(field, 0)
|
||||
}
|
||||
m.Push(field, _dir_size(m, p))
|
||||
} else {
|
||||
nline := 0
|
||||
if f, e := os.Open(p); m.Assert(e) {
|
||||
defer f.Close()
|
||||
for bio := bufio.NewScanner(f); bio.Scan(); nline++ {
|
||||
bio.Text()
|
||||
}
|
||||
}
|
||||
m.Push(field, nline)
|
||||
m.Push(field, _cat_size(m, p))
|
||||
}
|
||||
case mdb.HASH, "hashs":
|
||||
var h [20]byte
|
||||
h := ""
|
||||
if isDir {
|
||||
if d, e := ioutil.ReadDir(p); m.Assert(e) {
|
||||
meta := []string{}
|
||||
for _, v := range d {
|
||||
meta = append(meta, kit.Format("%s%d%s", v.Name(), v.Size(), v.ModTime()))
|
||||
}
|
||||
kit.Sort(meta)
|
||||
h = sha1.Sum([]byte(strings.Join(meta, "")))
|
||||
}
|
||||
h = _dir_hash(m, p)
|
||||
} else {
|
||||
if f, e := ioutil.ReadFile(path.Join(name, f.Name())); m.Assert(e) {
|
||||
h = sha1.Sum(f)
|
||||
}
|
||||
h = _cat_hash(m, p)
|
||||
}
|
||||
|
||||
m.Push(mdb.HASH, kit.Select(kit.Format(h[:6]), kit.Format(h[:]), field == mdb.HASH))
|
||||
m.Debug("what %v %v", h, p)
|
||||
m.Push(mdb.HASH, kit.Select(h[:6], h[:], field == mdb.HASH))
|
||||
case mdb.LINK:
|
||||
m.PushDownload(mdb.LINK, kit.Select("", f.Name(), !isDir), path.Join(root, name, f.Name()))
|
||||
m.PushDownload(mdb.LINK, kit.Select("", f.Name(), !isDir), p)
|
||||
case mdb.SHOW:
|
||||
switch p := m.MergeURL2("/share/local/"+path.Join(name, f.Name()), ice.POD, m.Option(ice.MSG_USERPOD)); kit.Ext(f.Name()) {
|
||||
case "png", "jpg":
|
||||
switch p := m.MergeURL2("/share/local/"+p, ice.POD, m.Option(ice.MSG_USERPOD)); kit.Ext(f.Name()) {
|
||||
case PNG, JPG:
|
||||
m.PushImages(field, p)
|
||||
case "mp4":
|
||||
case MP4:
|
||||
m.PushVideos(field, p)
|
||||
default:
|
||||
m.Push(field, "")
|
||||
}
|
||||
case "action":
|
||||
case mdb.ACTION:
|
||||
if m.IsCliUA() || m.Option(ice.MSG_USERROLE) == aaa.VOID {
|
||||
break
|
||||
}
|
||||
@ -178,27 +132,65 @@ func _dir_list(m *ice.Message, root string, name string, level int, deep bool, d
|
||||
}
|
||||
}
|
||||
|
||||
switch f.Name() {
|
||||
case "node_modules", "pluged", "target", "trash":
|
||||
continue
|
||||
}
|
||||
|
||||
if deep && isDir {
|
||||
_dir_list(m, root, path.Join(name, f.Name()), level+1, deep, dir_type, dir_reg, fields)
|
||||
switch f.Name() {
|
||||
case "node_modules", "pluged", "target", "trash":
|
||||
continue // 禁用递归
|
||||
}
|
||||
|
||||
_dir_list(m, root, pp, level+1, deep, dir_type, dir_reg, fields)
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
func _dir_search(m *ice.Message, kind, name string) {
|
||||
msg := _dir_list(m.Spawn(), PWD, "", 0, true, TYPE_BOTH, nil, kit.Split("time,type,name"))
|
||||
msg.Tables(func(value ice.Maps) {
|
||||
if !strings.Contains(value[mdb.NAME], name) {
|
||||
return
|
||||
}
|
||||
if value[mdb.TYPE] == CAT {
|
||||
value[mdb.TYPE] = kit.Ext(value[mdb.NAME])
|
||||
}
|
||||
m.PushSearch(value)
|
||||
|
||||
const (
|
||||
TYPE_ALL = "all"
|
||||
TYPE_CAT = "cat"
|
||||
TYPE_DIR = "dir"
|
||||
TYPE_BOTH = "both"
|
||||
)
|
||||
const (
|
||||
DIR_ROOT = "dir_root"
|
||||
DIR_TYPE = "dir_type"
|
||||
DIR_DEEP = "dir_deep"
|
||||
DIR_REG = "dir_reg"
|
||||
|
||||
DIR_DEF_FIELDS = "time,path,size,action"
|
||||
DIR_WEB_FIELDS = "time,size,path,action,link"
|
||||
DIR_CLI_FIELDS = "path,size,time"
|
||||
)
|
||||
const (
|
||||
ROOT = "root"
|
||||
TREE = "tree"
|
||||
FULL = "full"
|
||||
PATH = "path"
|
||||
FILE = "file"
|
||||
NAME = "name"
|
||||
SIZE = "size"
|
||||
LINE = "line"
|
||||
)
|
||||
const DIR = "dir"
|
||||
|
||||
func init() {
|
||||
Index.MergeCommands(ice.Commands{
|
||||
DIR: {Name: "dir path field auto upload", Help: "目录", Actions: ice.Actions{
|
||||
mdb.UPLOAD: {Name: "upload", Help: "上传", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Upload(m.Option(PATH))
|
||||
}},
|
||||
TRASH: {Name: "trash", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(TRASH, m.Option(PATH))
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
if m.Option(DIR_ROOT) != "" {
|
||||
m.Log_SELECT(DIR_ROOT, m.Option(DIR_ROOT))
|
||||
}
|
||||
_dir_list(m, kit.Select(PWD, m.Option(DIR_ROOT)), kit.Select(PWD, arg, 0),
|
||||
0, m.Option(DIR_DEEP) == ice.TRUE, kit.Select(TYPE_BOTH, m.Option(DIR_TYPE)), kit.Regexp(m.Option(DIR_REG)),
|
||||
kit.Split(kit.Select(kit.Select(DIR_DEF_FIELDS, m.OptionFields()), kit.Join(kit.Slice(arg, 1)))))
|
||||
m.SortTimeR(mdb.TIME)
|
||||
m.StatusTimeCount()
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
||||
@ -210,66 +202,3 @@ func Dir(m *ice.Message, sort string) *ice.Message {
|
||||
m.Copy(m.Cmd(DIR, PWD).Sort(sort))
|
||||
return m
|
||||
}
|
||||
func MkdirAll(m *ice.Message, p string) error {
|
||||
m.Log_EXPORT("mkdir", "dir", p)
|
||||
return os.MkdirAll(p, ice.MOD_DIR)
|
||||
}
|
||||
|
||||
const (
|
||||
TYPE_ALL = "all"
|
||||
TYPE_CAT = "cat"
|
||||
TYPE_DIR = "dir"
|
||||
TYPE_BOTH = "both"
|
||||
)
|
||||
const (
|
||||
DIR_PACK = "dir_pack"
|
||||
DIR_ROOT = "dir_root"
|
||||
DIR_TYPE = "dir_type"
|
||||
DIR_DEEP = "dir_deep"
|
||||
DIR_REG = "dir_reg"
|
||||
|
||||
DIR_DEF_FIELDS = "time,path,size,action"
|
||||
DIR_WEB_FIELDS = "time,size,path,action,link"
|
||||
DIR_CLI_FIELDS = "path,size,time"
|
||||
)
|
||||
const DIR = "dir"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
DIR: {Name: DIR, Help: "目录", Value: kit.Data()},
|
||||
}, Commands: ice.Commands{
|
||||
DIR: {Name: "dir path field... auto upload", Help: "目录", Actions: ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmd(mdb.RENDER, mdb.CREATE, m.CommandKey(), m.PrefixKey())
|
||||
}},
|
||||
mdb.SEARCH: {Name: "search type name", Help: "搜索", Hand: func(m *ice.Message, arg ...string) {
|
||||
if arg[0] == mdb.FOREACH {
|
||||
return
|
||||
}
|
||||
_dir_search(m, arg[0], arg[1])
|
||||
}},
|
||||
mdb.RENDER: {Name: "render type name text", Help: "渲染", Hand: func(m *ice.Message, arg ...string) {
|
||||
_dir_list(m, arg[2], arg[1], 0, m.Option(DIR_DEEP) == ice.TRUE, kit.Select(TYPE_BOTH, m.Option(DIR_TYPE)),
|
||||
nil, kit.Split(kit.Select("time,size,type,path", m.OptionFields())))
|
||||
}},
|
||||
mdb.UPLOAD: {Name: "upload", Help: "上传", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Upload(m.Option(PATH))
|
||||
}},
|
||||
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
|
||||
os.Remove(m.Option(PATH))
|
||||
}},
|
||||
TRASH: {Name: "trash", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(TRASH, m.Option(PATH))
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
if m.Option(DIR_ROOT) != "" {
|
||||
m.Info("dir_root: %v", m.Option(DIR_ROOT))
|
||||
}
|
||||
_dir_list(m, kit.Select(PWD, m.Option(DIR_ROOT)), kit.Select(PWD, arg, 0),
|
||||
0, m.Option(DIR_DEEP) == ice.TRUE, kit.Select(TYPE_BOTH, m.Option(DIR_TYPE)), kit.Regexp(m.Option(DIR_REG)),
|
||||
kit.Split(kit.Select(kit.Select(DIR_DEF_FIELDS, m.OptionFields()), kit.Join(kit.Slice(arg, 1)))))
|
||||
m.SortTimeR(mdb.TIME)
|
||||
m.StatusTimeCount()
|
||||
}},
|
||||
}})
|
||||
}
|
||||
|
@ -9,11 +9,11 @@ import (
|
||||
const FIND = "find"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
FIND: {Name: "find path word auto", Help: "搜索", Hand: func(m *ice.Message, arg ...string) {
|
||||
for _, file := range strings.Split(m.Cmdx("cli.system", FIND, PWD, "-name", arg[1]), ice.NL) {
|
||||
m.Push(FILE, strings.TrimPrefix(file, PWD))
|
||||
}
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -5,10 +5,10 @@ import ice "shylinux.com/x/icebergs"
|
||||
const GREP = "grep"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
GREP: {Name: "grep path word auto", Help: "搜索", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Option("cmd_dir", arg[0])
|
||||
m.Split(m.Cmdx("cli.system", GREP, "--exclude=.[a-z]*", "--exclude-dir=.[a-z]*", "-rni", arg[1]), "file:line:text", ":")
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
100
base/nfs/nfs.go
100
base/nfs/nfs.go
@ -1,9 +1,107 @@
|
||||
package nfs
|
||||
|
||||
import ice "shylinux.com/x/icebergs"
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/toolkits/file"
|
||||
)
|
||||
|
||||
var Index = &ice.Context{Name: "nfs", Help: "存储模块"}
|
||||
|
||||
func init() {
|
||||
ice.Index.Register(Index, nil, TAR, CAT, DIR, DEFS, SAVE, PUSH, COPY, LINK, TAIL, TRASH, GREP)
|
||||
}
|
||||
|
||||
var DiskFile = file.NewDiskFile()
|
||||
var PackFile = file.NewPackFile()
|
||||
|
||||
func init() { file.Init(ice.Pulse.OptionFiles(DiskFile, PackFile)) }
|
||||
|
||||
func StatFile(m *ice.Message, p string) (os.FileInfo, error) {
|
||||
file := m.OptionFiles()
|
||||
return file.StatFile(p)
|
||||
}
|
||||
func OpenFile(m *ice.Message, p string) (io.ReadCloser, error) {
|
||||
file := m.OptionFiles()
|
||||
return file.OpenFile(p)
|
||||
}
|
||||
func CreateFile(m *ice.Message, p string) (io.WriteCloser, string, error) {
|
||||
file := m.OptionFiles()
|
||||
return file.CreateFile(p)
|
||||
}
|
||||
func AppendFile(m *ice.Message, p string) (io.ReadWriteCloser, string, error) {
|
||||
file := m.OptionFiles()
|
||||
w, e := file.AppendFile(p)
|
||||
return w, p, e
|
||||
}
|
||||
func WriteFile(m *ice.Message, p string, b []byte) error {
|
||||
file := m.OptionFiles()
|
||||
return file.WriteFile(p, b)
|
||||
}
|
||||
|
||||
func ReadDir(m *ice.Message, p string) ([]os.FileInfo, error) {
|
||||
file := m.OptionFiles()
|
||||
list, e := file.ReadDir(p)
|
||||
for i := 0; i < len(list)-1; i++ {
|
||||
for j := i + 1; j < len(list); j++ {
|
||||
if list[i].Name() > list[j].Name() {
|
||||
list[i], list[j] = list[j], list[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
return list, e
|
||||
}
|
||||
func MkdirAll(m *ice.Message, p string) error {
|
||||
file := m.OptionFiles()
|
||||
return file.MkdirAll(p, ice.MOD_DIR)
|
||||
}
|
||||
func RemoveAll(m *ice.Message, p string) error {
|
||||
file := m.OptionFiles()
|
||||
return file.RemoveAll(p)
|
||||
}
|
||||
func Remove(m *ice.Message, p string) error {
|
||||
file := m.OptionFiles()
|
||||
return file.Remove(p)
|
||||
}
|
||||
func Rename(m *ice.Message, oldname string, newname string) error {
|
||||
file := m.OptionFiles()
|
||||
return file.Rename(oldname, newname)
|
||||
}
|
||||
func Symlink(m *ice.Message, oldname string, newname string) error {
|
||||
file := m.OptionFiles()
|
||||
return file.Symlink(oldname, newname)
|
||||
}
|
||||
func Link(m *ice.Message, oldname string, newname string) error {
|
||||
file := m.OptionFiles()
|
||||
return file.Link(oldname, newname)
|
||||
}
|
||||
func Close(m *ice.Message) {
|
||||
file := m.OptionFiles()
|
||||
file.Close()
|
||||
}
|
||||
|
||||
func ExistsFile(m *ice.Message, p string) bool {
|
||||
file := m.OptionFiles()
|
||||
if _, e := file.StatFile(p); e == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func ReadFile(m *ice.Message, p string) ([]byte, error) {
|
||||
file := m.OptionFiles()
|
||||
if f, e := file.OpenFile(p); e == nil {
|
||||
return ioutil.ReadAll(f)
|
||||
} else {
|
||||
return nil, e
|
||||
}
|
||||
}
|
||||
|
||||
func NewWriteCloser(w func([]byte) (int, error), c func() error) io.WriteCloser {
|
||||
return file.NewWriteCloser(w, c)
|
||||
}
|
||||
func NewReadCloser(r io.Reader) io.ReadCloser {
|
||||
return file.NewReadCloser(r)
|
||||
}
|
||||
|
63
base/nfs/pack.go
Normal file
63
base/nfs/pack.go
Normal file
@ -0,0 +1,63 @@
|
||||
package nfs
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
const PACK = "pack"
|
||||
|
||||
func init() {
|
||||
pack := PackFile
|
||||
Index.MergeCommands(ice.Commands{
|
||||
PACK: {Name: "pack path auto upload create", Help: "文件系统", Actions: ice.Actions{
|
||||
mdb.UPLOAD: {Name: "upload", Help: "上传", Hand: func(m *ice.Message, arg ...string) {
|
||||
if b, h, e := m.R.FormFile(mdb.UPLOAD); m.Assert(e) {
|
||||
defer b.Close()
|
||||
if f, p, e := pack.CreateFile(path.Join(m.Option(PATH), h.Filename)); m.Assert(e) {
|
||||
defer f.Close()
|
||||
if n, e := io.Copy(f, b); e == nil {
|
||||
m.Log_IMPORT(FILE, p, SIZE, n)
|
||||
}
|
||||
}
|
||||
}
|
||||
}},
|
||||
mdb.CREATE: {Name: "create path=h1/h2/hi.txt text=hello", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
|
||||
if f, _, e := pack.CreateFile(m.Option(PATH)); e == nil {
|
||||
defer f.Close()
|
||||
f.Write([]byte(m.Option(mdb.TEXT)))
|
||||
}
|
||||
}},
|
||||
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
|
||||
pack.Remove(path.Clean(m.Option(PATH)))
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
p := kit.Select("", arg, 0)
|
||||
if p != "" && !strings.HasSuffix(p, PS) {
|
||||
if f, e := pack.OpenFile(p); e == nil {
|
||||
defer f.Close()
|
||||
if b, e := ioutil.ReadAll(f); e == nil {
|
||||
m.Echo(string(b))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
ls, _ := pack.ReadDir(p)
|
||||
for _, f := range ls {
|
||||
m.Push(mdb.TIME, f.ModTime().Format(ice.MOD_TIME))
|
||||
m.Push(PATH, path.Join(p, f.Name())+kit.Select("", PS, f.IsDir()))
|
||||
m.Push(SIZE, f.Size())
|
||||
}
|
||||
m.Sort("time,path")
|
||||
m.PushAction(mdb.REMOVE)
|
||||
m.StatusTimeCount()
|
||||
}},
|
||||
})
|
||||
}
|
@ -1,17 +1,16 @@
|
||||
package nfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
func _defs_file(m *ice.Message, name string, text ...string) {
|
||||
if kit.FileExists(path.Join(m.Option(DIR_ROOT), name)) {
|
||||
if ExistsFile(m, path.Join(m.Option(DIR_ROOT), name)) {
|
||||
return
|
||||
}
|
||||
for i, v := range text {
|
||||
@ -21,11 +20,11 @@ func _defs_file(m *ice.Message, name string, text ...string) {
|
||||
_save_file(m, name, text...)
|
||||
}
|
||||
func _save_file(m *ice.Message, name string, text ...string) {
|
||||
if f, p, e := kit.Create(path.Join(m.Option(DIR_ROOT), name)); m.Assert(e) {
|
||||
if f, p, e := CreateFile(m, path.Join(m.Option(DIR_ROOT), name)); m.Assert(e) {
|
||||
defer f.Close()
|
||||
|
||||
for _, v := range text {
|
||||
if n, e := f.WriteString(v); m.Assert(e) {
|
||||
if n, e := fmt.Fprint(f, v); m.Assert(e) {
|
||||
m.Log_EXPORT(FILE, p, SIZE, n)
|
||||
}
|
||||
}
|
||||
@ -33,16 +32,11 @@ func _save_file(m *ice.Message, name string, text ...string) {
|
||||
}
|
||||
}
|
||||
func _push_file(m *ice.Message, name string, text ...string) {
|
||||
p := path.Join(m.Option(DIR_ROOT), name)
|
||||
if strings.Contains(p, ice.PS) {
|
||||
MkdirAll(m, path.Dir(p))
|
||||
}
|
||||
|
||||
if f, e := os.OpenFile(p, os.O_WRONLY|os.O_APPEND|os.O_CREATE, ice.MOD_FILE); m.Assert(e) {
|
||||
if f, p, e := AppendFile(m, path.Join(m.Option(DIR_ROOT), name)); m.Assert(e) {
|
||||
defer f.Close()
|
||||
|
||||
for _, k := range text {
|
||||
if n, e := f.WriteString(k); m.Assert(e) {
|
||||
if n, e := fmt.Fprint(f, k); m.Assert(e) {
|
||||
m.Log_EXPORT(FILE, p, SIZE, n)
|
||||
}
|
||||
}
|
||||
@ -50,11 +44,11 @@ func _push_file(m *ice.Message, name string, text ...string) {
|
||||
}
|
||||
}
|
||||
func _copy_file(m *ice.Message, name string, from ...string) {
|
||||
if f, p, e := kit.Create(path.Join(m.Option(DIR_ROOT), name)); m.Assert(e) {
|
||||
if f, p, e := CreateFile(m, path.Join(m.Option(DIR_ROOT), name)); m.Assert(e) {
|
||||
defer f.Close()
|
||||
|
||||
for _, v := range from {
|
||||
if s, e := os.Open(v); !m.Warn(e, ice.ErrNotFound, name) {
|
||||
if s, e := OpenFile(m, path.Join(m.Option(DIR_ROOT), v)); !m.Warn(e, ice.ErrNotFound, name) {
|
||||
defer s.Close()
|
||||
|
||||
if n, e := io.Copy(f, s); !m.Warn(e, ice.ErrNotFound, name) {
|
||||
@ -67,23 +61,28 @@ func _copy_file(m *ice.Message, name string, from ...string) {
|
||||
}
|
||||
}
|
||||
func _link_file(m *ice.Message, name string, from string) {
|
||||
if from == "" || m.Warn(!kit.FileExists(from), ice.ErrNotFound, from) {
|
||||
if m.Warn(from == "", ice.ErrNotValid, from) {
|
||||
return
|
||||
}
|
||||
os.Remove(name)
|
||||
name = path.Join(m.Option(DIR_ROOT), name)
|
||||
from = path.Join(m.Option(DIR_ROOT), from)
|
||||
if m.Warn(!ExistsFile(m, from), ice.ErrNotFound, from) {
|
||||
return
|
||||
}
|
||||
Remove(m, name)
|
||||
MkdirAll(m, path.Dir(name))
|
||||
if e := os.Link(from, name); e != nil {
|
||||
if m.Warn(os.Symlink(from, name), ice.ErrWarn, from) {
|
||||
if m.Warn(Link(m, from, name)) {
|
||||
if m.Warn(Symlink(m, from, name), ice.ErrWarn, from) {
|
||||
return
|
||||
}
|
||||
}
|
||||
m.Log_EXPORT(name, "from", from)
|
||||
m.Log_EXPORT(FILE, name, FROM, from)
|
||||
m.Echo(name)
|
||||
|
||||
}
|
||||
|
||||
const (
|
||||
CONTENT = "content"
|
||||
FROM = "from"
|
||||
)
|
||||
const DEFS = "defs"
|
||||
const SAVE = "save"
|
||||
@ -92,7 +91,7 @@ const COPY = "copy"
|
||||
const LINK = "link"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
DEFS: {Name: "defs file text...", Help: "默认", Hand: func(m *ice.Message, arg ...string) {
|
||||
_defs_file(m, arg[0], arg[1:]...)
|
||||
}},
|
||||
@ -119,5 +118,5 @@ func init() {
|
||||
LINK: {Name: "link file from", Help: "链接", Hand: func(m *ice.Message, arg ...string) {
|
||||
_link_file(m, arg[0], arg[1])
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -36,11 +36,7 @@ func _tail_count(m *ice.Message, name string) string {
|
||||
const TAIL = "tail"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
TAIL: {Name: TAIL, Help: "日志流", Value: kit.Data(
|
||||
mdb.SHORT, mdb.NAME, mdb.FIELD, "time,id,file,text",
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
TAIL: {Name: "tail name id auto page filter:text create", Help: "日志流", Actions: ice.MergeAction(ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Richs(TAIL, "", mdb.FOREACH, func(key string, value ice.Map) {
|
||||
@ -62,7 +58,7 @@ func init() {
|
||||
mdb.CREATE: {Name: "create file name", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
|
||||
_tail_create(m, arg...)
|
||||
}},
|
||||
}, mdb.ZoneAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
}, mdb.ZoneAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,id,file,text")), Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Fields(len(kit.Slice(arg, 0, 2)), "time,name,count,file", m.Config(mdb.FIELD))
|
||||
m.OptionPage(kit.Slice(arg, 2)...)
|
||||
|
||||
@ -76,5 +72,5 @@ func init() {
|
||||
m.StatusTimeCountTotal(_tail_count(m, arg[0]))
|
||||
}
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ import (
|
||||
const TAR = "tar"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
TAR: {Name: "tar file path auto", Help: "打包", Actions: ice.Actions{
|
||||
mdb.IMPORT: {Name: "import", Help: "导入", Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) == 1 {
|
||||
@ -63,18 +63,18 @@ func init() {
|
||||
}
|
||||
|
||||
header.Name = strings.TrimPrefix(p, dir_root+ice.PS)
|
||||
if err = t.WriteHeader(header); m.Warn(err != nil, "err: %v", err) {
|
||||
if err = t.WriteHeader(header); m.Warn(err) {
|
||||
return
|
||||
}
|
||||
|
||||
file, err := os.Open(p)
|
||||
if m.Warn(err != nil, "err: %v", err) {
|
||||
if m.Warn(err) {
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
m.PushNoticeGrow(kit.Format("%v %v %v\n", header.Name, kit.FmtSize(f.Size()), kit.FmtSize(total)))
|
||||
if _, err = io.Copy(t, file); m.Warn(err != nil, "err: %v", err) {
|
||||
if _, err = io.Copy(t, file); m.Warn(err) {
|
||||
return
|
||||
}
|
||||
|
||||
@ -84,5 +84,5 @@ func init() {
|
||||
}
|
||||
m.StatusTimeCountTotal(kit.FmtSize(total))
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package nfs
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
@ -10,61 +9,59 @@ import (
|
||||
)
|
||||
|
||||
func _trash_create(m *ice.Message, name string) {
|
||||
if s, e := os.Stat(name); m.Assert(e) {
|
||||
p := path.Join(ice.VAR_TRASH, path.Base(name))
|
||||
if !s.IsDir() {
|
||||
if f, e := os.Open(name); m.Assert(e) {
|
||||
defer f.Close()
|
||||
p = path.Join(ice.VAR_TRASH, kit.HashsPath(f))
|
||||
}
|
||||
if m.Warn(name == "", ice.ErrNotValid, name) {
|
||||
return
|
||||
}
|
||||
s, e := StatFile(m, name)
|
||||
if m.Warn(e, ice.ErrNotFound, name) {
|
||||
return
|
||||
}
|
||||
p := path.Join(ice.VAR_TRASH, path.Base(name))
|
||||
if !s.IsDir() {
|
||||
if f, e := OpenFile(m, name); m.Assert(e) {
|
||||
defer f.Close()
|
||||
p = path.Join(ice.VAR_TRASH, kit.HashsPath(f))
|
||||
}
|
||||
}
|
||||
|
||||
MkdirAll(m, path.Dir(p))
|
||||
if os.RemoveAll(p); !m.Warn(os.Rename(name, p)) {
|
||||
m.Cmd(mdb.INSERT, TRASH, "", mdb.HASH, FILE, p, FROM, name)
|
||||
}
|
||||
MkdirAll(m, path.Dir(p))
|
||||
if RemoveAll(m, p); !m.Warn(Rename(m, name, p)) {
|
||||
mdb.HashCreate(m, FROM, name, FILE, p)
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
FROM = "from"
|
||||
)
|
||||
const TRASH = "trash"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
TRASH: {Name: TRASH, Help: "回收站", Value: kit.Data(
|
||||
mdb.SHORT, FROM, mdb.FIELD, "time,hash,file,from", PATH, ice.VAR_TRASH,
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
TRASH: {Name: "trash hash auto prunes", Help: "回收站", Actions: ice.MergeAction(ice.Actions{
|
||||
mdb.REVERT: {Name: "revert", Help: "恢复", Hand: func(m *ice.Message, arg ...string) {
|
||||
os.Rename(m.Option(FILE), m.Option(FROM))
|
||||
m.Cmd(mdb.DELETE, TRASH, "", mdb.HASH, m.OptionSimple(mdb.HASH))
|
||||
Rename(m, m.Option(FILE), m.Option(FROM))
|
||||
mdb.HashRemove(m, m.OptionSimple(mdb.HASH))
|
||||
}},
|
||||
mdb.CREATE: {Name: "create path", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
|
||||
p := path.Join(m.Config(PATH), path.Base(m.Option(PATH)))
|
||||
os.RemoveAll(p)
|
||||
if os.MkdirAll(path.Dir(p), ice.MOD_DIR); !m.Warn(os.Rename(m.Option(PATH), p)) {
|
||||
p := path.Join(ice.VAR_TRASH, path.Base(m.Option(PATH)))
|
||||
RemoveAll(m, p)
|
||||
if MkdirAll(m, path.Dir(p)); !m.Warn(Rename(m, m.Option(PATH), p)) {
|
||||
m.Echo(p)
|
||||
}
|
||||
}},
|
||||
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
|
||||
os.Remove(m.Option(FILE))
|
||||
m.Cmd(mdb.DELETE, TRASH, "", mdb.HASH, m.OptionSimple(mdb.HASH))
|
||||
Remove(m, m.Option(FILE))
|
||||
mdb.HashRemove(m, m.OptionSimple(mdb.HASH))
|
||||
}},
|
||||
mdb.PRUNES: {Name: "prunes before@date", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.HashPrunes(m, func(value ice.Maps) bool {
|
||||
os.Remove(value[FILE])
|
||||
Remove(m, value[FILE])
|
||||
return false
|
||||
})
|
||||
}},
|
||||
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
if mdb.HashSelect(m, arg...); len(arg) == 0 || !kit.FileExists(arg[0]) {
|
||||
}, mdb.HashAction(mdb.SHORT, FROM, mdb.FIELD, "time,hash,file,from")), Hand: func(m *ice.Message, arg ...string) {
|
||||
if mdb.HashSelect(m, arg...); len(arg) == 0 || !ExistsFile(m, arg[0]) {
|
||||
m.PushAction(mdb.REVERT, mdb.REMOVE)
|
||||
return
|
||||
}
|
||||
_trash_create(m, arg[0])
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -13,21 +13,21 @@ import (
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/cli"
|
||||
"shylinux.com/x/icebergs/base/ctx"
|
||||
"shylinux.com/x/icebergs/base/gdb"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
func Render(msg *ice.Message, cmd string, args ...ice.Any) (res string) {
|
||||
switch arg := kit.Simple(args...); cmd {
|
||||
func Render(msg *ice.Message, cmd string, arg ...ice.Any) (res string) {
|
||||
switch args := kit.Simple(arg...); cmd {
|
||||
case ice.RENDER_VOID:
|
||||
return res
|
||||
case ice.RENDER_RESULT:
|
||||
if len(arg) > 0 {
|
||||
msg.Resultv(arg)
|
||||
if len(args) > 0 {
|
||||
msg.Resultv(args)
|
||||
}
|
||||
res = msg.Result()
|
||||
|
||||
default:
|
||||
if res = msg.Result(); res == "" {
|
||||
res = msg.Table().Result()
|
||||
@ -110,22 +110,18 @@ func (f *Frame) alias(m *ice.Message, ls []string) []string {
|
||||
return ls
|
||||
}
|
||||
func (f *Frame) parse(m *ice.Message, line string) string {
|
||||
// for _, one := range kit.Split(line, ";", ";", ";") {
|
||||
for _, one := range kit.Simple(line) {
|
||||
msg := m.Spawn(f.target)
|
||||
ls := f.change(msg, f.alias(msg, kit.Split(strings.TrimSpace(one))))
|
||||
if len(ls) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
msg.Render("", kit.List())
|
||||
if msg.Cmdy(ls[0], ls[1:]); msg.IsErrNotFound() {
|
||||
msg.SetResult().Cmdy(cli.SYSTEM, ls)
|
||||
}
|
||||
|
||||
f.res = Render(msg, msg.Option(ice.MSG_OUTPUT), msg.Optionv(ice.MSG_ARGS).([]ice.Any)...)
|
||||
msg := m.Spawn(f.target)
|
||||
ls := f.change(msg, f.alias(msg, kit.Split(strings.TrimSpace(line))))
|
||||
if len(ls) == 0 {
|
||||
return ""
|
||||
}
|
||||
m.Sleep("10ms")
|
||||
|
||||
msg.Render("", kit.List())
|
||||
if msg.Cmdy(ls); msg.IsErrNotFound() {
|
||||
msg.SetResult().Cmdy(cli.SYSTEM, ls)
|
||||
}
|
||||
|
||||
f.res = Render(msg, msg.Option(ice.MSG_OUTPUT), msg.Optionv(ice.MSG_ARGS).([]ice.Any)...)
|
||||
return ""
|
||||
}
|
||||
func (f *Frame) scan(m *ice.Message, h, line string) *Frame {
|
||||
@ -142,22 +138,14 @@ func (f *Frame) scan(m *ice.Message, h, line string) *Frame {
|
||||
|
||||
m.I, m.O = f.stdin, f.stdout
|
||||
bio := bufio.NewScanner(f.stdin)
|
||||
for f.prompt(m, ps...); bio.Scan() && f.stdin != nil; f.prompt(m, ps...) {
|
||||
if h == STDIO {
|
||||
if len(bio.Text()) == 0 {
|
||||
continue // 空行
|
||||
}
|
||||
m.Cmdx(mdb.INSERT, SOURCE, kit.Keys(mdb.HASH, h), mdb.LIST, mdb.TEXT, bio.Text())
|
||||
for f.prompt(m, ps...); f.stdin != nil && bio.Scan(); f.prompt(m, ps...) {
|
||||
if len(bio.Text()) == 0 && h == STDIO {
|
||||
continue // 空行
|
||||
}
|
||||
|
||||
f.count++
|
||||
mdb.ZoneInsert(m.Spawn(), mdb.HASH, h, mdb.TEXT, bio.Text())
|
||||
|
||||
if len(bio.Text()) == 0 {
|
||||
if strings.Count(line, "`")%2 == 1 {
|
||||
line += ice.NL
|
||||
}
|
||||
continue // 空行
|
||||
}
|
||||
if strings.HasSuffix(bio.Text(), "\\") {
|
||||
line += bio.Text()[:len(bio.Text())-1]
|
||||
ps = f.ps2
|
||||
@ -170,11 +158,8 @@ func (f *Frame) scan(m *ice.Message, h, line string) *Frame {
|
||||
}
|
||||
if strings.HasPrefix(strings.TrimSpace(line), "#") {
|
||||
line = ""
|
||||
continue
|
||||
continue // 注释
|
||||
}
|
||||
// if line = strings.Split(line, " # ")[0]; len(line) == 0 {
|
||||
// continue // 注释
|
||||
// }
|
||||
if ps = f.ps1; f.stdout == os.Stdout {
|
||||
if ice.Info.Colors {
|
||||
f.printf(m, "\033[0m") // 清空格式
|
||||
@ -195,27 +180,28 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool {
|
||||
m.Optionv(FRAME, f)
|
||||
switch f.source = kit.Select(STDIO, arg, 0); f.source {
|
||||
case STDIO: // 终端交互
|
||||
m.Cap(ice.CTX_STREAM, f.source)
|
||||
if f.target == nil {
|
||||
if m.Cap(ice.CTX_STREAM, f.source); f.target == nil {
|
||||
f.target = m.Target()
|
||||
}
|
||||
|
||||
r, w, _ := os.Pipe()
|
||||
m.Go(func() { io.Copy(w, os.Stdin) })
|
||||
f.stdin, f.stdout = r, os.Stdout
|
||||
f.pipe = w
|
||||
go func() { io.Copy(w, os.Stdin) }()
|
||||
f.pipe, f.stdin, f.stdout = w, r, os.Stdout
|
||||
|
||||
m.Option(ice.MSG_OPTS, ice.MSG_USERNAME)
|
||||
|
||||
m.Conf(SOURCE, kit.Keys(mdb.HASH, STDIO, kit.Keym(mdb.NAME)), STDIO)
|
||||
m.Conf(SOURCE, kit.Keys(mdb.HASH, STDIO, kit.Keym(mdb.TIME)), m.Time())
|
||||
|
||||
f.count = kit.Int(m.Conf(SOURCE, kit.Keys(mdb.HASH, STDIO, kit.Keym(mdb.COUNT)))) + 1
|
||||
f.scan(m, STDIO, "")
|
||||
|
||||
default: // 脚本文件
|
||||
if strings.Contains(m.Option(ice.MSG_SCRIPT), ice.PS) {
|
||||
f.source = path.Join(path.Dir(m.Option(ice.MSG_SCRIPT)), f.source)
|
||||
if m.Option(ice.MSG_SCRIPT) != "" {
|
||||
ls := kit.Split(m.Option(ice.MSG_SCRIPT), ice.PS)
|
||||
for i := len(ls) - 1; i > 0; i-- {
|
||||
if p := path.Join(path.Join(ls[:i]...), f.source); nfs.ExistsFile(m, p) {
|
||||
f.source = p
|
||||
}
|
||||
}
|
||||
}
|
||||
m.Option(ice.MSG_SCRIPT, f.source)
|
||||
f.target = m.Source()
|
||||
@ -224,13 +210,12 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool {
|
||||
return true // 查找失败
|
||||
} else {
|
||||
buf := bytes.NewBuffer(make([]byte, 0, ice.MOD_BUFS))
|
||||
f.stdin, f.stdout = bytes.NewBufferString(msg.Result()), buf
|
||||
defer func() { m.Echo(buf.String()) }()
|
||||
|
||||
f.stdin, f.stdout = bytes.NewBuffer([]byte(msg.Result())), buf
|
||||
}
|
||||
|
||||
f.count = 1
|
||||
f.scan(m, m.Cmdx(mdb.INSERT, SOURCE, "", mdb.HASH, mdb.NAME, f.source), "")
|
||||
f.scan(m, mdb.HashCreate(m.Spawn(), mdb.NAME, f.source).Result(), "")
|
||||
}
|
||||
return true
|
||||
}
|
||||
@ -266,16 +251,14 @@ func init() {
|
||||
PS2, []ice.Any{mdb.COUNT, " ", TARGET, "> "},
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {}},
|
||||
SOURCE: {Name: "source file", Help: "脚本解析", Actions: ice.MergeAction(ice.Actions{
|
||||
"repeat": {Name: "repeat", Help: "执行", Hand: func(m *ice.Message, arg ...string) {
|
||||
gdb.RESTART: {Name: "restart", Help: "执行", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(SCREEN, m.Option(mdb.TEXT))
|
||||
m.ProcessInner()
|
||||
}},
|
||||
}, mdb.ZoneAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) > 0 && kit.Ext(arg[0]) == ice.SHY {
|
||||
(&Frame{}).Start(m, arg...)
|
||||
return // 脚本解析
|
||||
if f, ok := m.Target().Server().(*Frame); ok {
|
||||
f.Spawn(m, m.Target()).Start(m, arg...)
|
||||
}
|
||||
}},
|
||||
TARGET: {Name: "target name run", Help: "当前模块", Hand: func(m *ice.Message, arg ...string) {
|
||||
@ -284,26 +267,30 @@ func init() {
|
||||
f.prompt(m)
|
||||
}},
|
||||
PROMPT: {Name: "prompt arg run", Help: "命令提示", Hand: func(m *ice.Message, arg ...string) {
|
||||
f := m.Optionv(FRAME).(*Frame)
|
||||
f.ps1 = arg
|
||||
f.prompt(m)
|
||||
if f, ok := m.Optionv(FRAME).(*Frame); ok {
|
||||
f.ps1 = arg
|
||||
f.prompt(m)
|
||||
}
|
||||
}},
|
||||
PRINTF: {Name: "printf run text", Help: "输出显示", Hand: func(m *ice.Message, arg ...string) {
|
||||
f := m.Optionv(FRAME).(*Frame)
|
||||
f.printf(m, arg[0])
|
||||
if f, ok := m.Optionv(FRAME).(*Frame); ok {
|
||||
f.printf(m, arg[0])
|
||||
}
|
||||
}},
|
||||
SCREEN: {Name: "screen run text", Help: "输出命令", Hand: func(m *ice.Message, arg ...string) {
|
||||
f := m.Optionv(FRAME).(*Frame)
|
||||
for _, line := range kit.Split(arg[0], ice.NL, ice.NL) {
|
||||
fmt.Fprintf(f.pipe, line+ice.NL)
|
||||
f.printf(m, line+ice.NL)
|
||||
m.Sleep300ms()
|
||||
if f, ok := m.Optionv(FRAME).(*Frame); ok {
|
||||
for _, line := range kit.Split(arg[0], ice.NL, ice.NL) {
|
||||
fmt.Fprintf(f.pipe, line+ice.NL)
|
||||
f.printf(m, line+ice.NL)
|
||||
m.Sleep300ms()
|
||||
}
|
||||
m.Echo(f.res)
|
||||
}
|
||||
m.Echo(f.res)
|
||||
}},
|
||||
RETURN: {Name: "return", Help: "结束脚本", Hand: func(m *ice.Message, arg ...string) {
|
||||
f := m.Optionv(FRAME).(*Frame)
|
||||
f.Close(m, arg...)
|
||||
if f, ok := m.Optionv(FRAME).(*Frame); ok {
|
||||
f.Close(m, arg...)
|
||||
}
|
||||
}},
|
||||
}})
|
||||
}
|
||||
|
@ -36,7 +36,6 @@ func (c *Conn) Close() error {
|
||||
|
||||
func _client_dial(m *ice.Message, arg ...string) {
|
||||
c, e := net.Dial(TCP, m.Option(HOST)+ice.DF+m.Option(PORT))
|
||||
|
||||
c = &Conn{m: m, s: &Stat{}, Conn: c}
|
||||
if e == nil {
|
||||
defer c.Close()
|
||||
@ -57,8 +56,10 @@ func _client_dial(m *ice.Message, arg ...string) {
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
case nil:
|
||||
c.Write([]byte("hello world\n"))
|
||||
default:
|
||||
m.ErrorNotImplement(cb)
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,25 +78,18 @@ const (
|
||||
const CLIENT = "client"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
CLIENT: {Name: CLIENT, Help: "客户端", Value: kit.Data(
|
||||
mdb.FIELD, "time,hash,status,type,name,host,port,error,nread,nwrite",
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
CLIENT: {Name: "client hash auto prunes", Help: "客户端", Actions: ice.MergeAction(ice.Actions{
|
||||
ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Richs(CLIENT, "", mdb.FOREACH, func(key string, value ice.Map) {
|
||||
kit.Value(value, kit.Keym(STATUS), CLOSE)
|
||||
})
|
||||
m.Cmdy(SERVER, mdb.PRUNES)
|
||||
m.Conf(m.PrefixKey(), "", "")
|
||||
}},
|
||||
DIAL: {Name: "dial type name port=9010 host=", Help: "连接", Hand: func(m *ice.Message, arg ...string) {
|
||||
_client_dial(m, arg...)
|
||||
}},
|
||||
}, mdb.HashActionStatus()), Hand: func(m *ice.Message, arg ...string) {
|
||||
}, mdb.HashActionStatus(mdb.FIELD, "time,hash,status,type,name,host,port,error,nread,nwrite")), Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.HashSelect(m, arg...).Tables(func(value ice.Maps) {
|
||||
m.PushButton(kit.Select("", mdb.REMOVE, value[STATUS] == OPEN))
|
||||
})
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -59,13 +59,6 @@ func _islocalhost(m *ice.Message, ip string) (ok bool) {
|
||||
}
|
||||
return false
|
||||
}
|
||||
func IsLocalHost(m *ice.Message, ip string) bool { return _islocalhost(m, ip) }
|
||||
func ReplaceLocalhost(m *ice.Message, url string) string {
|
||||
if strings.Contains(url, "://"+LOCALHOST) {
|
||||
url = strings.Replace(url, "://"+LOCALHOST, "://"+m.Cmd(HOST).Append(aaa.IP), 1)
|
||||
}
|
||||
return url
|
||||
}
|
||||
|
||||
const (
|
||||
LOCALHOST = "localhost"
|
||||
@ -73,16 +66,10 @@ const (
|
||||
const HOST = "host"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
HOST: {Name: HOST, Help: "主机", Value: kit.Data(
|
||||
aaa.BLACK, kit.Data(mdb.SHORT, mdb.TEXT), aaa.WHITE, kit.Data(mdb.SHORT, mdb.TEXT),
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
HOST: {Name: "host name auto", Help: "主机", Actions: ice.Actions{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
HOST: {Name: "host name auto", Help: "主机", Actions: ice.MergeAction(ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmd(HOST).Tables(func(value ice.Maps) {
|
||||
m.Cmd(HOST, aaa.WHITE, value[aaa.IP])
|
||||
})
|
||||
m.Cmd(HOST).Tables(func(value ice.Maps) { m.Cmd(HOST, aaa.WHITE, value[aaa.IP]) })
|
||||
}},
|
||||
aaa.BLACK: {Name: "black", Help: "黑名单", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Log_CREATE(aaa.BLACK, arg[0])
|
||||
@ -92,8 +79,16 @@ func init() {
|
||||
m.Log_CREATE(aaa.WHITE, arg[0])
|
||||
m.Rich(HOST, kit.Keym(aaa.WHITE), kit.Dict(mdb.TEXT, arg[0]))
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
}, mdb.HashAction(aaa.BLACK, kit.Data(mdb.SHORT, mdb.TEXT), aaa.WHITE, kit.Data(mdb.SHORT, mdb.TEXT))), Hand: func(m *ice.Message, arg ...string) {
|
||||
_host_list(m, kit.Select("", arg, 0))
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
||||
func IsLocalHost(m *ice.Message, ip string) bool { return _islocalhost(m, ip) }
|
||||
func ReplaceLocalhost(m *ice.Message, url string) string {
|
||||
if strings.Contains(url, "://"+LOCALHOST) {
|
||||
url = strings.Replace(url, "://"+LOCALHOST, "://"+m.Cmd(HOST).Append(aaa.IP), 1)
|
||||
}
|
||||
return url
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/aaa"
|
||||
"shylinux.com/x/icebergs/base/cli"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
@ -25,12 +24,12 @@ func _port_right(m *ice.Message, arg ...string) string {
|
||||
c.Close()
|
||||
continue
|
||||
}
|
||||
p := path.Join(m.Conf(cli.DAEMON, kit.Keym(nfs.PATH)), kit.Format(i))
|
||||
if kit.FileExists(p) {
|
||||
p := path.Join(ice.USR_LOCAL_DAEMON, kit.Format(i))
|
||||
if nfs.ExistsFile(m, p) {
|
||||
continue
|
||||
}
|
||||
nfs.MkdirAll(m, p)
|
||||
|
||||
nfs.MkdirAll(m, p)
|
||||
m.Log_SELECT(PORT, i)
|
||||
return m.Config(CURRENT, i)
|
||||
}
|
||||
@ -46,10 +45,8 @@ const (
|
||||
const PORT = "port"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
PORT: {Name: PORT, Help: "端口", Value: kit.Data(BEGIN, 10000, CURRENT, 10000, END, 20000)},
|
||||
}, Commands: ice.Commands{
|
||||
PORT: {Name: "port port path auto", Help: "端口", Actions: ice.Actions{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
PORT: {Name: "port port path auto", Help: "端口", Actions: ice.MergeAction(ice.Actions{
|
||||
aaa.RIGHT: {Name: "right", Help: "分配", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Echo(_port_right(m, arg...))
|
||||
}},
|
||||
@ -58,33 +55,33 @@ func init() {
|
||||
m.Cmd(nfs.TRASH, path.Join(ice.USR_LOCAL_DAEMON, m.Option(PORT)))
|
||||
}
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) == 0 {
|
||||
current := kit.Int(m.Config(BEGIN))
|
||||
m.Option(nfs.DIR_ROOT, ice.USR_LOCAL_DAEMON)
|
||||
m.Cmd(nfs.DIR, nfs.PWD, nfs.DIR_CLI_FIELDS).Tables(func(value ice.Maps) {
|
||||
bin := m.Cmd(nfs.DIR, path.Join(value[nfs.PATH], ice.BIN), nfs.DIR_CLI_FIELDS).Append(nfs.PATH)
|
||||
if bin == "" {
|
||||
bin = m.Cmd(nfs.DIR, path.Join(value[nfs.PATH], "sbin"), nfs.DIR_CLI_FIELDS).Append(nfs.PATH)
|
||||
}
|
||||
port := kit.Int(path.Base(value[nfs.PATH]))
|
||||
if port > current {
|
||||
current = port
|
||||
}
|
||||
|
||||
m.Push(mdb.TIME, value[mdb.TIME])
|
||||
m.Push(PORT, port)
|
||||
m.Push(nfs.SIZE, value[nfs.SIZE])
|
||||
m.Push(ice.BIN, bin)
|
||||
})
|
||||
m.SortInt(PORT)
|
||||
m.PushAction(nfs.TRASH)
|
||||
m.Config(CURRENT, current)
|
||||
m.StatusTimeCount(m.ConfigSimple(BEGIN, CURRENT, END))
|
||||
}, mdb.HashAction(BEGIN, 10000, CURRENT, 10000, END, 20000)), Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) > 0 {
|
||||
m.Cmdy(nfs.DIR, arg[1:], kit.Dict(nfs.DIR_ROOT, path.Join(ice.USR_LOCAL_DAEMON, arg[0])))
|
||||
return
|
||||
}
|
||||
m.Option(nfs.DIR_ROOT, path.Join(m.Conf(cli.DAEMON, kit.Keym(nfs.PATH)), arg[0]))
|
||||
m.Cmdy(nfs.DIR, arg[1:])
|
||||
|
||||
current := kit.Int(m.Config(BEGIN))
|
||||
m.Option(nfs.DIR_ROOT, ice.USR_LOCAL_DAEMON)
|
||||
m.Cmd(nfs.DIR, nfs.PWD, nfs.DIR_CLI_FIELDS).Tables(func(value ice.Maps) {
|
||||
bin := m.Cmd(nfs.DIR, path.Join(value[nfs.PATH], ice.BIN), nfs.DIR_CLI_FIELDS).Append(nfs.PATH)
|
||||
if bin == "" {
|
||||
bin = m.Cmd(nfs.DIR, path.Join(value[nfs.PATH], "sbin"), nfs.DIR_CLI_FIELDS).Append(nfs.PATH)
|
||||
}
|
||||
port := kit.Int(path.Base(value[nfs.PATH]))
|
||||
if port > current {
|
||||
current = port
|
||||
}
|
||||
|
||||
m.Push(mdb.TIME, value[mdb.TIME])
|
||||
m.Push(PORT, port)
|
||||
m.Push(nfs.SIZE, value[nfs.SIZE])
|
||||
m.Push(ice.BIN, bin)
|
||||
})
|
||||
m.SortInt(PORT)
|
||||
m.PushAction(nfs.TRASH)
|
||||
m.Config(CURRENT, current)
|
||||
m.StatusTimeCount(m.ConfigSimple(BEGIN, CURRENT, END))
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ type Listener struct {
|
||||
func (l Listener) Accept() (net.Conn, error) {
|
||||
c, e := l.Listener.Accept()
|
||||
l.s.nc += 1
|
||||
return &Conn{m: l.m, h: "", s: &Stat{}, Conn: c}, e
|
||||
return &Conn{m: l.m, s: &Stat{}, Conn: c}, e
|
||||
}
|
||||
func (l Listener) Close() error {
|
||||
l.m.Cmd(mdb.MODIFY, SERVER, "", mdb.HASH, mdb.HASH, l.h, STATUS, CLOSE)
|
||||
@ -28,10 +28,8 @@ func (l Listener) Close() error {
|
||||
|
||||
func _server_listen(m *ice.Message, arg ...string) {
|
||||
l, e := net.Listen(TCP, m.Option(HOST)+":"+m.Option(PORT))
|
||||
h := m.Cmdx(mdb.INSERT, SERVER, "", mdb.HASH, arg,
|
||||
STATUS, kit.Select(ERROR, OPEN, e == nil), ERROR, kit.Format(e))
|
||||
|
||||
l = &Listener{m: m, h: h, s: &Stat{}, Listener: l}
|
||||
l = &Listener{m: m, h: m.Cmdx(mdb.INSERT, SERVER, "", mdb.HASH,
|
||||
arg, STATUS, kit.Select(ERROR, OPEN, e == nil), ERROR, kit.Format(e), kit.Dict(mdb.TARGET, l)), s: &Stat{}, Listener: l}
|
||||
if e == nil {
|
||||
defer l.Close()
|
||||
}
|
||||
@ -85,25 +83,28 @@ const (
|
||||
const SERVER = "server"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
SERVER: {Name: SERVER, Help: "服务器", Value: kit.Data(
|
||||
mdb.FIELD, "time,hash,status,type,name,host,port,error,nconn",
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
SERVER: {Name: "server hash auto prunes", Help: "服务器", Actions: ice.MergeAction(ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Conf("", mdb.HASH, "")
|
||||
}},
|
||||
ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Richs(SERVER, "", mdb.FOREACH, func(key string, value ice.Map) {
|
||||
kit.Value(value, kit.Keym(STATUS), CLOSE)
|
||||
mdb.HashSelectValue(m, func(target ice.Any) {
|
||||
if l, ok := target.(net.Listener); ok {
|
||||
l.Close()
|
||||
}
|
||||
if l, ok := target.(*Listener); ok {
|
||||
l.Close()
|
||||
}
|
||||
})
|
||||
m.Cmdy(SERVER, mdb.PRUNES)
|
||||
}},
|
||||
LISTEN: {Name: "LISTEN type name port=9030 host=", Help: "监听", Hand: func(m *ice.Message, arg ...string) {
|
||||
_server_listen(m, arg...)
|
||||
}},
|
||||
}, mdb.HashActionStatus()), Hand: func(m *ice.Message, arg ...string) {
|
||||
}, mdb.HashActionStatus(mdb.FIELD, "time,hash,status,type,name,host,port,error,nconn")), Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.HashSelect(m, arg...).Tables(func(value ice.Maps) {
|
||||
m.PushButton(kit.Select("", mdb.REMOVE, value[STATUS] == CLOSE))
|
||||
})
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -426,5 +426,4 @@ func _story_commit(m *ice.Message, arg ...string) {
|
||||
value["list"] = list
|
||||
}
|
||||
m.Echo(list)
|
||||
|
||||
}
|
@ -5,85 +5,86 @@ import (
|
||||
"strings"
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/aaa"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
"shylinux.com/x/icebergs/base/tcp"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
func _udp_addr(m *ice.Message, host, port string) *net.UDPAddr {
|
||||
func _broad_addr(m *ice.Message, host, port string) *net.UDPAddr {
|
||||
addr, err := net.ResolveUDPAddr("udp4", kit.Format("%s:%s", host, port))
|
||||
m.Assert(err)
|
||||
return addr
|
||||
}
|
||||
func _udp_broad(m *ice.Message, host, port string, remote_host, remote_port string) {
|
||||
if s, e := net.DialUDP("udp", nil, _udp_addr(m, remote_host, remote_port)); m.Assert(e) {
|
||||
func _broad_send(m *ice.Message, host, port string, remote_host, remote_port string) {
|
||||
if s, e := net.DialUDP("udp", nil, _broad_addr(m, remote_host, remote_port)); m.Assert(e) {
|
||||
defer s.Close()
|
||||
msg := m.Spawn(kit.Dict(tcp.HOST, host, tcp.PORT, port))
|
||||
m.Debug("broad %v to %v:%v", msg.FormatMeta(), remote_host, remote_port)
|
||||
m.Log_EXPORT(BROAD, msg.FormatMeta(), "to", remote_host+ice.DF+remote_port)
|
||||
s.Write([]byte(msg.FormatMeta()))
|
||||
}
|
||||
}
|
||||
func _serve_udp(m *ice.Message, host, port string) {
|
||||
m.Cmd(BROAD, mdb.CREATE, tcp.HOST, host, tcp.PORT, port)
|
||||
_udp_broad(m, host, port, "255.255.255.255", "9020")
|
||||
|
||||
if s, e := net.ListenUDP("udp", _udp_addr(m, "0.0.0.0", port)); m.Assert(e) {
|
||||
func _broad_serve(m *ice.Message, host, port string) {
|
||||
_broad_send(m, host, port, "255.255.255.255", "9020")
|
||||
if s, e := net.ListenUDP("udp", _broad_addr(m, "0.0.0.0", port)); m.Assert(e) {
|
||||
defer s.Close()
|
||||
m.Debug("listen %v %v", host, port)
|
||||
m.Cmd(BROAD, mdb.CREATE, tcp.HOST, host, tcp.PORT, port, kit.Dict(mdb.TARGET, s))
|
||||
|
||||
buf := make([]byte, 1024)
|
||||
buf := make([]byte, ice.MOD_BUFS)
|
||||
for {
|
||||
n, addr, err := s.ReadFromUDP(buf[:])
|
||||
if err != nil {
|
||||
m.Debug("what %v", err)
|
||||
continue
|
||||
break
|
||||
}
|
||||
m.Debug("recv %v %v", string(buf[:n]), addr)
|
||||
m.Log_IMPORT(BROAD, string(buf[:n]), "from", addr)
|
||||
|
||||
msg := m.Spawn(buf[:n])
|
||||
if m.Cmd(BROAD, kit.Format("%s,%s", msg.Option(tcp.HOST), msg.Option(tcp.PORT))).Length() > 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if remote, err := net.ResolveUDPAddr("udp4", kit.Format("%s:%s", msg.Option(tcp.HOST), msg.Option(tcp.PORT))); err == nil {
|
||||
if remote, err := net.ResolveUDPAddr("udp4", kit.Format("%s:%s", msg.Option(tcp.HOST), msg.Option(tcp.PORT))); !m.Warn(err) {
|
||||
m.Cmd(BROAD).Tables(func(value ice.Maps) {
|
||||
m.Debug("broad %v to %v", kit.Format(value), kit.Format(remote))
|
||||
m.Log_EXPORT(BROAD, kit.Format(value), "to", kit.Format(remote))
|
||||
s.WriteToUDP([]byte(m.Spawn(value).FormatMeta()), remote)
|
||||
})
|
||||
m.Cmd(BROAD, mdb.CREATE, msg.OptionSimple(tcp.HOST, tcp.PORT))
|
||||
} else {
|
||||
m.Debug("what %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
func _broad_search(m *ice.Message, kind, name, text string, arg ...string) {
|
||||
m.Richs(BROAD, nil, mdb.FOREACH, func(key string, value ice.Map) {
|
||||
if value = kit.GetMeta(value); !strings.Contains(kit.Format(value[tcp.HOST]), name) {
|
||||
mdb.HashSelectValue(m, func(value ice.Map) {
|
||||
if !strings.Contains(kit.Format(value[tcp.HOST]), name) {
|
||||
return
|
||||
}
|
||||
m.PushSearch(mdb.TYPE, "friend", mdb.TEXT, kit.Format("http://%s:%s", value[tcp.HOST], value[tcp.PORT]), value)
|
||||
m.PushSearch(mdb.TYPE, FRIEND, mdb.TEXT, kit.Format("http://%s:%s", value[tcp.HOST], value[tcp.PORT]), value)
|
||||
})
|
||||
}
|
||||
|
||||
const BROAD = "broad"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
BROAD: {Name: "broad hash auto", Help: "广播", Actions: ice.MergeAction(ice.Actions{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
BROAD: {Name: "broad hash auto serve", Help: "广播", Actions: ice.MergeAction(ice.Actions{
|
||||
ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.HashSelectValue(m, func(target ice.Any) {
|
||||
if c, ok := target.(*net.UDPConn); ok {
|
||||
c.Close()
|
||||
}
|
||||
})
|
||||
}},
|
||||
mdb.SEARCH: {Name: "search type name text", Help: "搜索", Hand: func(m *ice.Message, arg ...string) {
|
||||
_broad_search(m, arg[0], arg[1], kit.Select("", arg, 2))
|
||||
}},
|
||||
SERVE: {Name: "broad port=9020", Help: "搜索", Hand: func(m *ice.Message, arg ...string) {
|
||||
_serve_udp(m, m.Cmd(tcp.HOST).Append("ip"), m.Option(tcp.PORT))
|
||||
_broad_serve(m, m.Cmd(tcp.HOST).Append(aaa.IP), m.Option(tcp.PORT))
|
||||
}},
|
||||
SPACE: {Name: "space dev", Help: "连接", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmd(SPIDE, mdb.CREATE, mdb.NAME, m.Option(ice.DEV), ADDRESS,
|
||||
kit.Format("http://%s:%s", m.Option(tcp.HOST), m.Option(tcp.PORT)))
|
||||
m.Cmd(SPACE, tcp.DIAL, m.OptionSimple(ice.DEV))
|
||||
}},
|
||||
}, mdb.HashAction(
|
||||
mdb.SHORT, "host,port", mdb.FIELD, "time,hash,host,port",
|
||||
)), Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.HashSelect(m, arg...)
|
||||
m.PushAction(SPACE, mdb.REMOVE)
|
||||
}},
|
||||
}})
|
||||
}, mdb.HashAction(mdb.SHORT, "host,port", mdb.FIELD, "time,hash,host,port", mdb.ACTION, "space"))},
|
||||
})
|
||||
}
|
||||
|
@ -10,16 +10,17 @@ import (
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
"shylinux.com/x/toolkits/miss"
|
||||
)
|
||||
|
||||
func _cache_name(m *ice.Message, h string) string {
|
||||
return path.Join(m.Config(nfs.PATH), h[:2], h)
|
||||
return path.Join(ice.VAR_FILE, h[:2], h)
|
||||
}
|
||||
func _cache_save(m *ice.Message, kind, name, text string, arg ...string) { // file size
|
||||
if name == "" {
|
||||
return
|
||||
}
|
||||
if len(text) > 512 || kind == "go" { // 存入文件
|
||||
if len(text) > 512 || kind == nfs.GO { // 存入文件
|
||||
p := m.Cmdx(nfs.SAVE, _cache_name(m, kit.Hashs(text)), text)
|
||||
text, arg = p, kit.Simple(p, len(text))
|
||||
}
|
||||
@ -28,7 +29,7 @@ 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.Cmdx(mdb.INSERT, CACHE, "", mdb.HASH, kit.SimpleKV("", kind, name, text), nfs.FILE, file, nfs.SIZE, size)
|
||||
h := mdb.HashCreate(m, kit.SimpleKV("", kind, name, text), nfs.FILE, file, nfs.SIZE, size).Result()
|
||||
|
||||
// 返回结果
|
||||
m.Push(mdb.TIME, m.Time())
|
||||
@ -50,26 +51,26 @@ func _cache_watch(m *ice.Message, key, file string) {
|
||||
})
|
||||
}
|
||||
func _cache_catch(m *ice.Message, name string) (file, size string) {
|
||||
if f, e := os.Open(name); m.Assert(e) {
|
||||
if f, e := nfs.OpenFile(m, name); m.Assert(e) {
|
||||
defer f.Close()
|
||||
|
||||
if s, e := f.Stat(); m.Assert(e) {
|
||||
if s, e := nfs.StatFile(m, name); m.Assert(e) {
|
||||
return m.Cmdx(nfs.LINK, _cache_name(m, kit.Hashs(f)), name), kit.Format(s.Size())
|
||||
}
|
||||
}
|
||||
return "", "0"
|
||||
}
|
||||
func _cache_upload(m *ice.Message, r *http.Request) (kind, name, file, size string) {
|
||||
if buf, h, e := r.FormFile(UPLOAD); e == nil {
|
||||
defer buf.Close()
|
||||
if b, h, e := r.FormFile(UPLOAD); e == nil {
|
||||
defer b.Close()
|
||||
|
||||
// 创建文件
|
||||
if f, p, e := kit.Create(_cache_name(m, kit.Hashs(buf))); m.Assert(e) {
|
||||
if f, p, e := miss.CreateFile(_cache_name(m, kit.Hashs(b))); m.Assert(e) {
|
||||
defer f.Close()
|
||||
|
||||
// 导入数据
|
||||
buf.Seek(0, os.SEEK_SET)
|
||||
if n, e := io.Copy(f, buf); m.Assert(e) {
|
||||
b.Seek(0, os.SEEK_SET)
|
||||
if n, e := io.Copy(f, b); m.Assert(e) {
|
||||
m.Log_IMPORT(nfs.FILE, p, nfs.SIZE, kit.FmtSize(int64(n)))
|
||||
return h.Header.Get(ContentType), h.Filename, p, kit.Format(n)
|
||||
}
|
||||
@ -80,12 +81,14 @@ 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()
|
||||
|
||||
if f, p, e := kit.Create(path.Join(ice.VAR_TMP, kit.Hashs(mdb.UNIQ))); m.Assert(e) {
|
||||
step, total := 0, kit.Int(kit.Select("1", r.Header.Get(ContentLength)))
|
||||
if f, p, e := miss.CreateFile(path.Join(ice.VAR_TMP, kit.Hashs(mdb.UNIQ))); m.Assert(e) {
|
||||
defer f.Close()
|
||||
|
||||
step, total := 0, kit.Int(kit.Select("100", r.Header.Get(ContentLength)))
|
||||
size, buf := 0, make([]byte, ice.MOD_BUFS)
|
||||
|
||||
for {
|
||||
if n, _ := r.Body.Read(buf); n > 0 {
|
||||
if n, e := r.Body.Read(buf); n > 0 && e == nil {
|
||||
size += n
|
||||
f.Write(buf[0:n])
|
||||
s := size * 100 / total
|
||||
@ -95,31 +98,16 @@ func _cache_download(m *ice.Message, r *http.Response) (file, size string) {
|
||||
cb(size, total, s)
|
||||
case func(int, int):
|
||||
cb(size, total)
|
||||
case []string:
|
||||
m.Richs(cb[0], cb[1], cb[2], func(key string, value ice.Map) {
|
||||
value = kit.GetMeta(value)
|
||||
value[mdb.COUNT], value[mdb.TOTAL], value[mdb.VALUE] = size, total, kit.Format(s)
|
||||
})
|
||||
default:
|
||||
if s != step && s%10 == 0 {
|
||||
m.Log_IMPORT(nfs.FILE, p, mdb.VALUE, s, mdb.COUNT, kit.FmtSize(int64(size)), mdb.TOTAL, kit.FmtSize(int64(total)))
|
||||
}
|
||||
}
|
||||
|
||||
step = s
|
||||
continue
|
||||
}
|
||||
|
||||
f.Close()
|
||||
break
|
||||
}
|
||||
|
||||
if f, e := os.Open(p); m.Assert(e) {
|
||||
defer f.Close()
|
||||
|
||||
m.Log_IMPORT(nfs.FILE, p, nfs.SIZE, kit.FmtSize(int64(size)))
|
||||
c := _cache_name(m, kit.Hashs(f))
|
||||
m.Cmd(nfs.LINK, c, p)
|
||||
return c, kit.Format(size)
|
||||
return p, kit.Format(size)
|
||||
}
|
||||
}
|
||||
return "", "0"
|
||||
@ -135,22 +123,7 @@ const (
|
||||
const CACHE = "cache"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
CACHE: {Name: CACHE, Help: "缓存池", Value: kit.Data(
|
||||
mdb.SHORT, mdb.TEXT, mdb.FIELD, "time,hash,size,type,name,text",
|
||||
mdb.STORE, ice.VAR_DATA, nfs.PATH, ice.VAR_FILE, mdb.FSIZE, "200000",
|
||||
mdb.LIMIT, "50", mdb.LEAST, "30",
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
"/cache/": {Name: "/cache/", Help: "缓存池", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Richs(CACHE, nil, arg[0], func(key string, value ice.Map) {
|
||||
if kit.Format(value[nfs.FILE]) == "" {
|
||||
m.RenderResult(value[mdb.TEXT])
|
||||
} else {
|
||||
m.RenderDownload(value[nfs.FILE])
|
||||
}
|
||||
})
|
||||
}},
|
||||
Index.MergeCommands(ice.Commands{
|
||||
CACHE: {Name: "cache hash auto", Help: "缓存池", Actions: ice.MergeAction(ice.Actions{
|
||||
WATCH: {Name: "watch key file", Help: "释放", Hand: func(m *ice.Message, arg ...string) {
|
||||
_cache_watch(m, arg[0], arg[1])
|
||||
@ -169,19 +142,28 @@ func init() {
|
||||
DOWNLOAD: {Name: "download type name", Help: "下载", Hand: func(m *ice.Message, arg ...string) {
|
||||
if r, ok := m.Optionv(RESPONSE).(*http.Response); ok {
|
||||
file, size := _cache_download(m, r)
|
||||
file, size = _cache_catch(m, file)
|
||||
_cache_save(m, arg[0], arg[1], "", file, size)
|
||||
}
|
||||
}},
|
||||
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
}, mdb.HashAction(mdb.SHORT, mdb.TEXT, mdb.FIELD, "time,hash,size,type,name,text,file")), Hand: func(m *ice.Message, arg ...string) {
|
||||
if mdb.HashSelect(m, arg...); len(arg) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if m.Append(nfs.FILE) == "" {
|
||||
m.PushScript("inner", m.Append(mdb.TEXT))
|
||||
} else {
|
||||
m.PushDownload(m.Append(mdb.NAME), m.MergeURL2("/share/cache/"+arg[0]))
|
||||
m.PushDownload(m.Append(mdb.NAME), m.MergeURL2(SHARE_CACHE+arg[0]))
|
||||
}
|
||||
}},
|
||||
}})
|
||||
PP(CACHE): {Name: "/cache/", Help: "缓存池", Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.HashSelectDetail(m, arg[0], func(value ice.Map) {
|
||||
if kit.Format(value[nfs.FILE]) == "" {
|
||||
m.RenderResult(value[mdb.TEXT])
|
||||
} else {
|
||||
m.RenderDownload(value[nfs.FILE])
|
||||
}
|
||||
})
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
@ -7,44 +7,65 @@ import (
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/cli"
|
||||
"shylinux.com/x/icebergs/base/gdb"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
"shylinux.com/x/icebergs/base/tcp"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
"shylinux.com/x/toolkits/file"
|
||||
)
|
||||
|
||||
func _dream_list(m *ice.Message) *ice.Message {
|
||||
return m.Cmdy(nfs.DIR, m.Config(nfs.PATH), "time,size,name").Tables(func(value ice.Maps) {
|
||||
if m.Richs(SPACE, nil, value[mdb.NAME], func(key string, val ice.Map) {
|
||||
m.Push(mdb.TYPE, val[mdb.TYPE])
|
||||
list := m.CmdMap(SPACE, mdb.NAME)
|
||||
m.Cmdy(nfs.DIR, ice.USR_LOCAL_WORK, "time,size,name").Tables(func(value ice.Maps) {
|
||||
if dream, ok := list[value[mdb.NAME]]; ok {
|
||||
m.Push(mdb.TYPE, dream[mdb.TYPE])
|
||||
m.Push(cli.STATUS, cli.START)
|
||||
m.PushButton("vimer", "xterm", cli.OPEN, cli.STOP)
|
||||
m.PushAnchor(strings.Split(m.MergePod(value[mdb.NAME]), "?")[0])
|
||||
}) == nil {
|
||||
text := []string{}
|
||||
for _, line := range kit.Split(m.Cmdx(SPACE, value[mdb.NAME], cli.SYSTEM, "git", "diff", "--shortstat"), ice.FS, ice.FS) {
|
||||
if list := kit.Split(line); strings.Contains(line, "file") {
|
||||
text = append(text, list[0]+" file")
|
||||
} else if strings.Contains(line, "ins") {
|
||||
text = append(text, list[0]+" +++")
|
||||
} else if strings.Contains(line, "dele") {
|
||||
text = append(text, list[0]+" ---")
|
||||
}
|
||||
}
|
||||
m.Push(mdb.TEXT, strings.Join(text, ", "))
|
||||
} else {
|
||||
m.Push(mdb.TYPE, WORKER)
|
||||
m.Push(cli.STATUS, cli.STOP)
|
||||
m.PushButton(cli.START, nfs.TRASH)
|
||||
m.PushAnchor("")
|
||||
m.Push(mdb.TEXT, "")
|
||||
}
|
||||
})
|
||||
return m.Sort("status,type,name").StatusTimeCount(cli.START, len(list))
|
||||
}
|
||||
|
||||
func _dream_show(m *ice.Message, name string) {
|
||||
if !strings.Contains(name, "-") || !strings.HasPrefix(name, "20") {
|
||||
name = m.Time("20060102-") + kit.ReplaceAll(name, "-", "_")
|
||||
}
|
||||
defer m.ProcessOpen(m.MergePod(m.Option(mdb.NAME, name)))
|
||||
// defer m.ProcessOpen(m.MergePod(m.Option(mdb.NAME, name)))
|
||||
defer m.Echo(m.MergePod(m.Option(mdb.NAME, name)))
|
||||
|
||||
// 任务目录
|
||||
p := path.Join(m.Config(nfs.PATH), name)
|
||||
p := path.Join(ice.USR_LOCAL_WORK, name)
|
||||
if pid := m.Cmdx(nfs.CAT, path.Join(p, ice.Info.PidPath)); pid != "" && kit.FileExists("/proc/"+pid) {
|
||||
m.Info("already exists %v", pid)
|
||||
return // 已经启动
|
||||
} else if m.Cmd(SPACE, name).Length() > 0 {
|
||||
return // 已经启动
|
||||
}
|
||||
|
||||
if m.Option(nfs.REPOS) != "" { // 下载源码
|
||||
m.Cmd("web.code.git.repos", mdb.CREATE, m.OptionSimple(nfs.REPOS), nfs.PATH, p)
|
||||
} else { // 创建目录
|
||||
nfs.MkdirAll(m, p)
|
||||
file.MkdirAll(p, ice.MOD_DIR)
|
||||
}
|
||||
|
||||
// 任务模板
|
||||
// 目录文件
|
||||
if m.Option(nfs.TEMPLATE) != "" {
|
||||
for _, file := range []string{
|
||||
ice.ETC_MISS_SH, ice.SRC_MAIN_SHY, ice.SRC_MAIN_GO,
|
||||
@ -53,7 +74,7 @@ func _dream_show(m *ice.Message, name string) {
|
||||
if kit.FileExists(path.Join(p, file)) {
|
||||
continue
|
||||
}
|
||||
switch m.Cmdy(nfs.COPY, path.Join(p, file), path.Join(m.Config(nfs.PATH), m.Option(nfs.TEMPLATE), file)); file {
|
||||
switch m.Cmdy(nfs.COPY, path.Join(p, file), path.Join(ice.USR_LOCAL_WORK, m.Option(nfs.TEMPLATE), file)); file {
|
||||
case ice.GO_MOD:
|
||||
kit.Rewrite(path.Join(p, file), func(line string) string {
|
||||
return kit.Select(line, "module "+name, strings.HasPrefix(line, "module"))
|
||||
@ -61,37 +82,26 @@ func _dream_show(m *ice.Message, name string) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 任务脚本
|
||||
m.Cmd(nfs.DEFS, path.Join(p, ice.ETC_MISS_SH), m.Config("miss"))
|
||||
defer m.Cmdy(nfs.DIR, p)
|
||||
|
||||
if pid := m.Cmdx(nfs.CAT, path.Join(p, m.Conf(gdb.SIGNAL, kit.Keym(nfs.PATH)))); pid != "" && kit.FileExists("/proc/"+pid) {
|
||||
m.Info("already exists %v", pid)
|
||||
return // 已经启动
|
||||
} else if m.Cmd(SPACE, name).Length() > 0 {
|
||||
return // 已经启动
|
||||
}
|
||||
|
||||
defer m.ToastProcess()()
|
||||
|
||||
m.Optionv(cli.CMD_DIR, p)
|
||||
// 环境变量
|
||||
m.Optionv(cli.CMD_DIR, kit.Path(p))
|
||||
m.Optionv(cli.CMD_ENV, kit.Simple(
|
||||
cli.CTX_OPS, "http://:"+m.Cmd(SERVE, ice.OptionFields("")).Append(tcp.PORT),
|
||||
cli.PATH, cli.BinPath(kit.Path(p, ice.BIN)), cli.HOME, kit.Env(cli.HOME),
|
||||
cli.SHELL, kit.Env(cli.SHELL), cli.TERM, kit.Env(cli.TERM),
|
||||
cli.TERM, kit.Env(cli.TERM), cli.SHELL, kit.Env(cli.SHELL),
|
||||
cli.USER, ice.Info.UserName, m.Configv(cli.ENV),
|
||||
))
|
||||
m.Optionv(cli.CMD_OUTPUT, path.Join(p, ice.BIN_BOOT_LOG))
|
||||
|
||||
// 启动任务
|
||||
defer m.ToastProcess()()
|
||||
bin := kit.Select(os.Args[0], cli.SystemFind(m, ice.ICE_BIN, kit.Path(path.Join(p, ice.BIN)), kit.Path(ice.BIN)))
|
||||
m.Cmd(cli.DAEMON, bin, SPACE, tcp.DIAL, ice.DEV, ice.OPS, m.OptionSimple(mdb.NAME, RIVER))
|
||||
|
||||
m.Sleep3s()
|
||||
m.Option(cli.CMD_ENV, "")
|
||||
m.Option(cli.CMD_OUTPUT, "")
|
||||
m.Event(DREAM_CREATE, kit.SimpleKV("", m.Option(mdb.TYPE), name)...)
|
||||
m.Event(DREAM_CREATE, m.OptionSimple(mdb.TYPE, mdb.NAME)...)
|
||||
}
|
||||
|
||||
const (
|
||||
@ -102,8 +112,8 @@ const (
|
||||
const DREAM = "dream"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
DREAM: {Name: "dream name path auto start", Help: "梦想家", Actions: ice.Actions{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
DREAM: {Name: "dream name path auto start", Help: "梦想家", Actions: ice.MergeAction(ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Config("miss", _dream_miss)
|
||||
}},
|
||||
@ -129,10 +139,10 @@ func init() {
|
||||
cli.STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmd(SPACE, mdb.MODIFY, m.OptionSimple(mdb.NAME), mdb.STATUS, cli.STOP)
|
||||
m.Cmd(SPACE, m.Option(mdb.NAME), ice.EXIT)
|
||||
m.ProcessRefresh("100ms")
|
||||
m.ProcessRefresh30ms()
|
||||
}},
|
||||
DREAM_STOP: {Name: "dream.stop type name", Help: "停止", Hand: func(m *ice.Message, arg ...string) {
|
||||
if m.Cmd(SPACE, m.Option(mdb.NAME)).Append(mdb.STATUS) == cli.STOP {
|
||||
if m.CmdAppend(SPACE, m.Option(mdb.NAME), mdb.STATUS) == cli.STOP {
|
||||
m.Cmd(mdb.DELETE, m.Prefix(SPACE), "", mdb.HASH, m.OptionSimple(mdb.NAME))
|
||||
} else {
|
||||
m.Cmd(mdb.DELETE, m.Prefix(SPACE), "", mdb.HASH, m.OptionSimple(mdb.NAME))
|
||||
@ -140,42 +150,19 @@ func init() {
|
||||
}
|
||||
}},
|
||||
nfs.TRASH: {Name: "trash", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmd(nfs.TRASH, mdb.CREATE, path.Join(m.Config(nfs.PATH), m.Option(mdb.NAME)))
|
||||
m.Cmd(nfs.TRASH, mdb.CREATE, path.Join(ice.USR_LOCAL_WORK, m.Option(mdb.NAME)))
|
||||
m.ProcessRefresh30ms()
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
if start := 0; len(arg) == 0 {
|
||||
_dream_list(m).SetAppend(mdb.TEXT)
|
||||
m.Tables(func(value ice.Maps) {
|
||||
if value[cli.STATUS] != cli.START {
|
||||
m.Push(mdb.TEXT, "")
|
||||
return
|
||||
}
|
||||
start++
|
||||
text := []string{}
|
||||
for _, line := range kit.Split(m.Cmdx(SPACE, value[mdb.NAME], cli.SYSTEM, "git", "diff", "--shortstat"), ice.FS, ice.FS) {
|
||||
if list := kit.Split(line); strings.Contains(line, "file") {
|
||||
text = append(text, list[0]+" file")
|
||||
} else if strings.Contains(line, "ins") {
|
||||
text = append(text, list[0]+" +++")
|
||||
} else if strings.Contains(line, "dele") {
|
||||
text = append(text, list[0]+" ---")
|
||||
}
|
||||
}
|
||||
m.Push(mdb.TEXT, strings.Join(text, ", "))
|
||||
}).Sort("status,type,name").StatusTimeCount(cli.START, start)
|
||||
if !m.IsMobileUA() {
|
||||
}, mdb.HashAction("miss", _dream_miss)), Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) == 0 {
|
||||
if _dream_list(m); !m.IsMobileUA() {
|
||||
m.Display("/plugin/table.js?style=card")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
m.Option(nfs.DIR_ROOT, path.Join(m.Config(nfs.PATH), arg[0]))
|
||||
m.Cmdy(nfs.CAT, arg[1:])
|
||||
m.Cmdy(nfs.CAT, arg[1:], kit.Dict(nfs.DIR_ROOT, path.Join(ice.USR_LOCAL_WORK, arg[0])))
|
||||
}},
|
||||
}, Configs: ice.Configs{
|
||||
DREAM: {Name: DREAM, Help: "梦想家", Value: kit.Data(nfs.PATH, ice.USR_LOCAL_WORK, "miss", _dream_miss)},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
||||
var _dream_miss = `#! /bin/sh
|
||||
|
@ -2,6 +2,7 @@ package web
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
@ -9,13 +10,15 @@ import (
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/aaa"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
"shylinux.com/x/icebergs/base/tcp"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
const (
|
||||
STATUS = "status"
|
||||
COOKIE = "cookie"
|
||||
STATUS = "status"
|
||||
)
|
||||
|
||||
func Render(msg *ice.Message, cmd string, args ...ice.Any) {
|
||||
@ -27,30 +30,34 @@ func Render(msg *ice.Message, cmd string, args ...ice.Any) {
|
||||
case COOKIE: // value [name [path [expire]]]
|
||||
RenderCookie(msg, arg[0], arg[1:]...)
|
||||
|
||||
case STATUS, ice.RENDER_STATUS: // [code [text]]
|
||||
RenderStatus(msg, kit.Int(kit.Select("200", arg, 0)), kit.Select("", arg, 1))
|
||||
|
||||
case ice.RENDER_REDIRECT: // url [arg...]
|
||||
RenderRedirect(msg, arg...)
|
||||
|
||||
case ice.RENDER_DOWNLOAD: // file [type [name]]
|
||||
if strings.HasPrefix(arg[0], "http") {
|
||||
if strings.HasPrefix(arg[0], ice.HTTP) {
|
||||
http.Redirect(msg.W, msg.R, arg[0], http.StatusSeeOther)
|
||||
break
|
||||
}
|
||||
msg.W.Header().Set("Content-Disposition", fmt.Sprintf("filename=%s", kit.Select(path.Base(kit.Select(arg[0], msg.Option("filename"))), arg, 2)))
|
||||
if RenderType(msg.W, arg[0], kit.Select("", arg, 1)); !ice.Info.Dump(msg.W, arg[0], nil) {
|
||||
RenderType(msg.W, arg[0], kit.Select("", arg, 1))
|
||||
if _, e := nfs.DiskFile.StatFile(arg[0]); e == nil {
|
||||
http.ServeFile(msg.W, msg.R, kit.Path(arg[0]))
|
||||
} else if f, e := nfs.PackFile.OpenFile(arg[0]); e == nil {
|
||||
defer f.Close()
|
||||
io.Copy(msg.W, f)
|
||||
}
|
||||
|
||||
case ice.RENDER_REDIRECT: // url [arg...]
|
||||
RenderRedirect(msg, arg...)
|
||||
|
||||
case ice.RENDER_RESULT:
|
||||
if len(arg) > 0 { // [str [arg...]]
|
||||
msg.W.Write([]byte(kit.Format(arg[0], args[1:]...)))
|
||||
} else {
|
||||
args = append(args, "length:", len(msg.Result()))
|
||||
args = append(args, nfs.SIZE, len(msg.Result()))
|
||||
msg.W.Write([]byte(msg.Result()))
|
||||
}
|
||||
|
||||
case STATUS, ice.RENDER_STATUS: // [code [text]]
|
||||
RenderStatus(msg, kit.Int(kit.Select("200", arg, 0)), kit.Select("", arg, 1))
|
||||
|
||||
case ice.RENDER_JSON:
|
||||
msg.W.Header().Set("Content-Type", "application/json")
|
||||
msg.W.Write([]byte(arg[0]))
|
||||
@ -73,26 +80,33 @@ func Render(msg *ice.Message, cmd string, args ...ice.Any) {
|
||||
msg.Echo(kit.Format(cmd, args...))
|
||||
}
|
||||
msg.W.Header().Set(ContentType, ContentJSON)
|
||||
fmt.Fprint(msg.W, msg.FormatsMeta())
|
||||
fmt.Fprint(msg.W, msg.FormatMeta())
|
||||
}
|
||||
}
|
||||
func RenderType(w http.ResponseWriter, name, mime string) {
|
||||
if mime != "" {
|
||||
w.Header().Set(ContentType, mime)
|
||||
return
|
||||
}
|
||||
|
||||
switch kit.Ext(name) {
|
||||
case nfs.CSS:
|
||||
w.Header().Set(ContentType, "text/css; charset=utf-8")
|
||||
case "pdf":
|
||||
w.Header().Set(ContentType, "application/pdf")
|
||||
}
|
||||
}
|
||||
func RenderHeader(msg *ice.Message, key, value string) {
|
||||
msg.W.Header().Set(key, value)
|
||||
}
|
||||
func RenderStatus(msg *ice.Message, code int, text string) {
|
||||
msg.W.WriteHeader(code)
|
||||
msg.W.Write([]byte(text))
|
||||
}
|
||||
func CookieName(url string) string {
|
||||
return ice.MSG_SESSID + "_" + kit.ReplaceAll(kit.ParseURLMap(url)[tcp.HOST], ".", "_", ":", "_")
|
||||
}
|
||||
func RenderCookie(msg *ice.Message, value string, arg ...string) { // name path expire
|
||||
expire := time.Now().Add(kit.Duration(kit.Select(msg.Conf(aaa.SESS, kit.Keym(aaa.EXPIRE)), arg, 2)))
|
||||
expire := time.Now().Add(kit.Duration(kit.Select(msg.Conf(aaa.SESS, kit.Keym(mdb.EXPIRE)), arg, 2)))
|
||||
http.SetCookie(msg.W, &http.Cookie{Value: value,
|
||||
Name: kit.Select(CookieName(msg.Option(ice.MSG_USERWEB)), arg, 0), Path: kit.Select(ice.PS, arg, 1), Expires: expire})
|
||||
}
|
||||
func RenderRedirect(msg *ice.Message, arg ...string) {
|
||||
http.Redirect(msg.W, msg.R, kit.MergeURL(arg[0], arg[1:]), http.StatusTemporaryRedirect)
|
||||
func RenderStatus(msg *ice.Message, code int, text string) {
|
||||
msg.W.WriteHeader(code)
|
||||
msg.W.Write([]byte(text))
|
||||
}
|
||||
func RenderRefresh(msg *ice.Message, arg ...string) { // url text delay
|
||||
msg.Render(ice.RENDER_VOID)
|
||||
@ -107,27 +121,18 @@ func RenderRefresh(msg *ice.Message, arg ...string) { // url text delay
|
||||
</html>
|
||||
`, kit.Select("3", arg, 2), kit.Select(msg.Option(ice.MSG_USERWEB), arg, 0), kit.Select("loading...", arg, 1)))
|
||||
}
|
||||
func RenderType(w http.ResponseWriter, name, mime string) {
|
||||
if mime != "" {
|
||||
w.Header().Set(ContentType, mime)
|
||||
return
|
||||
}
|
||||
|
||||
switch kit.Ext(name) {
|
||||
case "css":
|
||||
w.Header().Set(ContentType, "text/css; charset=utf-8")
|
||||
case "pdf":
|
||||
w.Header().Set(ContentType, "application/pdf")
|
||||
default:
|
||||
}
|
||||
}
|
||||
func RenderResult(msg *ice.Message, arg ...ice.Any) {
|
||||
Render(msg, ice.RENDER_RESULT, arg...)
|
||||
func RenderRedirect(msg *ice.Message, arg ...string) {
|
||||
http.Redirect(msg.W, msg.R, kit.MergeURL(arg[0], arg[1:]), http.StatusTemporaryRedirect)
|
||||
}
|
||||
func RenderDownload(msg *ice.Message, arg ...ice.Any) {
|
||||
Render(msg, ice.RENDER_DOWNLOAD, arg...)
|
||||
}
|
||||
|
||||
func RenderResult(msg *ice.Message, arg ...ice.Any) {
|
||||
Render(msg, ice.RENDER_RESULT, arg...)
|
||||
}
|
||||
func CookieName(url string) string {
|
||||
return ice.MSG_SESSID + "_" + kit.ReplaceAll(kit.ParseURLMap(url)[tcp.HOST], ".", "_", ":", "_")
|
||||
}
|
||||
func Format(tag string, arg ...ice.Any) string {
|
||||
return kit.Format("<%s>%s</%s>", tag, strings.Join(kit.Simple(arg), ""), tag)
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
func _route_travel(m *ice.Message, route string) {
|
||||
m.Richs(SPACE, nil, mdb.FOREACH, func(key string, val ice.Map) {
|
||||
m.Cmd(SPACE).Tables(func(val ice.Maps) {
|
||||
switch val[mdb.TYPE] {
|
||||
case SERVER: // 远程查询
|
||||
if val[mdb.NAME] == ice.Info.NodeName {
|
||||
@ -31,13 +31,12 @@ func _route_travel(m *ice.Message, route string) {
|
||||
}
|
||||
})
|
||||
}
|
||||
func _route_list(m *ice.Message) {
|
||||
func _route_list(m *ice.Message) *ice.Message {
|
||||
m.Tables(func(value ice.Maps) {
|
||||
m.PushAnchor(value[ROUTE], m.MergePod(value[ROUTE]))
|
||||
|
||||
switch value[mdb.TYPE] {
|
||||
case SERVER:
|
||||
m.PushButton(tcp.START)
|
||||
m.PushButton(tcp.START, aaa.INVITE)
|
||||
case WORKER:
|
||||
fallthrough
|
||||
default:
|
||||
@ -59,22 +58,19 @@ func _route_list(m *ice.Message) {
|
||||
m.Push(ROUTE, ice.Info.NodeName)
|
||||
m.PushAnchor(tcp.LOCALHOST, kit.Format("%s://%s:%s", u.Scheme, tcp.LOCALHOST, u.Port()))
|
||||
m.PushButton(tcp.START)
|
||||
return m
|
||||
}
|
||||
|
||||
const ROUTE = "route"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
ROUTE: {Name: ROUTE, Help: "路由器", Value: kit.Data(mdb.SHORT, ROUTE)},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
ROUTE: {Name: "route route ctx cmd auto invite spide", Help: "路由器", Actions: ice.Actions{
|
||||
aaa.INVITE: {Name: "invite", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(SPACE, m.Option(ROUTE), SPACE, aaa.INVITE, arg)
|
||||
m.ProcessInner()
|
||||
m.Cmdy(SPACE, m.Option(ROUTE), SPACE, aaa.INVITE, arg).ProcessInner()
|
||||
}},
|
||||
cli.START: {Name: "start name repos template", Help: "启动", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(SPACE, m.Option(ROUTE), DREAM, tcp.START, arg)
|
||||
m.ProcessInner()
|
||||
m.Cmdy(SPACE, m.Option(ROUTE), DREAM, tcp.START, arg).ProcessInner()
|
||||
}},
|
||||
ctx.COMMAND: {Name: "command", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(SPACE, m.Option(ROUTE), kit.Keys(m.Option(ice.CTX), m.Option(ice.CMD)), arg)
|
||||
@ -85,7 +81,7 @@ func init() {
|
||||
SPIDE: {Name: "spide", Help: "架构图", Hand: func(m *ice.Message, arg ...string) {
|
||||
if m.Option(ROUTE) == "" { // 路由列表 route
|
||||
m.Cmdy(ROUTE).Cut(ROUTE)
|
||||
m.Display("/plugin/story/spide.js?prefix=spide", lex.SPLIT, ice.PT)
|
||||
m.DisplayStorySpide("prefix", "spide", lex.SPLIT, ice.PT)
|
||||
|
||||
} else if m.Option(ctx.CONTEXT) == "" { // 模块列表 context
|
||||
m.Cmdy(SPACE, m.Option(ROUTE), ctx.CONTEXT, ice.ICE, ctx.CONTEXT).Cut(mdb.NAME).RenameAppend(mdb.NAME, ctx.CONTEXT)
|
||||
@ -101,8 +97,7 @@ func init() {
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) == 0 || arg[0] == "" { // 路由列表
|
||||
if _route_travel(m, kit.Select("", arg, 0)); m.W != nil {
|
||||
_route_list(m)
|
||||
m.Sort("type,route")
|
||||
_route_list(m).Sort("type,route")
|
||||
}
|
||||
|
||||
} else if len(arg) == 1 || arg[1] == "" { // 模块列表
|
||||
@ -122,5 +117,5 @@ func init() {
|
||||
m.ProcessField(ctx.ACTION, ctx.COMMAND)
|
||||
}
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package web
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
@ -17,12 +18,48 @@ import (
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
"shylinux.com/x/icebergs/base/tcp"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
"shylinux.com/x/toolkits/logs"
|
||||
)
|
||||
|
||||
var rewriteList = []ice.Any{}
|
||||
|
||||
func AddRewrite(cb ice.Any) { rewriteList = append(rewriteList, cb) }
|
||||
|
||||
func _serve_rewrite(m *ice.Message) {
|
||||
AddRewrite(func(w http.ResponseWriter, r *http.Request) bool {
|
||||
msg, repos := m.Spawn(SERVE, w, r), kit.Select(ice.INTSHELL, ice.VOLCANOS, strings.Contains(r.Header.Get("User-Agent"), "Mozilla/5.0"))
|
||||
if r.Method == SPIDE_GET {
|
||||
switch r.URL.Path {
|
||||
case ice.PS:
|
||||
if repos == ice.VOLCANOS {
|
||||
if s := msg.Cmdx("web.chat.website", lex.PARSE, ice.INDEX_IML, "Header", "", "River", "", "Footer", ""); s != "" {
|
||||
Render(msg, ice.RENDER_RESULT, s)
|
||||
return true // 定制主页
|
||||
}
|
||||
}
|
||||
Render(msg, ice.RENDER_DOWNLOAD, path.Join(msg.Config(kit.Keys(repos, nfs.PATH)), msg.Config(kit.Keys(repos, INDEX))))
|
||||
return true // 默认主页
|
||||
|
||||
case PP(ice.HELP):
|
||||
r.URL.Path = P(ice.HELP, ice.TUTOR_SHY)
|
||||
}
|
||||
p := path.Join(ice.USR, repos, r.URL.Path)
|
||||
m.Debug("what %v", p)
|
||||
if _, e := nfs.DiskFile.StatFile(p); e == nil {
|
||||
m.Debug("what %v", p)
|
||||
http.ServeFile(w, r, kit.Path(p))
|
||||
return true
|
||||
} else if f, e := nfs.PackFile.OpenFile(p); e == nil {
|
||||
defer f.Close()
|
||||
m.Debug("what %v", p)
|
||||
RenderType(w, p, "")
|
||||
io.Copy(w, f)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
func _serve_domain(m *ice.Message) string {
|
||||
if p := m.Config(DOMAIN); p != "" {
|
||||
return p
|
||||
@ -41,6 +78,36 @@ func _serve_domain(m *ice.Message) string {
|
||||
return kit.Format("https://%s", m.R.Host)
|
||||
}
|
||||
}
|
||||
func _serve_spide(m *ice.Message, prefix string, c *ice.Context) {
|
||||
for k := range c.Commands {
|
||||
if strings.HasPrefix(k, ice.PS) {
|
||||
m.Push(nfs.PATH, path.Join(prefix, k)+kit.Select("", ice.PS, strings.HasSuffix(k, ice.PS)))
|
||||
}
|
||||
}
|
||||
for k, v := range c.Contexts {
|
||||
_serve_spide(m, path.Join(prefix, k), v)
|
||||
}
|
||||
}
|
||||
func _serve_start(m *ice.Message) {
|
||||
ice.Info.Domain = kit.Select(kit.Format("%s://%s:%s", m.Option(tcp.PROTO), kit.Select(m.Cmd(tcp.HOST).Append(aaa.IP), m.Option(tcp.HOST)), m.Option(tcp.PORT)), ice.Info.Domain)
|
||||
if cli.NodeInfo(m, SERVER, kit.Select(ice.Info.HostName, m.Option("nodename"))); m.Option(tcp.PORT) == tcp.RANDOM {
|
||||
m.Option(tcp.PORT, m.Cmdx(tcp.PORT, aaa.RIGHT))
|
||||
}
|
||||
|
||||
if m.Option("staffname") != "" {
|
||||
m.Config("staffname", m.Option(aaa.USERNAME, m.Option("staffname")))
|
||||
}
|
||||
aaa.UserRoot(m, m.Option(aaa.PASSWORD), m.Option(aaa.USERNAME), m.Option(aaa.USERROLE))
|
||||
|
||||
m.Target().Start(m, m.OptionSimple(tcp.HOST, tcp.PORT)...)
|
||||
m.Go(func() { m.Cmd(BROAD, SERVE) })
|
||||
m.Sleep300ms()
|
||||
|
||||
for _, k := range kit.Split(m.Option(ice.DEV)) {
|
||||
m.Cmd(SPACE, tcp.DIAL, ice.DEV, k, mdb.NAME, ice.Info.NodeName)
|
||||
}
|
||||
}
|
||||
|
||||
func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool {
|
||||
if r.Header.Get("Index-Module") == "" {
|
||||
r.Header.Set("Index-Module", m.Prefix())
|
||||
@ -60,19 +127,20 @@ func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool {
|
||||
} else {
|
||||
r.Header.Set(ice.MSG_USERIP, strings.Split(r.RemoteAddr, ":")[0])
|
||||
}
|
||||
m.Info("%s %s %s", r.Header.Get(ice.MSG_USERIP), r.Method, r.URL)
|
||||
meta := logs.FileLineMeta("")
|
||||
m.Info("%s %s %s", r.Header.Get(ice.MSG_USERIP), r.Method, r.URL, meta)
|
||||
|
||||
// 参数日志
|
||||
if m.Config(LOGHEADERS) == ice.TRUE {
|
||||
for k, v := range r.Header {
|
||||
m.Info("%s: %v", k, kit.Format(v))
|
||||
m.Info("%s: %v", k, kit.Format(v), meta)
|
||||
}
|
||||
m.Info("")
|
||||
m.Info("", meta)
|
||||
|
||||
defer func() {
|
||||
m.Info("")
|
||||
m.Info("", meta)
|
||||
for k, v := range w.Header() {
|
||||
m.Info("%s: %v", k, kit.Format(v))
|
||||
m.Info("%s: %v", k, kit.Format(v), meta)
|
||||
}
|
||||
}()
|
||||
}
|
||||
@ -80,7 +148,7 @@ func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool {
|
||||
// 模块回调
|
||||
for _, h := range rewriteList {
|
||||
if m.Config(LOGHEADERS) == ice.TRUE {
|
||||
m.Info("%s: %v", r.URL.Path, kit.FileLine(h, 3))
|
||||
m.Info("%s: %v", r.URL.Path, kit.FileLine(h, 3), meta)
|
||||
}
|
||||
switch h := h.(type) {
|
||||
case func(w http.ResponseWriter, r *http.Request) func():
|
||||
@ -95,7 +163,7 @@ func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
m.Error(true, ice.ErrNotImplement)
|
||||
m.ErrorNotImplement(h)
|
||||
}
|
||||
}
|
||||
return true
|
||||
@ -131,7 +199,7 @@ func _serve_handle(key string, cmd *ice.Command, msg *ice.Message, w http.Respon
|
||||
}
|
||||
_serve_params(msg, r.URL.Path)
|
||||
|
||||
// 请求参数
|
||||
// 解析参数
|
||||
switch r.Header.Get(ContentType) {
|
||||
case ContentJSON:
|
||||
defer r.Body.Close()
|
||||
@ -145,11 +213,12 @@ func _serve_handle(key string, cmd *ice.Command, msg *ice.Message, w http.Respon
|
||||
default:
|
||||
r.ParseMultipartForm(kit.Int64(kit.Select("4096", r.Header.Get(ContentLength))))
|
||||
if r.ParseForm(); len(r.PostForm) > 0 {
|
||||
meta := logs.FileLineMeta("")
|
||||
for k, v := range r.PostForm {
|
||||
if len(v) > 1 {
|
||||
msg.Logs("form", k, len(v), kit.Join(v, ice.SP))
|
||||
msg.Logs("form", k, len(v), kit.Join(v, ice.SP), meta)
|
||||
} else {
|
||||
msg.Logs("form", k, v)
|
||||
msg.Logs("form", k, v, meta)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -163,16 +232,11 @@ func _serve_handle(key string, cmd *ice.Command, msg *ice.Message, w http.Respon
|
||||
v[i], _ = url.QueryUnescape(p)
|
||||
}
|
||||
}
|
||||
if msg.Optionv(k, v); k == ice.MSG_SESSID {
|
||||
msg.Option(ice.MSG_SESSID, v[0])
|
||||
RenderCookie(msg, v[0])
|
||||
}
|
||||
msg.Optionv(k, v)
|
||||
}
|
||||
for k, v := range r.PostForm {
|
||||
msg.Optionv(k, v)
|
||||
}
|
||||
|
||||
// 会话参数
|
||||
for _, v := range r.Cookies() {
|
||||
msg.Option(v.Name, v.Value)
|
||||
}
|
||||
@ -181,7 +245,7 @@ func _serve_handle(key string, cmd *ice.Command, msg *ice.Message, w http.Respon
|
||||
msg.Option(ice.MSG_USERWEB, _serve_domain(msg))
|
||||
msg.Option(ice.MSG_USERADDR, kit.Select(r.RemoteAddr, r.Header.Get(ice.MSG_USERADDR)))
|
||||
msg.Option(ice.MSG_USERIP, r.Header.Get(ice.MSG_USERIP))
|
||||
msg.Option(ice.MSG_USERUA, r.Header.Get("User-Agent"))
|
||||
msg.Option(ice.MSG_USERUA, r.Header.Get(UserAgent))
|
||||
if msg.Option(ice.POD) != "" {
|
||||
msg.Option(ice.MSG_USERPOD, msg.Option(ice.POD))
|
||||
}
|
||||
@ -240,10 +304,8 @@ func _serve_login(msg *ice.Message, key string, cmds []string, w http.ResponseWr
|
||||
return cmds, msg.Result(0) != ice.ErrWarn && msg.Result(0) != ice.FALSE
|
||||
}
|
||||
|
||||
if ls := strings.Split(r.URL.Path, ice.PS); msg.Config(kit.Keys(aaa.BLACK, ls[1])) == ice.TRUE {
|
||||
return cmds, false // 黑名单
|
||||
} else if msg.Config(kit.Keys(aaa.WHITE, ls[1])) == ice.TRUE {
|
||||
return cmds, true // 白名单
|
||||
if msg.Right(key, cmds) {
|
||||
return cmds, true
|
||||
}
|
||||
|
||||
if msg.Warn(msg.Option(ice.MSG_USERNAME) == "", ice.ErrNotLogin, r.URL.Path) {
|
||||
@ -255,16 +317,6 @@ func _serve_login(msg *ice.Message, key string, cmds []string, w http.ResponseWr
|
||||
}
|
||||
return cmds, true
|
||||
}
|
||||
func _serve_spide(m *ice.Message, prefix string, c *ice.Context) {
|
||||
for k := range c.Commands {
|
||||
if strings.HasPrefix(k, ice.PS) {
|
||||
m.Push(nfs.PATH, path.Join(prefix, k)+kit.Select("", ice.PS, strings.HasSuffix(k, ice.PS)))
|
||||
}
|
||||
}
|
||||
for k, v := range c.Contexts {
|
||||
_serve_spide(m, path.Join(prefix, k), v)
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
WEB_LOGIN = "_login"
|
||||
@ -279,120 +331,58 @@ func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
SERVE: {Name: SERVE, Help: "服务器", Value: kit.Data(
|
||||
mdb.SHORT, mdb.NAME, mdb.FIELD, "time,status,name,port,dev",
|
||||
tcp.LOCALHOST, ice.TRUE, aaa.BLACK, kit.Dict(), aaa.WHITE, kit.Dict(
|
||||
LOGIN, ice.TRUE, SHARE, ice.TRUE, SPACE, ice.TRUE,
|
||||
ice.VOLCANOS, ice.TRUE, ice.PUBLISH, ice.TRUE,
|
||||
ice.INTSHELL, ice.TRUE, ice.REQUIRE, ice.TRUE,
|
||||
"cmd", ice.TRUE, ice.HELP, ice.TRUE,
|
||||
), LOGHEADERS, ice.FALSE,
|
||||
|
||||
DOMAIN, "", nfs.PATH, kit.Dict(ice.PS, ice.USR_VOLCANOS),
|
||||
DOMAIN, "", tcp.LOCALHOST, ice.TRUE, LOGHEADERS, ice.FALSE,
|
||||
nfs.PATH, kit.Dict(ice.PS, ice.USR_VOLCANOS),
|
||||
ice.VOLCANOS, kit.Dict(nfs.PATH, ice.USR_VOLCANOS, INDEX, "page/index.html",
|
||||
nfs.REPOS, "https://shylinux.com/x/volcanos", nfs.BRANCH, nfs.MASTER,
|
||||
), ice.PUBLISH, ice.USR_PUBLISH,
|
||||
|
||||
),
|
||||
ice.INTSHELL, kit.Dict(nfs.PATH, ice.USR_INTSHELL, INDEX, ice.INDEX_SH,
|
||||
nfs.REPOS, "https://shylinux.com/x/intshell", nfs.BRANCH, nfs.MASTER,
|
||||
), ice.REQUIRE, ".ish/pluged",
|
||||
),
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
SERVE: {Name: "serve name auto start spide", Help: "服务器", Actions: ice.MergeAction(ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
cli.NodeInfo(m, WORKER, ice.Info.PathName)
|
||||
AddRewrite(func(w http.ResponseWriter, r *http.Request) bool {
|
||||
w.Header().Add("Access-Control-Allow-Origin", "*")
|
||||
if r.Method == SPIDE_GET {
|
||||
switch r.URL.Path {
|
||||
case ice.PS:
|
||||
msg := m.Spawn(SERVE, w, r)
|
||||
repos := kit.Select(ice.INTSHELL, ice.VOLCANOS, strings.Contains(r.Header.Get("User-Agent"), "Mozilla/5.0"))
|
||||
if repos == ice.VOLCANOS {
|
||||
if s := msg.Cmdx("web.chat.website", lex.PARSE, "index.iml", "Header", "", "River", "", "Footer", ""); s != "" {
|
||||
Render(msg, ice.RENDER_RESULT, s)
|
||||
return true // 定制主页
|
||||
}
|
||||
}
|
||||
Render(msg, ice.RENDER_DOWNLOAD, path.Join(msg.Config(kit.Keys(repos, nfs.PATH)), msg.Config(kit.Keys(repos, INDEX))))
|
||||
return true // 默认主页
|
||||
|
||||
case "/help/":
|
||||
r.URL.Path = "/help/tutor.shy"
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
}},
|
||||
ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmd(SERVE).Tables(func(value ice.Maps) {
|
||||
m.Done(value[cli.STATUS] == tcp.START)
|
||||
})
|
||||
for _, p := range []string{LOGIN, SHARE, SPACE, ice.VOLCANOS, ice.INTSHELL, ice.PUBLISH, ice.REQUIRE, ice.HELP, ice.CMD} {
|
||||
m.Cmd(aaa.ROLE, aaa.WHITE, aaa.VOID, p)
|
||||
}
|
||||
_serve_rewrite(m)
|
||||
}},
|
||||
DOMAIN: {Name: "domain", Help: "域名", Hand: func(m *ice.Message, arg ...string) {
|
||||
ice.Info.Domain = m.Conf(SHARE, kit.Keym(DOMAIN, m.Config(DOMAIN, arg[0])))
|
||||
}},
|
||||
"list_broad": {Name: "list_broad", Help: "服务发现", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Go(func() { _serve_udp(m, m.Cmd(tcp.HOST).Append(aaa.IP), m.Option(tcp.PORT)) })
|
||||
}},
|
||||
aaa.BLACK: {Name: "black", Help: "黑名单", Hand: func(m *ice.Message, arg ...string) {
|
||||
for _, k := range arg {
|
||||
m.Log_CREATE(aaa.BLACK, k)
|
||||
m.Config(kit.Keys(aaa.BLACK, k), ice.TRUE)
|
||||
}
|
||||
}},
|
||||
aaa.WHITE: {Name: "white", Help: "白名单", Hand: func(m *ice.Message, arg ...string) {
|
||||
for _, k := range arg {
|
||||
m.Log_CREATE(aaa.WHITE, k)
|
||||
m.Config(kit.Keys(aaa.WHITE, k), ice.TRUE)
|
||||
}
|
||||
}},
|
||||
cli.START: {Name: "start dev proto=http host port=9020 nodename password username userrole staffname", Help: "启动", Hand: func(m *ice.Message, arg ...string) {
|
||||
ice.Info.Domain = kit.Select(kit.Format("%s://%s:%s", m.Option(tcp.PROTO), kit.Select(m.Cmd(tcp.HOST).Append(aaa.IP), m.Option(tcp.HOST)), m.Option(tcp.PORT)), ice.Info.Domain)
|
||||
if cli.NodeInfo(m, SERVER, kit.Select(ice.Info.HostName, m.Option("nodename"))); m.Option(tcp.PORT) == tcp.RANDOM {
|
||||
m.Option(tcp.PORT, m.Cmdx(tcp.PORT, aaa.RIGHT))
|
||||
}
|
||||
if m.Option("staffname") != "" {
|
||||
m.Config("staffname", m.Option(aaa.USERNAME, m.Option("staffname")))
|
||||
}
|
||||
aaa.UserRoot(m, m.Option(aaa.PASSWORD), m.Option(aaa.USERNAME), m.Option(aaa.USERROLE))
|
||||
|
||||
m.Go(func() { m.Cmd(BROAD, SERVE) })
|
||||
m.Target().Start(m, m.OptionSimple(tcp.HOST, tcp.PORT)...)
|
||||
m.Sleep300ms()
|
||||
|
||||
for _, k := range kit.Split(m.Option(ice.DEV)) {
|
||||
m.Cmd(SPACE, tcp.DIAL, ice.DEV, k, mdb.NAME, ice.Info.NodeName)
|
||||
}
|
||||
_serve_start(m)
|
||||
}},
|
||||
"spide": {Name: "spide", Help: "架构图", Hand: func(m *ice.Message, arg ...string) {
|
||||
SPIDE: {Name: "spide", Help: "架构图", Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) == 0 { // 模块列表
|
||||
m.Display("/plugin/story/spide.js", "root", ice.ICE, "prefix", "spide")
|
||||
_serve_spide(m, ice.PS, m.Target())
|
||||
m.StatusTimeCount()
|
||||
return
|
||||
m.DisplayStorySpide(lex.PREFIX, m.ActionKey(), nfs.ROOT, m.MergeLink(ice.PS))
|
||||
}
|
||||
}},
|
||||
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.HashSelect(m, arg...)
|
||||
}},
|
||||
}, mdb.HashAction())},
|
||||
|
||||
"/intshell/": {Name: "/intshell/", Help: "命令行", Hand: func(m *ice.Message, arg ...string) {
|
||||
PP(ice.INTSHELL): {Name: "/intshell/", Help: "命令行", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.RenderIndex(SERVE, ice.INTSHELL, arg...)
|
||||
}},
|
||||
"/volcanos/": {Name: "/volcanos/", Help: "浏览器", Hand: func(m *ice.Message, arg ...string) {
|
||||
PP(ice.VOLCANOS): {Name: "/volcanos/", Help: "浏览器", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.RenderIndex(SERVE, ice.VOLCANOS, arg...)
|
||||
}},
|
||||
"/require/src/": {Name: "/require/src/", Help: "代码库", Hand: func(m *ice.Message, arg ...string) {
|
||||
if p := path.Join(ice.SRC, path.Join(arg...)); m.Option(ice.POD) != "" {
|
||||
m.RenderResult(m.Cmdx(SPACE, m.Option(ice.POD), nfs.CAT, p))
|
||||
} else {
|
||||
m.RenderDownload(p)
|
||||
}
|
||||
PP(ice.PUBLISH): {Name: "/publish/", Help: "定制化", Hand: func(m *ice.Message, arg ...string) {
|
||||
_share_local(aaa.UserRoot(m), ice.USR_PUBLISH, path.Join(arg...))
|
||||
}},
|
||||
"/require/usr/": {Name: "/require/usr/", Help: "代码库", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.RenderDownload(path.Join(ice.USR, path.Join(arg...)))
|
||||
PP(ice.REQUIRE): {Name: "/require/shylinux.com/x/volcanos/proto.js", Help: "代码库", Hand: func(m *ice.Message, arg ...string) {
|
||||
_share_repos(m, path.Join(arg[0], arg[1], arg[2]), arg[3:]...)
|
||||
}},
|
||||
"/require/node_modules/": {Name: "/require/node_modules/", Help: "依赖库", Hand: func(m *ice.Message, arg ...string) {
|
||||
p := path.Join(ice.USR_VOLCANOS, "node_modules", path.Join(arg...))
|
||||
PP(ice.REQUIRE, ice.SRC): {Name: "/require/src/", Help: "源代码", Hand: func(m *ice.Message, arg ...string) {
|
||||
_share_local(aaa.UserRoot(m), ice.SRC, path.Join(arg...))
|
||||
}},
|
||||
PP(ice.REQUIRE, ice.USR): {Name: "/require/usr/", Help: "代码库", Hand: func(m *ice.Message, arg ...string) {
|
||||
_share_local(aaa.UserRoot(m), ice.USR, path.Join(arg...))
|
||||
}},
|
||||
PP(ice.REQUIRE, ice.NODE_MODULES): {Name: "/require/node_modules/", Help: "依赖库", Hand: func(m *ice.Message, arg ...string) {
|
||||
p := path.Join(ice.USR_VOLCANOS, ice.NODE_MODULES, path.Join(arg...))
|
||||
if b, ok := ice.Info.Pack[p]; ok && len(b) > 0 {
|
||||
|
||||
} else if _, e := os.Stat(p); e != nil {
|
||||
@ -400,18 +390,7 @@ func init() {
|
||||
}
|
||||
m.RenderDownload(p)
|
||||
}},
|
||||
"/require/": {Name: "/require/", Help: "代码库", Hand: func(m *ice.Message, arg ...string) {
|
||||
_share_repos(m, path.Join(arg[0], arg[1], arg[2]), arg[3:]...)
|
||||
}},
|
||||
"/publish/": {Name: "/publish/", Help: "定制化", Hand: func(m *ice.Message, arg ...string) {
|
||||
if strings.HasPrefix(arg[0], "ice.") && m.Option(ice.POD) != "" {
|
||||
_share_local(aaa.UserRoot(m), path.Join(ice.USR_PUBLISH, arg[0]))
|
||||
// _share_local(aaa.UserRoot(m), ice.BIN_ICE_BIN)
|
||||
return
|
||||
}
|
||||
_share_local(m, m.Conf(SERVE, kit.Keym(ice.PUBLISH)), path.Join(arg...))
|
||||
}},
|
||||
"/help/": {Name: "/help/", Help: "帮助", Hand: func(m *ice.Message, arg ...string) {
|
||||
PP(ice.HELP): {Name: "/help/", Help: "帮助", Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) == 0 {
|
||||
arg = append(arg, "tutor.shy")
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package web
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
@ -16,33 +15,27 @@ import (
|
||||
"shylinux.com/x/icebergs/base/ssh"
|
||||
"shylinux.com/x/icebergs/base/tcp"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
"shylinux.com/x/toolkits/file"
|
||||
)
|
||||
|
||||
func _share_link(m *ice.Message, p string, arg ...ice.Any) string {
|
||||
p = kit.Select("", "/share/local/", !strings.HasPrefix(p, ice.PS)) + p
|
||||
return tcp.ReplaceLocalhost(m, m.MergeURL2(p, arg...))
|
||||
}
|
||||
func _share_repos(m *ice.Message, repos string, arg ...string) {
|
||||
if repos == ice.Info.Make.Module && kit.FileExists(path.Join(arg...)) {
|
||||
m.RenderDownload(path.Join(arg...))
|
||||
return
|
||||
}
|
||||
prefix := kit.Path(m.Conf(SERVE, kit.Keym(ice.REQUIRE)))
|
||||
if !kit.FileExists(path.Join(prefix, repos)) { // 克隆代码
|
||||
m.Cmd("web.code.git.repos", mdb.CREATE, nfs.REPOS, "https://"+repos, nfs.PATH, path.Join(prefix, repos))
|
||||
}
|
||||
m.RenderDownload(path.Join(prefix, repos, path.Join(arg...)))
|
||||
}
|
||||
func _share_proxy(m *ice.Message) {
|
||||
switch p := path.Join(ice.VAR_PROXY, m.Option(ice.POD), m.Option(nfs.PATH)); m.R.Method {
|
||||
case http.MethodGet: // 下发文件
|
||||
m.RenderDownload(path.Join(p, m.Option(mdb.NAME)))
|
||||
func _share_render(m *ice.Message, arg ...string) {
|
||||
ice.AddRender(ice.RENDER_DOWNLOAD, func(msg *ice.Message, cmd string, args ...ice.Any) string {
|
||||
list := []string{}
|
||||
if msg.Option(ice.MSG_USERPOD) != "" {
|
||||
list = append(list, ice.POD, msg.Option(ice.MSG_USERPOD))
|
||||
}
|
||||
|
||||
case http.MethodPost: // 上传文件
|
||||
m.Cmdy(CACHE, UPLOAD)
|
||||
m.Cmdy(CACHE, WATCH, m.Option(mdb.DATA), p)
|
||||
m.RenderResult(m.Option(nfs.PATH))
|
||||
}
|
||||
arg := kit.Simple(args...)
|
||||
if len(arg) > 1 {
|
||||
list = append(list, "filename", arg[0])
|
||||
}
|
||||
return fmt.Sprintf(`<a href="%s" download="%s">%s</a>`,
|
||||
_share_link(msg, kit.Select(arg[0], arg, 1), list), path.Base(arg[0]), arg[0])
|
||||
})
|
||||
}
|
||||
func _share_link(m *ice.Message, p string, arg ...ice.Any) string {
|
||||
p = kit.Select("", SHARE_LOCAL, !strings.HasPrefix(p, ice.PS)) + p
|
||||
return tcp.ReplaceLocalhost(m, m.MergeURL2(p, arg...))
|
||||
}
|
||||
func _share_cache(m *ice.Message, arg ...string) {
|
||||
if pod := m.Option(ice.POD); m.PodCmd(CACHE, arg[0]) {
|
||||
@ -52,10 +45,10 @@ func _share_cache(m *ice.Message, arg ...string) {
|
||||
m.Option(ice.POD, pod)
|
||||
_share_local(m, m.Append(nfs.FILE))
|
||||
}
|
||||
return
|
||||
} else {
|
||||
msg := m.Cmd(CACHE, arg[0])
|
||||
m.RenderDownload(msg.Append(nfs.FILE), msg.Append(mdb.TYPE), msg.Append(mdb.NAME))
|
||||
}
|
||||
msg := m.Cmd(CACHE, arg[0])
|
||||
m.RenderDownload(msg.Append(nfs.FILE), msg.Append(mdb.TYPE), msg.Append(mdb.NAME))
|
||||
}
|
||||
func _share_local(m *ice.Message, arg ...string) {
|
||||
p := path.Join(arg...)
|
||||
@ -72,36 +65,51 @@ func _share_local(m *ice.Message, arg ...string) {
|
||||
}
|
||||
}
|
||||
|
||||
if m.Option(ice.POD) != "" { // 远程文件
|
||||
pp := path.Join(ice.VAR_PROXY, m.Option(ice.POD), p)
|
||||
cache := time.Now().Add(-time.Hour * 240000)
|
||||
var size int64
|
||||
if s, e := os.Stat(pp); e == nil {
|
||||
cache = s.ModTime()
|
||||
size = s.Size()
|
||||
}
|
||||
|
||||
// 上传文件
|
||||
if p == "bin/ice.bin" {
|
||||
aaa.UserRoot(m).Cmd(SPACE, m.Option(ice.POD), SPIDE, "submit", m.MergeURL2(SHARE_PROXY, nfs.PATH, ""), m.Option(ice.POD), p, size, cache.Format(ice.MOD_TIME))
|
||||
} else {
|
||||
m.Cmd(SPACE, m.Option(ice.POD), SPIDE, ice.DEV, SPIDE_RAW, m.MergeURL2(SHARE_PROXY, nfs.PATH, ""),
|
||||
SPIDE_PART, m.OptionSimple(ice.POD), nfs.PATH, p, nfs.SIZE, size, CACHE, cache.Format(ice.MOD_TIME), UPLOAD, "@"+p)
|
||||
|
||||
}
|
||||
|
||||
if s, e := os.Stat(pp); e == nil && !s.IsDir() {
|
||||
p = pp
|
||||
}
|
||||
if m.Option(ice.POD) == "" {
|
||||
m.RenderDownload(p)
|
||||
return // 本地文件
|
||||
}
|
||||
if strings.HasSuffix(p, path.Join(ice.USR_PUBLISH, ice.ORDER_JS)) {
|
||||
if !kit.FileExists(p) {
|
||||
m.RenderResult("")
|
||||
return
|
||||
}
|
||||
|
||||
pp := path.Join(ice.VAR_PROXY, m.Option(ice.POD), p)
|
||||
cache, size := time.Now().Add(-time.Hour*240000), int64(0)
|
||||
if s, e := file.StatFile(pp); e == nil {
|
||||
cache, size = s.ModTime(), s.Size()
|
||||
}
|
||||
|
||||
// 上传文件
|
||||
if p == "bin/ice.bin" {
|
||||
aaa.UserRoot(m).Cmd(SPACE, m.Option(ice.POD), SPIDE, "submit", m.MergeURL2(SHARE_PROXY, nfs.PATH, ""), m.Option(ice.POD), p, size, cache.Format(ice.MOD_TIME))
|
||||
} else {
|
||||
m.Cmd(SPACE, m.Option(ice.POD), SPIDE, ice.DEV, SPIDE_RAW, m.MergeURL2(SHARE_PROXY, nfs.PATH, ""),
|
||||
SPIDE_PART, m.OptionSimple(ice.POD), nfs.PATH, p, nfs.SIZE, size, CACHE, cache.Format(ice.MOD_TIME), UPLOAD, "@"+p)
|
||||
}
|
||||
if s, e := file.StatFile(pp); e == nil && !s.IsDir() {
|
||||
p = pp
|
||||
}
|
||||
|
||||
m.RenderDownload(p)
|
||||
}
|
||||
func _share_proxy(m *ice.Message) {
|
||||
switch p := path.Join(ice.VAR_PROXY, m.Option(ice.POD), m.Option(nfs.PATH)); m.R.Method {
|
||||
case http.MethodGet: // 下发文件
|
||||
m.RenderDownload(path.Join(p, m.Option(mdb.NAME)))
|
||||
|
||||
case http.MethodPost: // 上传文件
|
||||
m.Cmdy(CACHE, UPLOAD)
|
||||
m.Cmdy(CACHE, WATCH, m.Option(mdb.DATA), p)
|
||||
m.RenderResult(m.Option(nfs.PATH))
|
||||
}
|
||||
}
|
||||
func _share_repos(m *ice.Message, repos string, arg ...string) {
|
||||
if repos == ice.Info.Make.Module && kit.FileExists(path.Join(arg...)) {
|
||||
m.RenderDownload(path.Join(arg...))
|
||||
return
|
||||
}
|
||||
if !kit.FileExists(path.Join(ice.ISH_PLUGED, repos)) { // 克隆代码
|
||||
m.Cmd("web.code.git.repos", mdb.CREATE, nfs.REPOS, "https://"+repos, nfs.PATH, path.Join(ice.ISH_PLUGED, repos))
|
||||
}
|
||||
m.RenderDownload(path.Join(ice.ISH_PLUGED, repos, path.Join(arg...)))
|
||||
}
|
||||
|
||||
const (
|
||||
TOPIC = "topic"
|
||||
@ -112,9 +120,9 @@ const (
|
||||
|
||||
SHARE_TOAST = "/share/toast/"
|
||||
SHARE_CACHE = "/share/cache/"
|
||||
SHARE_REPOS = "/share/repos/"
|
||||
SHARE_PROXY = "/share/proxy/"
|
||||
SHARE_LOCAL = "/share/local/"
|
||||
SHARE_PROXY = "/share/proxy/"
|
||||
SHARE_REPOS = "/share/repos/"
|
||||
|
||||
SHARE_LOCAL_AVATAR = "/share/local/avatar/"
|
||||
SHARE_LOCAL_BACKGROUND = "/share/local/background/"
|
||||
@ -122,26 +130,10 @@ const (
|
||||
const SHARE = "share"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
SHARE: {Name: SHARE, Help: "共享链", Value: kit.Data(
|
||||
mdb.EXPIRE, "72h", mdb.FIELD, "time,hash,userrole,username,river,storm,type,name,text",
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
SHARE: {Name: "share hash auto prunes", Help: "共享链", Actions: ice.MergeAction(ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
ice.AddRender(ice.RENDER_DOWNLOAD, func(msg *ice.Message, cmd string, args ...ice.Any) string {
|
||||
list := []string{}
|
||||
if msg.Option(ice.MSG_USERPOD) != "" {
|
||||
list = append(list, ice.POD, msg.Option(ice.MSG_USERPOD))
|
||||
}
|
||||
|
||||
arg := kit.Simple(args...)
|
||||
if len(arg) > 1 {
|
||||
list = append(list, "filename", arg[0])
|
||||
}
|
||||
return fmt.Sprintf(`<a href="%s" download="%s">%s</a>`,
|
||||
_share_link(msg, kit.Select(arg[0], arg, 1), list), path.Base(arg[0]), arg[0])
|
||||
})
|
||||
_share_render(m)
|
||||
}},
|
||||
mdb.CREATE: {Name: "create type name text", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(mdb.INSERT, m.PrefixKey(), "", mdb.HASH, mdb.TIME, m.Time(m.Config(mdb.EXPIRE)),
|
||||
@ -154,38 +146,31 @@ func init() {
|
||||
m.EchoQRCode(msg.Option(mdb.LINK))
|
||||
m.ProcessInner()
|
||||
}},
|
||||
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
}, mdb.HashAction(mdb.FIELD, "time,hash,userrole,username,river,storm,type,name,text", mdb.EXPIRE, "72h")), Hand: func(m *ice.Message, arg ...string) {
|
||||
if m.PodCmd(SHARE, arg) && m.Length() > 0 {
|
||||
return
|
||||
}
|
||||
if mdb.HashSelect(m, arg...); len(arg) > 0 {
|
||||
link := _share_link(m, "/share/"+arg[0])
|
||||
link := _share_link(m, P(SHARE, arg[0]))
|
||||
m.PushQRCode(cli.QRCODE, link)
|
||||
m.PushScript(ssh.SCRIPT, link)
|
||||
m.PushAnchor(link)
|
||||
} else {
|
||||
m.Action(LOGIN)
|
||||
}
|
||||
m.PushAction(mdb.REMOVE)
|
||||
m.StatusTimeCount()
|
||||
}},
|
||||
"/share/": {Name: "/share/", Help: "共享链", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Option(SHARE, kit.Select(m.Option(SHARE), arg, 0))
|
||||
if msg := m.Cmd(SHARE, m.Option(SHARE)); kit.Int(msg.Append(mdb.TIME)) < kit.Int(msg.FormatTime()) {
|
||||
PP(SHARE): {Name: "/share/", Help: "共享链", Hand: func(m *ice.Message, arg ...string) {
|
||||
msg := m.Cmd(SHARE, m.Option(SHARE, kit.Select(m.Option(SHARE), arg, 0)))
|
||||
if kit.Int(msg.Append(mdb.TIME)) < kit.Int(msg.FormatTime()) {
|
||||
m.RenderResult("共享超时")
|
||||
return
|
||||
} else {
|
||||
switch msg.Append(mdb.TYPE) {
|
||||
case LOGIN:
|
||||
if sessid := aaa.SessCreate(m, msg.Append(aaa.USERNAME)); m.Option(ice.MSG_USERWEB) == "" {
|
||||
m.RenderRedirect(ice.PS, ice.MSG_SESSID, sessid)
|
||||
} else {
|
||||
RenderCookie(m, sessid)
|
||||
RenderRedirect(m, ice.PS)
|
||||
}
|
||||
default:
|
||||
m.RenderIndex(SERVE, ice.VOLCANOS)
|
||||
}
|
||||
}
|
||||
switch msg.Append(mdb.TYPE) {
|
||||
case LOGIN:
|
||||
sessid := aaa.SessCreate(m, msg.Append(aaa.USERNAME))
|
||||
m.RenderRedirect(ice.PS, ice.MSG_SESSID, sessid)
|
||||
default:
|
||||
m.RenderIndex(SERVE, ice.VOLCANOS)
|
||||
}
|
||||
}},
|
||||
|
||||
@ -195,22 +180,20 @@ func init() {
|
||||
SHARE_CACHE: {Name: "/share/cache/", Help: "缓存池", Hand: func(m *ice.Message, arg ...string) {
|
||||
_share_cache(m, arg...)
|
||||
}},
|
||||
SHARE_REPOS: {Name: "/share/repos/", Help: "代码库", Hand: func(m *ice.Message, arg ...string) {
|
||||
_share_repos(m, path.Join(arg[0], arg[1], arg[2]), arg[3:]...)
|
||||
}},
|
||||
SHARE_PROXY: {Name: "/share/proxy/", Help: "文件流", Hand: func(m *ice.Message, arg ...string) {
|
||||
_share_proxy(m)
|
||||
}},
|
||||
SHARE_LOCAL: {Name: "/share/local/", Help: "文件夹", Hand: func(m *ice.Message, arg ...string) {
|
||||
_share_local(m, arg...)
|
||||
}},
|
||||
SHARE_LOCAL_AVATAR: {Name: "avatar", Help: "头像", Hand: func(m *ice.Message, arg ...string) {
|
||||
// RenderType(m.W, "", "image/svg+xml")
|
||||
// m.RenderResult(`<svg font-size="32" text-anchor="middle" dominant-baseline="middle" width="80" height="60" xmlns="http://www.w3.org/2000/svg"><text x="40" y="30" stroke="red">hello</text></svg>`)
|
||||
m.RenderDownload(strings.TrimPrefix(m.Cmd(aaa.USER, m.Option(ice.MSG_USERNAME)).Append(aaa.AVATAR), SHARE_LOCAL))
|
||||
}},
|
||||
SHARE_LOCAL_BACKGROUND: {Name: "background", Help: "壁纸", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.RenderDownload(strings.TrimPrefix(m.Cmd(aaa.USER, m.Option(ice.MSG_USERNAME)).Append(aaa.BACKGROUND), SHARE_LOCAL))
|
||||
}},
|
||||
}})
|
||||
SHARE_PROXY: {Name: "/share/proxy/", Help: "文件流", Hand: func(m *ice.Message, arg ...string) {
|
||||
_share_proxy(m)
|
||||
}},
|
||||
SHARE_REPOS: {Name: "/share/repos/", Help: "代码库", Hand: func(m *ice.Message, arg ...string) {
|
||||
_share_repos(m, path.Join(arg[0], arg[1], arg[2]), arg[3:]...)
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
@ -41,109 +41,117 @@ func _space_domain(m *ice.Message) (link string) {
|
||||
return tcp.ReplaceLocalhost(m, link)
|
||||
}
|
||||
func _space_dial(m *ice.Message, dev, name string, arg ...string) {
|
||||
if strings.HasPrefix(dev, "http") {
|
||||
if strings.HasPrefix(dev, ice.HTTP) {
|
||||
m.Cmd(SPIDE, mdb.CREATE, ice.DEV, dev)
|
||||
dev = ice.DEV
|
||||
}
|
||||
|
||||
value := m.Richs(SPIDE, nil, dev, nil)
|
||||
client := kit.Value(value, tcp.CLIENT).(ice.Map)
|
||||
|
||||
host := kit.Format(client[tcp.HOSTNAME])
|
||||
proto := strings.Replace(kit.Format(client[tcp.PROTOCOL]), "http", "ws", 1)
|
||||
uri := kit.MergeURL(proto+"://"+host+"/space/", mdb.TYPE, ice.Info.NodeType, mdb.NAME, name,
|
||||
SHARE, m.Conf(cli.RUNTIME, kit.Keys("conf.ctx_share")), RIVER, m.Conf(cli.RUNTIME, kit.Keys("conf.ctx_river")), arg)
|
||||
msg := m.Cmd(SPIDE, dev)
|
||||
host := msg.Append(kit.Keys(tcp.CLIENT, tcp.HOSTNAME))
|
||||
proto := strings.Replace(msg.Append(kit.Keys(tcp.CLIENT, tcp.PROTOCOL)), ice.HTTP, "ws", 1)
|
||||
uri := kit.MergeURL(proto+"://"+host+PP(SPACE), mdb.TYPE, ice.Info.NodeType, mdb.NAME, name, SHARE, ice.Info.CtxShare, RIVER, ice.Info.CtxRiver, arg)
|
||||
u := kit.ParseURL(uri)
|
||||
|
||||
m.Go(func() {
|
||||
u := kit.ParseURL(uri)
|
||||
redial := m.Configm(REDIAL)
|
||||
frame := m.Target().Server().(*Frame)
|
||||
|
||||
for i := 0; i >= 0 && i < kit.Int(redial["c"]); i++ {
|
||||
msg := m.Spawn()
|
||||
ls := strings.Split(host, ":")
|
||||
msg.Cmd(tcp.CLIENT, tcp.DIAL, kit.SimpleKV("type,name,host,port", proto, dev, ls[0], kit.Select("443", ls, 1)), func(s net.Conn) {
|
||||
if s, _, e := websocket.NewClient(s, u, nil, kit.Int(redial["r"]), kit.Int(redial["w"])); !msg.Warn(e) {
|
||||
msg.Rich(SPACE, nil, kit.Dict(SOCKET, s, kit.SimpleKV("", MASTER, dev, host)))
|
||||
msg.Log_CREATE(SPACE, dev, "retry", i, "uri", uri)
|
||||
defer msg.Conf(SPACE, kit.KeyHash(name), "")
|
||||
ls := strings.Split(host, ":")
|
||||
args := kit.SimpleKV("type,name,host,port", proto, dev, ls[0], kit.Select("443", ls, 1))
|
||||
|
||||
// 连接成功
|
||||
if i = 0; _space_handle(msg, true, frame.send, s, dev) {
|
||||
i = -2 // 连接关闭
|
||||
redial := m.Configm(REDIAL)
|
||||
a, b, c := kit.Int(redial["a"]), kit.Int(redial["b"]), kit.Int(redial["c"])
|
||||
for i := 0; i >= 0 && i < c; i++ {
|
||||
msg := m.Spawn()
|
||||
msg.Cmd(tcp.CLIENT, tcp.DIAL, args, func(s net.Conn) {
|
||||
if s, _, e := websocket.NewClient(s, u, nil, kit.Int(redial["r"]), kit.Int(redial["w"])); !msg.Warn(e) {
|
||||
msg.Option(mdb.TARGET, s)
|
||||
msg.Log_CREATE(SPACE, dev, "retry", i, "uri", uri)
|
||||
mdb.HashCreate(msg, kit.SimpleKV("", MASTER, dev, host))
|
||||
defer mdb.HashRemove(msg, mdb.NAME, name)
|
||||
|
||||
if i = 0; _space_handle(msg, true, frame, s, dev) {
|
||||
i = -2 // 关闭连接
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 断线重连
|
||||
sleep := time.Duration(rand.Intn(kit.Int(redial["a"])*i+2)+kit.Int(redial["b"])) * time.Millisecond
|
||||
sleep := time.Duration(rand.Intn(a*(i+1))+b) * time.Millisecond
|
||||
msg.Cost("order", i, "sleep", sleep, "reconnect", dev)
|
||||
time.Sleep(sleep)
|
||||
if time.Sleep(sleep); mdb.HashSelect(msg).Length() == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
func _space_handle(m *ice.Message, safe bool, send map[string]*ice.Message, c *websocket.Conn, name string) bool {
|
||||
for running := true; running; {
|
||||
if _, b, e := c.ReadMessage(); m.Warn(e, SPACE, name) {
|
||||
func _space_handle(m *ice.Message, safe bool, frame *Frame, c *websocket.Conn, name string) bool {
|
||||
for {
|
||||
_, b, e := c.ReadMessage()
|
||||
if m.Warn(e, SPACE, name) {
|
||||
break
|
||||
} else {
|
||||
socket, msg := c, m.Spawn(b)
|
||||
target := kit.Simple(msg.Optionv(ice.MSG_TARGET))
|
||||
source := kit.Simple(msg.Optionv(ice.MSG_SOURCE), name)
|
||||
msg.Log("recv", "%v->%v %s %v", source, target, msg.Detailv(), msg.FormatMeta())
|
||||
}
|
||||
|
||||
if len(target) == 0 {
|
||||
if msg.Option(ice.MSG_HANDLE) == ice.TRUE {
|
||||
msg.Debug("what %v %v", msg.FormatMeta(), msg.FormatStack(1, 100))
|
||||
continue
|
||||
}
|
||||
if msg.Optionv(ice.MSG_HANDLE, ice.TRUE); safe { // 下行命令
|
||||
msg.Option(ice.MSG_USERROLE, kit.Select(msg.Option(ice.MSG_USERROLE), msg.Cmd(aaa.USER, msg.Option(ice.MSG_USERNAME)).Append(aaa.USERROLE)))
|
||||
if msg.Option(ice.MSG_USERROLE) == aaa.VOID && ice.Info.UserName == "demo" {
|
||||
msg.Option(ice.MSG_USERROLE, aaa.TECH)
|
||||
}
|
||||
msg.Log_AUTH(aaa.USERROLE, msg.Option(ice.MSG_USERROLE), aaa.USERNAME, msg.Option(ice.MSG_USERNAME))
|
||||
msg.Go(func() { _space_exec(msg, source, target, c, name) })
|
||||
} else { // 上行请求
|
||||
msg.Push(mdb.LINK, kit.MergePOD(_space_domain(msg), name))
|
||||
_space_echo(msg, []string{}, kit.Revert(source)[1:], c, name)
|
||||
}
|
||||
socket, msg := c, m.Spawn(b)
|
||||
target := kit.Simple(msg.Optionv(ice.MSG_TARGET))
|
||||
source := kit.Simple(msg.Optionv(ice.MSG_SOURCE), name)
|
||||
msg.Log("recv", "%v->%v %s %v", source, target, msg.Detailv(), msg.FormatMeta())
|
||||
|
||||
} else if msg.Richs(SPACE, nil, target[0], func(key string, value ice.Map) {
|
||||
if s, ok := value[SOCKET].(*websocket.Conn); ok {
|
||||
socket, source, target = s, source, target[1:]
|
||||
_space_echo(msg, source, target, socket, kit.Select("", target))
|
||||
return // 转发报文
|
||||
}
|
||||
|
||||
if msg.Warn(msg.Option(ice.MSG_HANDLE) == ice.TRUE, ice.ErrNotFound, "already handled") {
|
||||
// 回复失败
|
||||
|
||||
} else { // 下发失败
|
||||
msg.Warn(true, ice.ErrNotFound, target)
|
||||
source, target = []string{}, kit.Revert(source)[1:]
|
||||
}
|
||||
}) != nil { // 转发成功
|
||||
|
||||
} else if res, ok := send[msg.Option(ice.MSG_TARGET)]; len(target) != 1 || !ok {
|
||||
if msg.Warn(msg.Option(ice.MSG_HANDLE) == ice.TRUE, ice.ErrNotFound, target) {
|
||||
// 回复失败
|
||||
|
||||
} else { // 下发失败
|
||||
msg.Warn(true, ice.ErrNotFound, target)
|
||||
source, target = []string{}, kit.Revert(source)[1:]
|
||||
}
|
||||
|
||||
} else { // 接收响应
|
||||
m.Sleep30ms()
|
||||
res.Back(msg)
|
||||
if len(target) == 0 { // 执行命令
|
||||
if msg.Option(ice.MSG_HANDLE) == ice.TRUE { // 异常请求
|
||||
msg.Debug("what %v %v", msg.FormatMeta(), msg.FormatStack(1, 100))
|
||||
continue
|
||||
}
|
||||
if msg.Optionv(ice.MSG_HANDLE, ice.TRUE); safe { // 下行命令
|
||||
msg.Option(ice.MSG_USERROLE, kit.Select(msg.Option(ice.MSG_USERROLE), msg.Cmd(aaa.USER, msg.Option(ice.MSG_USERNAME)).Append(aaa.USERROLE)))
|
||||
if msg.Option(ice.MSG_USERROLE) == aaa.VOID && ice.Info.UserName == "demo" {
|
||||
msg.Option(ice.MSG_USERROLE, aaa.TECH)
|
||||
}
|
||||
msg.Log_AUTH(aaa.USERROLE, msg.Option(ice.MSG_USERROLE), aaa.USERNAME, msg.Option(ice.MSG_USERNAME))
|
||||
msg.Go(func() { _space_exec(msg, source, target, c, name) })
|
||||
continue
|
||||
}
|
||||
// 上行请求
|
||||
msg.Push(mdb.LINK, kit.MergePOD(_space_domain(msg), name))
|
||||
_space_echo(msg, []string{}, kit.Revert(source)[1:], c, name)
|
||||
continue
|
||||
}
|
||||
|
||||
if mdb.HashSelectDetail(msg, target[0], func(value ice.Map) { // 转发命令
|
||||
if s, ok := value[mdb.TARGET].(*websocket.Conn); ok {
|
||||
socket, source, target = s, source, target[1:]
|
||||
_space_echo(msg, source, target, socket, kit.Select("", target))
|
||||
return // 转发报文
|
||||
}
|
||||
|
||||
if msg.Warn(msg.Option(ice.MSG_HANDLE) == ice.TRUE, ice.ErrNotValid, "already handled") {
|
||||
// 回复失败
|
||||
|
||||
} else { // 下发失败
|
||||
msg.Warn(true, ice.ErrNotFound, target)
|
||||
source, target = []string{}, kit.Revert(source)[1:]
|
||||
}
|
||||
}) {
|
||||
continue
|
||||
}
|
||||
|
||||
if res, ok := frame.getSend(msg.Option(ice.MSG_TARGET)); len(target) != 1 || !ok {
|
||||
if msg.Warn(msg.Option(ice.MSG_HANDLE) == ice.TRUE, ice.ErrNotValid, target) {
|
||||
// 回复失败
|
||||
|
||||
} else { // 下发失败
|
||||
msg.Warn(true, ice.ErrNotFound, target)
|
||||
source, target = []string{}, kit.Revert(source)[1:]
|
||||
}
|
||||
continue
|
||||
} else { // 接收响应
|
||||
m.Sleep30ms()
|
||||
res.Back(msg)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
func _space_exec(msg *ice.Message, source, target []string, c *websocket.Conn, name string) {
|
||||
if msg.Right(msg.Detailv()) {
|
||||
if msg.Right(msg.Detailv()) { // 执行命令
|
||||
msg = msg.Cmd()
|
||||
}
|
||||
|
||||
@ -154,12 +162,11 @@ func _space_exec(msg *ice.Message, source, target []string, c *websocket.Conn, n
|
||||
func _space_echo(msg *ice.Message, source, target []string, c *websocket.Conn, name string) {
|
||||
msg.Optionv(ice.MSG_SOURCE, source)
|
||||
msg.Optionv(ice.MSG_TARGET, target)
|
||||
if e := c.WriteMessage(1, []byte(msg.FormatMeta())); msg.Warn(e) {
|
||||
msg.Cmd(mdb.DELETE, msg.PrefixKey(), "", mdb.HASH, mdb.NAME, name)
|
||||
if e := c.WriteMessage(1, []byte(msg.FormatMeta())); msg.Warn(e) { // 回复失败
|
||||
mdb.HashRemove(msg, mdb.NAME, name)
|
||||
c.Close()
|
||||
return
|
||||
}
|
||||
|
||||
target = append([]string{name}, target...)
|
||||
msg.Log("send", "%v->%v %v %v", source, target, msg.Detailv(), msg.FormatMeta())
|
||||
}
|
||||
@ -169,77 +176,54 @@ func _space_send(m *ice.Message, space string, arg ...string) {
|
||||
return
|
||||
}
|
||||
|
||||
target := kit.Split(space, ice.PT, ice.PT)
|
||||
m.Warn(m.Richs(SPACE, nil, target[0], func(key string, value ice.Map) {
|
||||
if socket, ok := value[SOCKET].(*websocket.Conn); !m.Warn(!ok, ice.ErrNotFound, SOCKET) {
|
||||
|
||||
// 复制选项
|
||||
for _, k := range kit.Simple(m.Optionv(ice.MSG_OPTS)) {
|
||||
switch k {
|
||||
case ice.MSG_DETAIL, ice.MSG_CMDS, ice.MSG_SESSID:
|
||||
default:
|
||||
m.Optionv(k, m.Optionv(k))
|
||||
}
|
||||
}
|
||||
m.Optionv(ice.MSG_OPTS, m.Optionv(ice.MSG_OPTS))
|
||||
m.Optionv(ice.MSG_OPTION, m.Optionv(ice.MSG_OPTS))
|
||||
|
||||
// 构造路由
|
||||
frame := m.Target().Server().(*Frame)
|
||||
id := kit.Format(m.Target().ID())
|
||||
frame.send[id] = m
|
||||
|
||||
// 下发命令
|
||||
_space_echo(m.Set(ice.MSG_DETAIL, arg...), []string{id}, target[1:], socket, target[0])
|
||||
|
||||
m.Option(TIMEOUT, m.Config(kit.Keys(TIMEOUT, "c")))
|
||||
m.Call(m.Option("_async") == "", func(res *ice.Message) *ice.Message { // 返回结果
|
||||
if delete(frame.send, id); res != nil && m != nil {
|
||||
return m.Cost(kit.Format("[%v]->%v %v %v", id, target, arg, m.Copy(res).FormatSize()))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
}) == nil, ice.ErrNotFound, space)
|
||||
}
|
||||
func _space_search(m *ice.Message, kind, name, text string, arg ...string) {
|
||||
m.Richs(SPACE, nil, mdb.FOREACH, func(key string, value ice.Map) {
|
||||
if value = kit.GetMeta(value); !strings.Contains(kit.Format(value[mdb.NAME]), name) {
|
||||
return
|
||||
}
|
||||
|
||||
switch value[mdb.TYPE] {
|
||||
case CHROME:
|
||||
|
||||
case MASTER:
|
||||
m.PushSearch(mdb.TEXT, m.Cmd(SPIDE, value[mdb.NAME], ice.OptionFields("")).Append("client.url"), value)
|
||||
// 生成参数
|
||||
for _, k := range kit.Simple(m.Optionv(ice.MSG_OPTS)) {
|
||||
switch k {
|
||||
case ice.MSG_DETAIL, ice.MSG_CMDS, ice.MSG_SESSID:
|
||||
default:
|
||||
m.PushSearch(mdb.TEXT, m.MergePod(kit.Format(value[mdb.NAME])), value)
|
||||
m.Optionv(k, m.Optionv(k))
|
||||
}
|
||||
})
|
||||
if name != "" {
|
||||
}
|
||||
m.Optionv(ice.MSG_OPTS, m.Optionv(ice.MSG_OPTS))
|
||||
m.Optionv(ice.MSG_OPTION, m.Optionv(ice.MSG_OPTS))
|
||||
m.Set(ice.MSG_DETAIL, arg...)
|
||||
|
||||
// 发送命令
|
||||
frame := m.Target().Server().(*Frame)
|
||||
target, id := kit.Split(space, ice.PT, ice.PT), ""
|
||||
if m.Warn(!mdb.HashSelectDetail(m, target[0], func(value ice.Map) {
|
||||
if socket, ok := value[mdb.TARGET].(*websocket.Conn); !m.Warn(!ok, ice.ErrNotFound, mdb.TARGET) {
|
||||
id = frame.addSend(kit.Format(m.Target().ID()), m)
|
||||
_space_echo(m, []string{id}, target[1:], socket, target[0])
|
||||
}
|
||||
}), ice.ErrNotFound, space) {
|
||||
return
|
||||
}
|
||||
m.Cmd(SERVE, ice.OptionFields("")).Tables(func(val ice.Maps) {
|
||||
m.Cmd(tcp.HOST, ice.OptionFields("")).Tables(func(value ice.Maps) {
|
||||
m.PushSearch(kit.SimpleKV("", MYSELF, value[mdb.NAME], kit.Format("http://%s:%s", value[aaa.IP], val[tcp.PORT])))
|
||||
})
|
||||
|
||||
// 返回结果
|
||||
m.Option(TIMEOUT, m.Config(kit.Keys(TIMEOUT, "c")))
|
||||
m.Call(m.Option("_async") == "", func(res *ice.Message) *ice.Message {
|
||||
if frame.delSend(id); res != nil && m != nil {
|
||||
return m.Cost(kit.Format("[%v]->%v %v %v", id, target, arg, m.Copy(res).FormatSize()))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
func _space_fork(m *ice.Message) {
|
||||
if s, e := websocket.Upgrade(m.W, m.R, nil, kit.Int(m.Config("buffer.r")), kit.Int(m.Config("buffer.w"))); m.Assert(e) {
|
||||
buffer := m.Configm(BUFFER)
|
||||
if s, e := websocket.Upgrade(m.W, m.R, nil, kit.Int(buffer["r"]), kit.Int(buffer["w"])); m.Assert(e) {
|
||||
text := kit.Select(s.RemoteAddr().String(), m.Option(ice.MSG_USERADDR))
|
||||
name := strings.ToLower(m.Option(mdb.NAME, kit.ReplaceAll(kit.Select(text, m.Option(mdb.NAME)), ".", "_", ":", "_")))
|
||||
kind := kit.Select(WORKER, m.Option(mdb.TYPE))
|
||||
args := append([]string{mdb.TYPE, kind, mdb.NAME, name}, m.OptionSimple(SHARE, RIVER)...)
|
||||
|
||||
m.Go(func() {
|
||||
h := m.Rich(SPACE, nil, kit.Dict(SOCKET, s, mdb.TEXT, kit.Select(text, m.Option(mdb.TEXT)), args))
|
||||
m.Log_CREATE(SPACE, name, mdb.TYPE, kind)
|
||||
m.Optionv(mdb.TARGET, s)
|
||||
mdb.HashCreate(m, mdb.TEXT, kit.Select(text, m.Option(mdb.TEXT)), args)
|
||||
|
||||
switch kind {
|
||||
case CHROME: // 交互节点
|
||||
defer m.Confv(SPACE, kit.Keys(mdb.HASH, h), "")
|
||||
defer mdb.HashRemove(m, mdb.NAME, name)
|
||||
m.Go(func(msg *ice.Message) {
|
||||
switch m.Option(ice.CMD) {
|
||||
case cli.PWD:
|
||||
@ -261,13 +245,36 @@ func _space_fork(m *ice.Message) {
|
||||
default: // 服务节点
|
||||
m.Event(SPACE_START, args...)
|
||||
defer m.Event(SPACE_STOP, args...)
|
||||
defer m.Cmd(mdb.DELETE, m.PrefixKey(), "", mdb.HASH, mdb.NAME, name)
|
||||
defer mdb.HashRemove(m, mdb.NAME, name)
|
||||
}
|
||||
|
||||
_space_handle(m, false, m.Target().Server().(*Frame).send, s, name)
|
||||
_space_handle(m, false, m.Target().Server().(*Frame), s, name)
|
||||
})
|
||||
}
|
||||
}
|
||||
func _space_search(m *ice.Message, kind, name, text string, arg ...string) {
|
||||
m.Cmd(SPACE, ice.OptionFields("")).Tables(func(value ice.Maps) {
|
||||
if !strings.Contains(value[mdb.NAME], name) {
|
||||
return
|
||||
}
|
||||
|
||||
switch value[mdb.TYPE] {
|
||||
case CHROME:
|
||||
|
||||
case MASTER:
|
||||
m.PushSearch(mdb.TEXT, m.Cmd(SPIDE, value[mdb.NAME], ice.OptionFields("")).Append("client.url"), value)
|
||||
default:
|
||||
m.PushSearch(mdb.TEXT, m.MergePod(value[mdb.NAME]), value)
|
||||
}
|
||||
})
|
||||
if name != "" {
|
||||
return
|
||||
}
|
||||
m.Cmd(SERVE, ice.OptionFields("")).Tables(func(val ice.Maps) {
|
||||
m.Cmd(tcp.HOST, ice.OptionFields("")).Tables(func(value ice.Maps) {
|
||||
m.PushSearch(kit.SimpleKV("", MYSELF, value[mdb.NAME], kit.Format("http://%s:%s", value[aaa.IP], val[tcp.PORT])))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const (
|
||||
CHROME = "chrome"
|
||||
@ -278,13 +285,12 @@ const (
|
||||
WORKER = "worker"
|
||||
)
|
||||
const (
|
||||
SPACE_START = "space.start"
|
||||
SPACE_STOP = "space.stop"
|
||||
|
||||
SOCKET = "socket"
|
||||
BUFFER = "buffer"
|
||||
REDIAL = "redial"
|
||||
TIMEOUT = "timeout"
|
||||
|
||||
SPACE_START = "space.start"
|
||||
SPACE_STOP = "space.stop"
|
||||
)
|
||||
const SPACE = "space"
|
||||
|
||||
@ -298,16 +304,23 @@ func init() {
|
||||
}, Commands: ice.Commands{
|
||||
SPACE: {Name: "space name cmd auto invite", Help: "空间站", Actions: ice.MergeAction(ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Conf(SPACE, mdb.HASH, "")
|
||||
m.Conf("", mdb.HASH, "")
|
||||
}},
|
||||
ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.HashSelectValue(m, func(target ice.Any) {
|
||||
if c, ok := target.(*websocket.Conn); ok {
|
||||
c.Close()
|
||||
}
|
||||
})
|
||||
m.Conf("", mdb.HASH, "")
|
||||
}},
|
||||
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmd(SPACE, mdb.MODIFY, m.OptionSimple(mdb.NAME), mdb.STATUS, cli.STOP)
|
||||
mdb.HashModify(m, m.OptionSimple(mdb.NAME), mdb.STATUS, cli.STOP)
|
||||
defer mdb.HashRemove(m, m.OptionSimple(mdb.NAME))
|
||||
m.Cmd(SPACE, m.Option(mdb.NAME), ice.EXIT)
|
||||
mdb.HashRemove(m, m.OptionSimple(mdb.NAME))
|
||||
}},
|
||||
mdb.SEARCH: {Name: "search type name text", Help: "搜索", Hand: func(m *ice.Message, arg ...string) {
|
||||
_space_search(m, arg[0], arg[1], kit.Select("", arg, 2))
|
||||
_broad_search(m, arg[0], arg[1], kit.Select("", arg, 2))
|
||||
}},
|
||||
aaa.INVITE: {Name: "invite", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
|
||||
for _, k := range []string{ice.MISC, ice.CORE, ice.BASE} {
|
||||
@ -342,7 +355,7 @@ func init() {
|
||||
// 下发命令
|
||||
_space_send(m, strings.ToLower(arg[0]), arg[1:]...)
|
||||
}},
|
||||
"/space/": {Name: "/space/ type name share river", Help: "空间站", Hand: func(m *ice.Message, arg ...string) {
|
||||
PP(SPACE): {Name: "/space/ type name share river", Help: "空间站", Hand: func(m *ice.Message, arg ...string) {
|
||||
_space_fork(m)
|
||||
}},
|
||||
}})
|
||||
|
@ -23,109 +23,100 @@ import (
|
||||
)
|
||||
|
||||
func _spide_create(m *ice.Message, name, address string) {
|
||||
if uri, e := url.Parse(address); e == nil && address != "" {
|
||||
if m.Richs(SPIDE, nil, name, func(key string, value ice.Map) {
|
||||
kit.Value(value, "client.hostname", uri.Host)
|
||||
kit.Value(value, "client.url", address)
|
||||
}) == nil {
|
||||
dir, file := path.Split(uri.EscapedPath())
|
||||
m.Echo(m.Rich(SPIDE, nil, kit.Dict(
|
||||
SPIDE_COOKIE, kit.Dict(), SPIDE_HEADER, kit.Dict(), SPIDE_CLIENT, kit.Dict(
|
||||
mdb.NAME, name, SPIDE_METHOD, SPIDE_POST, "url", address,
|
||||
tcp.PROTOCOL, uri.Scheme, tcp.HOSTNAME, uri.Host,
|
||||
nfs.PATH, dir, nfs.FILE, file, "query", uri.RawQuery,
|
||||
cli.TIMEOUT, "600s", LOGHEADERS, ice.FALSE,
|
||||
),
|
||||
)))
|
||||
}
|
||||
if uri, e := url.Parse(address); !m.Warn(e != nil || address == "") {
|
||||
dir, file := path.Split(uri.EscapedPath())
|
||||
mdb.HashCreate(m, CLIENT_NAME, name)
|
||||
mdb.HashSelectUpdate(m, name, func(value ice.Map) {
|
||||
value[SPIDE_COOKIE] = kit.Dict()
|
||||
value[SPIDE_HEADER] = kit.Dict()
|
||||
value[SPIDE_CLIENT] = kit.Dict(
|
||||
mdb.NAME, name, SPIDE_METHOD, SPIDE_POST, "url", address,
|
||||
tcp.PROTOCOL, uri.Scheme, tcp.HOSTNAME, uri.Host,
|
||||
nfs.PATH, dir, nfs.FILE, file, "query", uri.RawQuery,
|
||||
cli.TIMEOUT, "600s", LOGHEADERS, ice.FALSE,
|
||||
)
|
||||
})
|
||||
m.Log_CREATE(SPIDE, name, ADDRESS, address)
|
||||
}
|
||||
}
|
||||
func _spide_list(m *ice.Message, arg ...string) {
|
||||
m.Richs(SPIDE, nil, arg[0], func(key string, value ice.Map) {
|
||||
// 缓存方式
|
||||
cache, save := "", ""
|
||||
switch arg[1] {
|
||||
case "url":
|
||||
m.Echo("%v", kit.Value(value, "client.url"))
|
||||
return
|
||||
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:
|
||||
cache, arg = arg[1], arg[1:]
|
||||
}
|
||||
// 缓存方法
|
||||
cache, save := "", ""
|
||||
switch 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:
|
||||
cache, arg = arg[1], arg[1:]
|
||||
}
|
||||
|
||||
// 请求方法
|
||||
client := value[SPIDE_CLIENT].(ice.Map)
|
||||
method := kit.Select(SPIDE_POST, client[SPIDE_METHOD])
|
||||
switch arg = arg[1:]; arg[0] {
|
||||
case SPIDE_GET:
|
||||
method, arg = SPIDE_GET, arg[1:]
|
||||
case SPIDE_PUT:
|
||||
method, arg = SPIDE_PUT, arg[1:]
|
||||
case SPIDE_POST:
|
||||
method, arg = SPIDE_POST, arg[1:]
|
||||
case SPIDE_DELETE:
|
||||
method, arg = SPIDE_DELETE, arg[1:]
|
||||
}
|
||||
// 请求方法
|
||||
msg := mdb.HashSelect(m.Spawn(), arg[0])
|
||||
method := kit.Select(SPIDE_POST, msg.Append(CLIENT_METHOD))
|
||||
switch arg = arg[1:]; arg[0] {
|
||||
case SPIDE_GET:
|
||||
method, arg = SPIDE_GET, arg[1:]
|
||||
case SPIDE_PUT:
|
||||
method, arg = SPIDE_PUT, arg[1:]
|
||||
case SPIDE_POST:
|
||||
method, arg = SPIDE_POST, arg[1:]
|
||||
case SPIDE_DELETE:
|
||||
method, arg = SPIDE_DELETE, arg[1:]
|
||||
}
|
||||
|
||||
// 请求地址
|
||||
uri, arg := arg[0], arg[1:]
|
||||
// 构造请求
|
||||
uri, arg := arg[0], arg[1:]
|
||||
body, head, arg := _spide_body(m, method, arg...)
|
||||
req, e := http.NewRequest(method, kit.MergeURL2(msg.Append(CLIENT_URL), uri, arg), body)
|
||||
if m.Warn(e, ice.ErrNotValid, uri) {
|
||||
return
|
||||
}
|
||||
|
||||
// 请求参数
|
||||
body, head, arg := _spide_body(m, method, arg...)
|
||||
|
||||
// 构造请求
|
||||
req, e := http.NewRequest(method, kit.MergeURL2(kit.Format(client["url"]), uri, arg), body)
|
||||
if m.Warn(e, ice.ErrNotFound, uri) {
|
||||
return
|
||||
}
|
||||
|
||||
// 请求配置
|
||||
// 请求变量
|
||||
mdb.HashSelectDetail(m, msg.Append(CLIENT_NAME), func(value ice.Map) {
|
||||
_spide_head(m, req, head, value)
|
||||
})
|
||||
|
||||
// 发送请求
|
||||
res, e := _spide_send(m, req, kit.Format(client[cli.TIMEOUT]))
|
||||
if m.Warn(e, ice.ErrNotFound, uri) {
|
||||
return
|
||||
// 发送请求
|
||||
res, e := _spide_send(m, req, kit.Format(msg.Append("client.timeout")))
|
||||
if m.Warn(e, ice.ErrNotFound, uri) {
|
||||
return
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
// 请求日志
|
||||
if m.Config(LOGHEADERS) == ice.TRUE {
|
||||
for k, v := range res.Header {
|
||||
m.Debug("%v: %v", k, v)
|
||||
}
|
||||
}
|
||||
m.Cost(cli.STATUS, res.Status, nfs.SIZE, res.Header.Get(ContentLength), mdb.TYPE, res.Header.Get(ContentType))
|
||||
|
||||
if m.Config(LOGHEADERS) == ice.TRUE {
|
||||
for k, v := range res.Header {
|
||||
m.Debug("%v: %v", k, v)
|
||||
}
|
||||
}
|
||||
|
||||
// 检查结果
|
||||
defer res.Body.Close()
|
||||
m.Cost(cli.STATUS, res.Status, nfs.SIZE, res.Header.Get(ContentLength), mdb.TYPE, res.Header.Get(ContentType))
|
||||
|
||||
// 缓存配置
|
||||
// 响应变量
|
||||
mdb.HashSelectUpdate(m, msg.Append(CLIENT_NAME), func(value ice.Map) {
|
||||
for _, v := range res.Cookies() {
|
||||
kit.Value(value, kit.Keys(SPIDE_COOKIE, v.Name), v.Value)
|
||||
m.Log_IMPORT(v.Name, v.Value)
|
||||
}
|
||||
|
||||
// 错误信息
|
||||
if m.Warn(res.StatusCode != http.StatusOK, ice.ErrNotFound, uri, "status", res.Status) {
|
||||
// b, _ := ioutil.ReadAll(res.Body)
|
||||
switch m.Set(ice.MSG_RESULT); res.StatusCode {
|
||||
case http.StatusNotFound:
|
||||
m.Warn(true, ice.ErrNotFound, uri)
|
||||
return
|
||||
case http.StatusUnauthorized:
|
||||
m.Warn(true, ice.ErrNotRight, uri)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 解析结果
|
||||
_spide_save(m, cache, save, uri, res)
|
||||
})
|
||||
|
||||
// 处理异常
|
||||
if m.Warn(res.StatusCode != http.StatusOK, ice.ErrNotFound, uri, cli.STATUS, res.Status) {
|
||||
switch m.Set(ice.MSG_RESULT); res.StatusCode {
|
||||
case http.StatusNotFound:
|
||||
m.Warn(true, ice.ErrNotFound, uri)
|
||||
return
|
||||
case http.StatusUnauthorized:
|
||||
m.Warn(true, ice.ErrNotRight, uri)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 解析结果
|
||||
_spide_save(m, cache, save, uri, res)
|
||||
}
|
||||
func _spide_body(m *ice.Message, method string, arg ...string) (io.Reader, ice.Maps, []string) {
|
||||
head := ice.Maps{}
|
||||
@ -284,7 +275,7 @@ func _spide_save(m *ice.Message, cache, save, uri string, res *http.Response) {
|
||||
case SPIDE_CACHE:
|
||||
m.Optionv(RESPONSE, res)
|
||||
m.Cmdy(CACHE, DOWNLOAD, res.Header.Get(ContentType), uri)
|
||||
m.Echo(m.Append(DATA))
|
||||
m.Echo(m.Append(mdb.DATA))
|
||||
|
||||
default:
|
||||
b, _ := ioutil.ReadAll(res.Body)
|
||||
@ -302,25 +293,30 @@ func _spide_save(m *ice.Message, cache, save, uri string, res *http.Response) {
|
||||
}
|
||||
|
||||
const (
|
||||
// 缓存方法
|
||||
SPIDE_RAW = "raw"
|
||||
SPIDE_MSG = "msg"
|
||||
SPIDE_SAVE = "save"
|
||||
SPIDE_CACHE = "cache"
|
||||
|
||||
// 请求方法
|
||||
SPIDE_GET = "GET"
|
||||
SPIDE_PUT = "PUT"
|
||||
SPIDE_POST = "POST"
|
||||
SPIDE_DELETE = "DELETE"
|
||||
|
||||
// 请求参数
|
||||
SPIDE_BODY = "body"
|
||||
SPIDE_FORM = "form"
|
||||
SPIDE_PART = "part"
|
||||
SPIDE_JSON = "json"
|
||||
SPIDE_DATA = "data"
|
||||
SPIDE_FILE = "file"
|
||||
SPIDE_JSON = "json"
|
||||
|
||||
// 响应数据
|
||||
SPIDE_RES = "content_data"
|
||||
|
||||
// 请求头
|
||||
Bearer = "Bearer"
|
||||
Authorization = "Authorization"
|
||||
ContentType = "Content-Type"
|
||||
@ -328,6 +324,7 @@ const (
|
||||
UserAgent = "User-Agent"
|
||||
Accept = "Accept"
|
||||
|
||||
// 数据格式
|
||||
ContentFORM = "application/x-www-form-urlencoded"
|
||||
ContentJSON = "application/json"
|
||||
ContentHTML = "text/html"
|
||||
@ -340,30 +337,30 @@ const (
|
||||
SPIDE_HEADER = "header"
|
||||
SPIDE_COOKIE = "cookie"
|
||||
|
||||
CLIENT_NAME = "client.name"
|
||||
CLIENT_METHOD = "client.method"
|
||||
CLIENT_URL = "client.url"
|
||||
LOGHEADERS = "logheaders"
|
||||
|
||||
FORM = "form"
|
||||
ADDRESS = "address"
|
||||
REQUEST = "request"
|
||||
RESPONSE = "response"
|
||||
|
||||
CLIENT_NAME = "client.name"
|
||||
CLIENT_URL = "client.url"
|
||||
LOGHEADERS = "logheaders"
|
||||
|
||||
MERGE = "merge"
|
||||
MERGE = "merge"
|
||||
SUBMIT = "submit"
|
||||
)
|
||||
const SPIDE = "spide"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
SPIDE: {Name: SPIDE, Help: "蜘蛛侠", Value: kit.Data(mdb.SHORT, CLIENT_NAME, mdb.FIELD, "time,client.name,client.url", LOGHEADERS, ice.FALSE)},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
SPIDE: {Name: "spide client.name action=raw,msg,save,cache method=GET,PUT,POST,DELETE url format=form,part,json,data,file arg run create", Help: "蜘蛛侠", Actions: ice.MergeAction(ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
conf := m.Confm(cli.RUNTIME, "conf")
|
||||
m.Cmd(SPIDE, mdb.CREATE, ice.OPS, kit.Select("http://127.0.0.1:9020", conf["ctx_ops"]))
|
||||
m.Cmd(SPIDE, mdb.CREATE, ice.DEV, kit.Select("http://contexts.woa.com:80", conf["ctx_dev"]))
|
||||
m.Cmd(SPIDE, mdb.CREATE, ice.SHY, kit.Select("https://shylinux.com:443", conf["ctx_shy"]))
|
||||
m.Cmd(aaa.ROLE, aaa.WHITE, aaa.VOID, SPIDE, "submit")
|
||||
conf := m.Confm(cli.RUNTIME, cli.CONF)
|
||||
m.Cmd(SPIDE, mdb.CREATE, ice.OPS, kit.Select("http://127.0.0.1:9020", conf[cli.CTX_OPS]))
|
||||
m.Cmd(SPIDE, mdb.CREATE, ice.DEV, kit.Select("http://contexts.woa.com:80", conf[cli.CTX_DEV]))
|
||||
m.Cmd(SPIDE, mdb.CREATE, ice.SHY, kit.Select("https://shylinux.com:443", conf[cli.CTX_SHY]))
|
||||
m.Cmd(aaa.ROLE, aaa.WHITE, aaa.VOID, SPIDE, SUBMIT)
|
||||
}},
|
||||
mdb.CREATE: {Name: "create name address", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
|
||||
_spide_create(m, m.Option(mdb.NAME), m.Option(ADDRESS))
|
||||
@ -371,38 +368,24 @@ func init() {
|
||||
MERGE: {Name: "merge name path", Help: "拼接", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Echo(kit.MergeURL2(m.Cmd(SPIDE, arg[0], ice.OptionFields("")).Append(CLIENT_URL), arg[1], arg[2:]))
|
||||
}},
|
||||
"submit": {Name: "submit dev pod path size cache", Help: "发布", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(SPIDE, ice.DEV, SPIDE_RAW, m.Option("dev"), SPIDE_PART, "pod", m.Option("pod"), nfs.PATH, "bin/ice.bin", UPLOAD, "@"+"bin/ice.bin")
|
||||
SUBMIT: {Name: "submit dev pod path size cache", Help: "发布", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(SPIDE, ice.DEV, SPIDE_RAW, m.Option(ice.DEV), SPIDE_PART, m.OptionSimple(ice.POD), nfs.PATH, ice.BIN_ICE_BIN, UPLOAD, "@"+ice.BIN_ICE_BIN)
|
||||
}},
|
||||
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
}, mdb.HashAction(mdb.SHORT, CLIENT_NAME, mdb.FIELD, "time,client.name,client.url", LOGHEADERS, ice.FALSE)), Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) < 2 || arg[0] == "" || (len(arg) > 3 && arg[3] == "") {
|
||||
mdb.HashSelect(m, kit.Slice(arg, 0, 1)...)
|
||||
m.Sort("client.name")
|
||||
return
|
||||
mdb.HashSelect(m, kit.Slice(arg, 0, 1)...).Sort(CLIENT_NAME)
|
||||
} else {
|
||||
_spide_list(m, arg...)
|
||||
}
|
||||
_spide_list(m, arg...)
|
||||
}},
|
||||
|
||||
SPIDE_GET: {Name: "GET url key value run", Help: "蜘蛛侠", Actions: ice.Actions{
|
||||
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(mdb.DELETE, SPIDE, "", mdb.HASH, m.OptionSimple(CLIENT_NAME))
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
SPIDE_GET: {Name: "GET url key value run", Help: "蜘蛛侠", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Echo(kit.Formats(kit.UnMarshal(m.Cmdx(SPIDE, ice.DEV, SPIDE_RAW, SPIDE_GET, arg[0], arg[1:]))))
|
||||
}},
|
||||
SPIDE_POST: {Name: "POST url key value run", Help: "蜘蛛侠", Actions: ice.Actions{
|
||||
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(mdb.DELETE, SPIDE, "", mdb.HASH, m.OptionSimple(CLIENT_NAME))
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
SPIDE_POST: {Name: "POST url key value run", Help: "蜘蛛侠", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Echo(kit.Formats(kit.UnMarshal(m.Cmdx(SPIDE, ice.DEV, SPIDE_RAW, SPIDE_POST, arg[0], arg[1:]))))
|
||||
}},
|
||||
SPIDE_DELETE: {Name: "DELETE url key value run", Help: "蜘蛛侠", Actions: ice.Actions{
|
||||
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(mdb.DELETE, SPIDE, "", mdb.HASH, m.OptionSimple(CLIENT_NAME))
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
SPIDE_DELETE: {Name: "DELETE url key value run", Help: "蜘蛛侠", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Echo(kit.Formats(kit.UnMarshal(m.Cmdx(SPIDE, ice.DEV, SPIDE_RAW, SPIDE_DELETE, arg[0], arg[1:]))))
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -11,6 +11,8 @@ import (
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
"shylinux.com/x/icebergs/base/tcp"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
"shylinux.com/x/toolkits/logs"
|
||||
"shylinux.com/x/toolkits/task"
|
||||
)
|
||||
|
||||
type Frame struct {
|
||||
@ -20,21 +22,37 @@ type Frame struct {
|
||||
*http.ServeMux
|
||||
|
||||
send map[string]*ice.Message
|
||||
lock task.Lock
|
||||
}
|
||||
|
||||
func (web *Frame) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if _serve_main(web.Message, w, r) {
|
||||
web.ServeMux.ServeHTTP(w, r)
|
||||
func (frame *Frame) getSend(key string) (*ice.Message, bool) {
|
||||
defer frame.lock.RLock()()
|
||||
msg, ok := frame.send[key]
|
||||
return msg, ok
|
||||
}
|
||||
func (frame *Frame) addSend(key string, msg *ice.Message) string {
|
||||
defer frame.lock.Lock()()
|
||||
frame.send[key] = msg
|
||||
return key
|
||||
}
|
||||
func (frame *Frame) delSend(key string) {
|
||||
defer frame.lock.Lock()()
|
||||
delete(frame.send, key)
|
||||
}
|
||||
|
||||
func (frame *Frame) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if _serve_main(frame.Message, w, r) {
|
||||
frame.ServeMux.ServeHTTP(w, r)
|
||||
}
|
||||
}
|
||||
func (web *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server {
|
||||
func (frame *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server {
|
||||
return &Frame{}
|
||||
}
|
||||
func (web *Frame) Begin(m *ice.Message, arg ...string) ice.Server {
|
||||
web.send = map[string]*ice.Message{}
|
||||
return web
|
||||
func (frame *Frame) Begin(m *ice.Message, arg ...string) ice.Server {
|
||||
frame.send = map[string]*ice.Message{}
|
||||
return frame
|
||||
}
|
||||
func (web *Frame) Start(m *ice.Message, arg ...string) bool {
|
||||
func (frame *Frame) Start(m *ice.Message, arg ...string) bool {
|
||||
list := map[*ice.Context]string{}
|
||||
m.Travel(func(p *ice.Context, s *ice.Context) {
|
||||
if frame, ok := s.Server().(*Frame); ok {
|
||||
@ -42,19 +60,20 @@ func (web *Frame) Start(m *ice.Message, arg ...string) bool {
|
||||
return
|
||||
}
|
||||
frame.ServeMux = http.NewServeMux()
|
||||
meta := logs.FileLineMeta("")
|
||||
|
||||
// 级联路由
|
||||
msg := m.Spawn(s)
|
||||
if pframe, ok := p.Server().(*Frame); ok && pframe.ServeMux != nil {
|
||||
route := ice.PS + s.Name + ice.PS
|
||||
msg.Log(ROUTE, "%s <= %s", p.Name, route)
|
||||
msg.Log(ROUTE, "%s <= %s", p.Name, route, meta)
|
||||
pframe.Handle(route, http.StripPrefix(path.Dir(route), frame))
|
||||
list[s] = path.Join(list[p], route)
|
||||
}
|
||||
|
||||
// 静态路由
|
||||
m.Confm(SERVE, kit.Keym(nfs.PATH), func(key string, value string) {
|
||||
m.Log(ROUTE, "%s <- %s <- %s", s.Name, key, value)
|
||||
m.Log(ROUTE, "%s <- %s <- %s", s.Name, key, value, meta)
|
||||
frame.Handle(key, http.StripPrefix(key, http.FileServer(http.Dir(value))))
|
||||
})
|
||||
|
||||
@ -63,7 +82,7 @@ func (web *Frame) Start(m *ice.Message, arg ...string) bool {
|
||||
if s != sub || k[0] != '/' {
|
||||
return
|
||||
}
|
||||
msg.Log(ROUTE, "%s <- %s", s.Name, k)
|
||||
msg.Log(ROUTE, "%s <- %s", s.Name, k, meta)
|
||||
ice.Info.Route[path.Join(list[s], k)] = ice.FileCmd(kit.FileLine(x.Hand, 300))
|
||||
frame.HandleFunc(k, func(frame http.ResponseWriter, r *http.Request) {
|
||||
m.TryCatch(msg.Spawn(), true, func(msg *ice.Message) {
|
||||
@ -77,24 +96,25 @@ func (web *Frame) Start(m *ice.Message, arg ...string) bool {
|
||||
m.Event(SERVE_START)
|
||||
defer m.Event(SERVE_STOP)
|
||||
|
||||
web.Message, web.Server = m, &http.Server{Handler: web}
|
||||
frame.Message, frame.Server = m, &http.Server{Handler: frame}
|
||||
switch cb := m.OptionCB(SERVE).(type) {
|
||||
case func(http.Handler):
|
||||
cb(web) // 启动框架
|
||||
cb(frame) // 启动框架
|
||||
default:
|
||||
m.Cmd(tcp.SERVER, tcp.LISTEN, mdb.TYPE, WEB, m.OptionSimple(mdb.NAME, tcp.HOST, tcp.PORT), func(l net.Listener) {
|
||||
m.Cmdy(mdb.INSERT, SERVE, "", mdb.HASH, mdb.NAME, WEB, arg, m.OptionSimple(tcp.PROTO, ice.DEV), cli.STATUS, tcp.START)
|
||||
m.Cmd(mdb.INSERT, SERVE, "", mdb.HASH, mdb.NAME, WEB, arg, m.OptionSimple(tcp.PROTO, ice.DEV), cli.STATUS, tcp.START, kit.Dict(mdb.TARGET, l))
|
||||
defer m.Cmd(mdb.MODIFY, SERVE, "", mdb.HASH, m.OptionSimple(mdb.NAME), cli.STATUS, tcp.STOP)
|
||||
m.Warn(web.Server.Serve(l)) // 启动服务
|
||||
m.Warn(frame.Server.Serve(l)) // 启动服务
|
||||
})
|
||||
}
|
||||
return true
|
||||
}
|
||||
func (web *Frame) Close(m *ice.Message, arg ...string) bool {
|
||||
return m.Done(true)
|
||||
func (frame *Frame) Close(m *ice.Message, arg ...string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func P(arg ...string) string { return path.Join(ice.PS, path.Join(arg...)) }
|
||||
func P(arg ...string) string { return path.Join(ice.PS, path.Join(arg...)) }
|
||||
func PP(arg ...string) string { return path.Join(ice.PS, path.Join(arg...)) + ice.PS }
|
||||
|
||||
const (
|
||||
SERVE_START = "serve.start"
|
||||
@ -106,8 +126,7 @@ var Index = &ice.Context{Name: WEB, Help: "网络模块"}
|
||||
|
||||
func init() {
|
||||
ice.Index.Register(Index, &Frame{},
|
||||
SERVE, SPACE, DREAM, ROUTE,
|
||||
SHARE, SPIDE, CACHE, STORY,
|
||||
BROAD,
|
||||
BROAD, SERVE, SPACE, DREAM,
|
||||
SHARE, CACHE, SPIDE, ROUTE,
|
||||
)
|
||||
}
|
||||
|
@ -359,7 +359,7 @@ func init() {
|
||||
case func(string, *Matrix):
|
||||
cb(h, mat)
|
||||
default:
|
||||
m.Error(true, ice.ErrNotImplement)
|
||||
m.ErrorNotImplement(cb)
|
||||
}
|
||||
m.Echo(h)
|
||||
}},
|
||||
@ -400,7 +400,7 @@ func init() {
|
||||
case func(string, int, []string, int, *lex.Stream) (int, []string):
|
||||
return cb(nhash, hash, word, begin, stream)
|
||||
default:
|
||||
m.Error(true, ice.ErrNotImplement)
|
||||
m.ErrorNotImplement(cb)
|
||||
}
|
||||
return hash, word
|
||||
}, mat.index(m, NPAGE, m.Option(NPAGE)), stream, 1)
|
||||
|
@ -95,7 +95,7 @@ func _exp_true(m *ice.Message, arg string) bool {
|
||||
const SCRIPT = "script"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
SCRIPT: {Name: "script name npage text auto create", Help: "脚本解析", Actions: ice.Actions{
|
||||
mdb.CREATE: {Name: "create name=shy text=etc/yac.txt", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmd(MATRIX, mdb.CREATE, m.Option(mdb.NAME))
|
||||
@ -214,5 +214,5 @@ func init() {
|
||||
})
|
||||
m.Resultv(stack.res)
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
57
conf.go
57
conf.go
@ -17,7 +17,6 @@ const (
|
||||
SUCCESS = "success"
|
||||
FAILURE = "failure"
|
||||
PROCESS = "process"
|
||||
RESTART = "restart"
|
||||
OF = " of "
|
||||
|
||||
INIT = "init"
|
||||
@ -107,14 +106,18 @@ const ( // DIR
|
||||
PLUGIN_INPUT = "/plugin/input"
|
||||
PLUGIN_STORY = "/plugin/story"
|
||||
PLUGIN_LOCAL = "/plugin/local"
|
||||
NODE_MODULES = "node_modules"
|
||||
ISH_PLUGED = ".ish/pluged"
|
||||
|
||||
FAVICON = "favicon.ico"
|
||||
PROTO_JS = "proto.js"
|
||||
FRAME_JS = "frame.js"
|
||||
INDEX_JS = "index.js"
|
||||
ORDER_JS = "order.js"
|
||||
ORDER_SH = "order.sh"
|
||||
INDEX_SH = "index.sh"
|
||||
FAVICON = "favicon.ico"
|
||||
PROTO_JS = "proto.js"
|
||||
FRAME_JS = "frame.js"
|
||||
INDEX_JS = "index.js"
|
||||
ORDER_JS = "order.js"
|
||||
ORDER_SH = "order.sh"
|
||||
INDEX_SH = "index.sh"
|
||||
INDEX_IML = "index.iml"
|
||||
TUTOR_SHY = "tutor.shy"
|
||||
|
||||
USR_LOCAL = "usr/local"
|
||||
USR_LOCAL_GO = "usr/local/go"
|
||||
@ -159,6 +162,8 @@ const ( // DIR
|
||||
ICE_BIN = "ice.bin"
|
||||
GO_SUM = "go.sum"
|
||||
GO_MOD = "go.mod"
|
||||
|
||||
CTX_DAEMON = "ctx_daemon"
|
||||
)
|
||||
const ( // MSG
|
||||
MSG_DETAIL = "detail"
|
||||
@ -206,23 +211,26 @@ const ( // MSG
|
||||
MSG_STORM = "sess.storm"
|
||||
MSG_TOAST = "sess.toast"
|
||||
MSG_LOCAL = "sess.local"
|
||||
|
||||
MSG_FILES = "file.system"
|
||||
)
|
||||
const ( // RENDER
|
||||
RENDER_RAW = "_raw"
|
||||
RENDER_VOID = "_void"
|
||||
RENDER_JSON = "_json"
|
||||
RENDER_STATUS = "_status"
|
||||
RENDER_RESULT = "_result"
|
||||
RENDER_ANCHOR = "_anchor"
|
||||
RENDER_BUTTON = "_button"
|
||||
RENDER_SCRIPT = "_script"
|
||||
RENDER_QRCODE = "_qrcode"
|
||||
RENDER_IMAGES = "_images"
|
||||
RENDER_VIDEOS = "_videos"
|
||||
RENDER_IFRAME = "_iframe"
|
||||
RENDER_TEMPLATE = "_template"
|
||||
RENDER_REDIRECT = "_redirect"
|
||||
RENDER_DOWNLOAD = "_download"
|
||||
RENDER_TEMPLATE = "_template"
|
||||
RENDER_RESULT = "_result"
|
||||
RENDER_JSON = "_json"
|
||||
RENDER_VOID = "_void"
|
||||
RENDER_RAW = "_raw"
|
||||
|
||||
RENDER_ANCHOR = "_anchor"
|
||||
RENDER_BUTTON = "_button"
|
||||
RENDER_SCRIPT = "_script"
|
||||
RENDER_QRCODE = "_qrcode"
|
||||
RENDER_IMAGES = "_images"
|
||||
RENDER_VIDEOS = "_videos"
|
||||
RENDER_IFRAME = "_iframe"
|
||||
)
|
||||
const ( // PROCESS
|
||||
PROCESS_LOCATION = "_location"
|
||||
@ -369,4 +377,13 @@ const ( // gdb
|
||||
LISTEN = "listen"
|
||||
HAPPEN = "happen"
|
||||
FILELINE = "fileline"
|
||||
|
||||
RESTART = "restart"
|
||||
ERROR = "error"
|
||||
OPEN = "open"
|
||||
CLOSE = "close"
|
||||
START = "start"
|
||||
STOP = "stop"
|
||||
BEGIN = "begin"
|
||||
END = "end"
|
||||
)
|
||||
|
@ -146,7 +146,7 @@ const (
|
||||
const ACTION = "action"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
web.P(ACTION): {Name: "/action river storm action arg...", Help: "工作台", Actions: ice.MergeAction(ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
for _, cmd := range []string{
|
||||
@ -193,5 +193,5 @@ func init() {
|
||||
// 执行命令
|
||||
_action_exec(m, arg[0], arg[1], arg[2], arg[3:]...)
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -51,9 +51,40 @@ func _cmd_file(m *ice.Message, arg ...string) bool {
|
||||
const CMD = "cmd"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
CMD: {Name: CMD, Help: "命令", Value: kit.Data(mdb.SHORT, "type", nfs.PATH, nfs.PWD)},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
CMD: {Name: "cmd path auto upload up home", Help: "命令", Actions: ice.MergeAction(ice.Actions{
|
||||
web.UPLOAD: {Name: "upload", Help: "上传", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Upload(path.Join(m.Config(nfs.PATH), strings.TrimPrefix(path.Dir(m.R.URL.Path), "/cmd")))
|
||||
}},
|
||||
|
||||
"home": {Name: "home", Help: "根目录", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.ProcessLocation("/chat/cmd/")
|
||||
}},
|
||||
"up": {Name: "up", Help: "上一级", Hand: func(m *ice.Message, arg ...string) {
|
||||
if strings.TrimPrefix(m.R.URL.Path, "/cmd") == ice.PS {
|
||||
m.Cmdy(CMD)
|
||||
} else if strings.HasSuffix(m.R.URL.Path, ice.PS) {
|
||||
m.ProcessLocation("../")
|
||||
} else {
|
||||
m.ProcessLocation(nfs.PWD)
|
||||
}
|
||||
}},
|
||||
}, mdb.HashAction(mdb.SHORT, "type", nfs.PATH, nfs.PWD)), Hand: func(m *ice.Message, arg ...string) {
|
||||
if _cmd_file(m, arg...) {
|
||||
return
|
||||
}
|
||||
if msg := m.Cmd(ctx.COMMAND, arg[0]); msg.Length() > 0 {
|
||||
m.RenderCmd(arg[0])
|
||||
return
|
||||
}
|
||||
|
||||
if len(arg) > 0 {
|
||||
m.ProcessLocation(arg[0])
|
||||
return
|
||||
}
|
||||
m.Option(nfs.DIR_ROOT, path.Join(m.Config(nfs.PATH), strings.TrimPrefix(path.Dir(m.R.URL.Path), "/cmd")))
|
||||
m.Cmdy(nfs.DIR, arg)
|
||||
}},
|
||||
"/cmd/": {Name: "/cmd/", Help: "命令", Actions: ice.MergeAction(ice.Actions{
|
||||
ice.CTX_INIT: {Name: "_init", Help: "初始化", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(CMD, mdb.CREATE, mdb.TYPE, "shy", mdb.NAME, "web.wiki.word")
|
||||
@ -84,38 +115,5 @@ func init() {
|
||||
m.RenderDownload(path.Join(m.Config(nfs.PATH), path.Join(arg...))) // 文件
|
||||
}
|
||||
}},
|
||||
CMD: {Name: "cmd path auto upload up home", Help: "命令", Actions: ice.MergeAction(ice.Actions{
|
||||
web.UPLOAD: {Name: "upload", Help: "上传", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Upload(path.Join(m.Config(nfs.PATH), strings.TrimPrefix(path.Dir(m.R.URL.Path), "/cmd")))
|
||||
}},
|
||||
|
||||
"home": {Name: "home", Help: "根目录", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.ProcessLocation("/chat/cmd/")
|
||||
}},
|
||||
"up": {Name: "up", Help: "上一级", Hand: func(m *ice.Message, arg ...string) {
|
||||
if strings.TrimPrefix(m.R.URL.Path, "/cmd") == ice.PS {
|
||||
m.Cmdy(CMD)
|
||||
} else if strings.HasSuffix(m.R.URL.Path, ice.PS) {
|
||||
m.ProcessLocation("../")
|
||||
} else {
|
||||
m.ProcessLocation(nfs.PWD)
|
||||
}
|
||||
}},
|
||||
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
if _cmd_file(m, arg...) {
|
||||
return
|
||||
}
|
||||
if msg := m.Cmd(ctx.COMMAND, arg[0]); msg.Length() > 0 {
|
||||
m.RenderCmd(arg[0])
|
||||
return
|
||||
}
|
||||
|
||||
if len(arg) > 0 {
|
||||
m.ProcessLocation(arg[0])
|
||||
return
|
||||
}
|
||||
m.Option(nfs.DIR_ROOT, path.Join(m.Config(nfs.PATH), strings.TrimPrefix(path.Dir(m.R.URL.Path), "/cmd")))
|
||||
m.Cmdy(nfs.DIR, arg)
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -11,11 +11,7 @@ import (
|
||||
const FILES = "files"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
FILES: {Name: FILES, Help: "文件夹", Value: kit.Data(
|
||||
mdb.SHORT, mdb.DATA, mdb.FIELD, "time,hash,type,name,size,data",
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
FILES: {Name: "files hash auto upload", Help: "文件夹", Actions: ice.MergeAction(ice.Actions{
|
||||
web.UPLOAD: {Name: "upload", Help: "上传", Hand: func(m *ice.Message, arg ...string) {
|
||||
up := kit.Simple(m.Optionv(ice.MSG_UPLOAD))
|
||||
@ -25,7 +21,7 @@ func init() {
|
||||
}
|
||||
m.Cmdy(mdb.INSERT, m.PrefixKey(), "", mdb.HASH, mdb.TYPE, kit.Ext(up[1]), mdb.NAME, up[1], nfs.SIZE, up[2], mdb.DATA, up[0])
|
||||
}},
|
||||
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
}, mdb.HashAction(mdb.SHORT, mdb.DATA, mdb.FIELD, "time,hash,type,name,size,data")), Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.HashSelect(m, arg...)
|
||||
m.Tables(func(value ice.Maps) {
|
||||
link := web.SHARE_CACHE + value[mdb.DATA]
|
||||
@ -34,5 +30,5 @@ func init() {
|
||||
}
|
||||
})
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
const GRANT = "grant"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
GRANT: {Name: "grant space id auto insert", Help: "授权", Actions: ice.MergeAction(ice.Actions{
|
||||
mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
|
||||
switch arg[0] {
|
||||
@ -26,5 +26,5 @@ func init() {
|
||||
}},
|
||||
mdb.INSERT: {Name: "insert space grant userrole username", Help: "添加"},
|
||||
}, mdb.ZoneAction(mdb.SHORT, web.SPACE, mdb.FIELD, "time,grant,userrole,username"))},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
const INFO = "info"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
INFO: {Name: "info auto", Help: "信息", Actions: ice.Actions{
|
||||
mdb.MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(mdb.MODIFY, RIVER, "", mdb.HASH, mdb.HASH, m.Option(ice.MSG_RIVER), arg)
|
||||
@ -17,5 +17,5 @@ func init() {
|
||||
m.OptionFields(mdb.DETAIL)
|
||||
m.Cmdy(mdb.SELECT, RIVER, "", mdb.HASH, mdb.HASH, m.Option(ice.MSG_RIVER))
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -42,6 +42,9 @@ func init() {
|
||||
m.Echo(get(m, "place/v1/explore", m.OptionSimple("boundary,page_index")))
|
||||
}},
|
||||
"search": {Name: "search", Help: "搜索", Hand: func(m *ice.Message, arg ...string) {
|
||||
if arg[0] == "*" {
|
||||
return
|
||||
}
|
||||
m.Echo(get(m, "place/v1/search", m.OptionSimple("keyword,boundary,page_index")))
|
||||
}},
|
||||
"direction": {Name: "direction", Help: "导航", Hand: func(m *ice.Message, arg ...string) {
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
const NODE = "node"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
NODE: {Name: "node pod ctx cmd auto insert invite", Help: "设备", Actions: ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Watch(web.DREAM_START, m.PrefixKey())
|
||||
@ -60,5 +60,5 @@ func init() {
|
||||
}
|
||||
m.Cmdy(web.ROUTE, arg)
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
const OCEAN = "ocean"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
OCEAN: {Name: "ocean username auto insert invite", Help: "用户", Actions: ice.Actions{
|
||||
mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(aaa.USER, ice.OptionFields(aaa.USERNAME, aaa.USERNICK, aaa.USERZONE))
|
||||
@ -31,5 +31,5 @@ func init() {
|
||||
})
|
||||
m.PushAction(mdb.DELETE)
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -5,27 +5,22 @@ import (
|
||||
"shylinux.com/x/icebergs/base/cli"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
"shylinux.com/x/icebergs/base/ssh"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
const PASTE = "paste"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
PASTE: {Name: PASTE, Help: "粘贴", Value: kit.Data(
|
||||
mdb.SHORT, mdb.TEXT, mdb.FIELD, "time,hash,type,name,text",
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
PASTE: {Name: "paste hash auto getClipboardData", Help: "粘贴", Actions: ice.MergeAction(ice.Actions{
|
||||
"getClipboardData": {Name: "getClipboardData", Help: "粘贴", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(PASTE, mdb.CREATE, arg)
|
||||
}},
|
||||
mdb.CREATE: {Name: "create type=text name=hi text:textarea=hi", Help: "添加"},
|
||||
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
}, mdb.HashAction(mdb.SHORT, mdb.TEXT, mdb.FIELD, "time,hash,type,name,text")), Hand: func(m *ice.Message, arg ...string) {
|
||||
if mdb.HashSelect(m, arg...); len(arg) > 0 {
|
||||
m.PushScript(ssh.SCRIPT, m.Append(mdb.TEXT))
|
||||
m.PushQRCode(cli.QRCODE, m.Append(mdb.TEXT))
|
||||
}
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -16,13 +16,8 @@ import (
|
||||
const POD = "pod"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
POD: {Name: POD, Help: "节点", Value: kit.Data()},
|
||||
}, Commands: ice.Commands{
|
||||
"/pod/": {Name: "/pod/", Help: "节点", Actions: ice.MergeAction(ice.Actions{
|
||||
ice.CTX_INIT: {Name: "_init", Help: "初始化", Hand: func(m *ice.Message, arg ...string) {
|
||||
}},
|
||||
}, ctx.CmdAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
Index.MergeCommands(ice.Commands{
|
||||
"/pod/": {Name: "/pod/", Help: "节点", Actions: ctx.CmdAction(), Hand: func(m *ice.Message, arg ...string) {
|
||||
if strings.HasPrefix(m.R.Header.Get("User-Agent"), "curl") || strings.HasPrefix(m.R.Header.Get("User-Agent"), "Wget") {
|
||||
m.Option(ice.MSG_USERNAME, "root")
|
||||
m.Option(ice.MSG_USERROLE, "root")
|
||||
@ -53,5 +48,5 @@ func init() {
|
||||
// m.Cmdy(web.SPACE, m.Option(ice.MSG_USERPOD), "web.chat."+ice.PS+path.Join(arg[1:]...))
|
||||
}
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ func _river_list(m *ice.Message) {
|
||||
const RIVER = "river"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
RIVER: {Name: "river hash auto create", Help: "群组", Actions: ice.MergeAction(ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { m.Config(nfs.TEMPLATE, _river_template) }},
|
||||
mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
|
||||
@ -134,7 +134,7 @@ func init() {
|
||||
m.Cmdy(RIVER, arg)
|
||||
}
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
||||
var _river_template = kit.Dict(
|
||||
|
@ -2,7 +2,6 @@ package chat
|
||||
|
||||
import (
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/aaa"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
"shylinux.com/x/icebergs/base/web"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
@ -63,15 +62,15 @@ func init() {
|
||||
m.Cmdy(mdb.INSERT, m.Prefix(ROOM), "", mdb.HASH, m.OptionSimple(mdb.ZONE))
|
||||
m.Cmdy(mdb.INSERT, m.Prefix(JOIN), "", mdb.HASH, m.OptionSimple(mdb.ZONE))
|
||||
}},
|
||||
mdb.INSERT: {Name: "insert zone username daemon", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Conf(m.Prefix(JOIN), kit.Keys(kit.KeyHash(m.Option(mdb.ZONE)), kit.Keym(mdb.SHORT)), web.SOCKET)
|
||||
m.Cmdy(mdb.INSERT, m.Prefix(JOIN), kit.KeyHash(m.Option(mdb.ZONE)), mdb.HASH,
|
||||
aaa.USERNAME, m.Option(ice.MSG_USERNAME), web.SOCKET, m.Option(ice.MSG_DAEMON),
|
||||
)
|
||||
}},
|
||||
mdb.DELETE: {Name: "delete zone socket", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(mdb.DELETE, m.Prefix(JOIN), kit.KeyHash(m.Option(mdb.ZONE)), mdb.HASH, m.OptionSimple(web.SOCKET))
|
||||
}},
|
||||
// mdb.INSERT: {Name: "insert zone username daemon", Hand: func(m *ice.Message, arg ...string) {
|
||||
// m.Conf(m.Prefix(JOIN), kit.Keys(kit.KeyHash(m.Option(mdb.ZONE)), kit.Keym(mdb.SHORT)), web.SOCKET)
|
||||
// m.Cmdy(mdb.INSERT, m.Prefix(JOIN), kit.KeyHash(m.Option(mdb.ZONE)), mdb.HASH,
|
||||
// aaa.USERNAME, m.Option(ice.MSG_USERNAME), web.SOCKET, m.Option(ice.MSG_DAEMON),
|
||||
// )
|
||||
// }},
|
||||
// mdb.DELETE: {Name: "delete zone socket", Hand: func(m *ice.Message, arg ...string) {
|
||||
// m.Cmdy(mdb.DELETE, m.Prefix(JOIN), kit.KeyHash(m.Option(mdb.ZONE)), mdb.HASH, m.OptionSimple(web.SOCKET))
|
||||
// }},
|
||||
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Fields(len(arg), "time,space", "time,zone")
|
||||
if len(arg) == 0 {
|
||||
|
@ -11,18 +11,14 @@ import (
|
||||
const SCAN = "scan"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
SCAN: {Name: SCAN, Help: "扫码", Value: kit.Data(
|
||||
mdb.SHORT, mdb.TEXT, mdb.FIELD, "time,hash,type,name,text",
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
SCAN: {Name: "scan hash auto scanQRCode scanQRCode0", Help: "扫码", Meta: kit.Dict(
|
||||
ice.Display("scan.js"),
|
||||
), Actions: ice.MergeAction(ice.Actions{
|
||||
"scanQRCode0": {Name: "scan create", Help: "本机扫码"},
|
||||
"scanQRCode": {Name: "scan create", Help: "扫码"},
|
||||
mdb.CREATE: {Name: "create type=text name=hi text:textarea=hi", Help: "添加"},
|
||||
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
}, mdb.HashAction(mdb.SHORT, mdb.TEXT, mdb.FIELD, "time,hash,type,name,text")), Hand: func(m *ice.Message, arg ...string) {
|
||||
if mdb.HashSelect(m, arg...); len(arg) > 0 {
|
||||
if m.Append(mdb.TYPE) == "image" {
|
||||
m.PushImages("image", m.Append(mdb.TEXT))
|
||||
@ -31,5 +27,5 @@ func init() {
|
||||
m.PushQRCode(cli.QRCODE, m.Append(mdb.TEXT))
|
||||
}
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -10,9 +10,9 @@ import (
|
||||
const SEARCH = "search"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
web.P(SEARCH): {Name: "/search", Help: "搜索引擎", Actions: ctx.CmdAction(mdb.SHORT, mdb.NAME), Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(m.Space(m.Option(ice.POD)), mdb.SEARCH, arg).StatusTimeCount()
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -12,16 +12,15 @@ import (
|
||||
const SSO = "sso"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
"/sso": {Name: "/sso", Help: "登录", Hand: func(m *ice.Message, arg ...string) {
|
||||
if m.Option(ice.MSG_USERNAME) == "" {
|
||||
m.RenderIndex(web.SERVE, ice.VOLCANOS)
|
||||
return
|
||||
}
|
||||
sessid := m.Cmdx(web.SPACE, m.Option(web.SPACE), aaa.SESS, mdb.CREATE,
|
||||
mdb.TIME, m.Time("720h"),
|
||||
aaa.USERROLE, m.Option(ice.MSG_USERROLE),
|
||||
aaa.USERNAME, m.Option(ice.MSG_USERNAME),
|
||||
aaa.USERROLE, m.Option(ice.MSG_USERROLE),
|
||||
aaa.USERNICK, m.Option(ice.MSG_USERNICK),
|
||||
)
|
||||
m.RenderRedirect(kit.MergeURL(m.Option(cli.BACK), ice.MSG_SESSID, sessid))
|
||||
@ -31,5 +30,5 @@ func init() {
|
||||
// web.RenderCookie(m, sessid, web.CookieName(m.Option("back")))
|
||||
// m.RenderRedirect(kit.MergeURL(m.Option("back")))
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ func _storm_key(m *ice.Message, key ...ice.Any) string {
|
||||
const STORM = "storm"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
STORM: {Name: "storm hash id auto insert create", Help: "应用", Actions: ice.Actions{
|
||||
mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
|
||||
if ctx.Inputs(m, arg[0]) {
|
||||
@ -88,5 +88,5 @@ func init() {
|
||||
m.PushAction(mdb.EXPORT, mdb.IMPORT)
|
||||
}
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ func init() {
|
||||
mdb.TYPE: "text", mdb.NAME: "height", mdb.VALUE: "31",
|
||||
},
|
||||
}
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
TOPIC: {Name: "topic zone id auto create insert", Help: "主题", Actions: ice.MergeAction(ice.Actions{
|
||||
mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
|
||||
switch arg[0] {
|
||||
@ -145,5 +145,5 @@ body.{{.Option "topic"}} fieldset.panel.Header>div.output div:hover { background
|
||||
m.W.Header()[web.ContentType] = kit.Simple(web.ContentCSS)
|
||||
m.RenderResult()
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ const (
|
||||
)
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
TRANS: {Name: "trans from to auto", Help: "传输", Actions: ice.MergeAction(ice.Actions{
|
||||
SEND: {Name: "send", Help: "发送", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(web.SPACE, m.Option(TO), web.SPIDE, ice.DEV, web.SPIDE_SAVE, kit.Select(nfs.PWD, m.Option("to_path")),
|
||||
@ -50,5 +50,5 @@ func init() {
|
||||
}
|
||||
m.DisplayLocal("")
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ func init() {
|
||||
const AUTOGEN = "autogen"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
AUTOGEN: {Name: "autogen path auto create binpack script relay", Help: "生成", Actions: ice.Actions{
|
||||
mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
|
||||
switch arg[0] {
|
||||
@ -187,6 +187,7 @@ func init() {
|
||||
_defs(m, mdb.KEY, kit.Keys("web.code", m.Option(mdb.ZONE), m.Option(mdb.NAME)))
|
||||
m.Option(mdb.TEXT, kit.Format("`name:\"%s\" help:\"%s\"`", _defs_list(m), m.Option(mdb.HELP)))
|
||||
|
||||
m.OptionFiles(nfs.DiskFile)
|
||||
if p := path.Join(ice.SRC, m.Option(mdb.ZONE), kit.Keys(m.Option(mdb.NAME), GO)); !kit.FileExists(p) {
|
||||
_autogen_module(m, p)
|
||||
_autogen_import(m, path.Join(ice.SRC, m.Option(cli.MAIN)), m.Option(mdb.ZONE), _autogen_mod(m, ice.GO_MOD))
|
||||
@ -228,5 +229,5 @@ func init() {
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(nfs.CAT, kit.Select("version.go", arg, 0), kit.Dict(nfs.DIR_ROOT, ice.SRC))
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -37,12 +37,12 @@ func _bench_http(m *ice.Message, target string, arg ...string) {
|
||||
}
|
||||
}
|
||||
|
||||
var body int64
|
||||
var ndata int64
|
||||
if s, e := bench.HTTP(nconn, nreqs, list, func(req *http.Request, res *http.Response) {
|
||||
n, _ := io.Copy(ioutil.Discard, res.Body)
|
||||
atomic.AddInt64(&body, n)
|
||||
atomic.AddInt64(&ndata, n)
|
||||
}); m.Assert(e) {
|
||||
m.Echo("body: %s\n", kit.FmtSize(body))
|
||||
m.Echo("ndata: %s\n", kit.FmtSize(ndata))
|
||||
m.Echo(s.Show())
|
||||
m.ProcessInner()
|
||||
}
|
||||
@ -61,7 +61,7 @@ const (
|
||||
const BENCH = "bench"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
BENCH: {Name: "bench zone id auto insert", Help: "性能压测", Actions: ice.MergeAction(ice.Actions{
|
||||
mdb.INSERT: {Name: "insert zone=some type=http,redis name=demo text='http://localhost:9020' nconn=3 nreqs=10", Help: "添加"},
|
||||
ice.RUN: {Name: "run", Help: "执行", Hand: func(m *ice.Message, arg ...string) {
|
||||
@ -75,5 +75,5 @@ func init() {
|
||||
}, mdb.ZoneAction(mdb.SHORT, mdb.ZONE, mdb.FIELD, "time,id,type,name,text,nconn,nreqs")), Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.ZoneSelect(m, arg...).PushAction(kit.Select(mdb.REMOVE, ice.RUN, len(arg) > 0))
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -3,9 +3,7 @@ package code
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
@ -13,7 +11,6 @@ import (
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
"shylinux.com/x/icebergs/base/web"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
@ -51,11 +48,13 @@ func _binpack_can(m *ice.Message, f *os.File, dir string) {
|
||||
m.Option(nfs.DIR_TYPE, nfs.CAT)
|
||||
|
||||
for _, k := range []string{ice.FAVICON, ice.PROTO_JS, ice.FRAME_JS} {
|
||||
fmt.Fprintln(f, _binpack_file(m, path.Join(dir, k), ice.PS+k))
|
||||
// fmt.Fprintln(f, _binpack_file(m, path.Join(dir, k), ice.PS+k))
|
||||
fmt.Fprintln(f, _binpack_file(m, path.Join(dir, k), path.Join(ice.USR_VOLCANOS, k)))
|
||||
}
|
||||
for _, k := range []string{LIB, PAGE, PANEL, PLUGIN, "publish/client/nodejs/"} {
|
||||
m.Cmd(nfs.DIR, k).Sort(nfs.PATH).Tables(func(value ice.Maps) {
|
||||
fmt.Fprintln(f, _binpack_file(m, path.Join(dir, value[nfs.PATH]), ice.PS+value[nfs.PATH]))
|
||||
// fmt.Fprintln(f, _binpack_file(m, path.Join(dir, value[nfs.PATH]), ice.PS+value[nfs.PATH]))
|
||||
fmt.Fprintln(f, _binpack_file(m, path.Join(dir, value[nfs.PATH]), path.Join(ice.USR_VOLCANOS, value[nfs.PATH])))
|
||||
})
|
||||
}
|
||||
fmt.Fprintln(f)
|
||||
@ -67,50 +66,13 @@ func _binpack_ctx(m *ice.Message, f *os.File) {
|
||||
const BINPACK = "binpack"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
BINPACK: {Name: "binpack path auto create remove export", Help: "打包", Actions: ice.MergeAction(ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
if kit.FileExists(path.Join(ice.USR_VOLCANOS, ice.PROTO_JS)) {
|
||||
m.Cmd(BINPACK, mdb.REMOVE)
|
||||
return
|
||||
}
|
||||
|
||||
ice.Info.Dump = func(w io.Writer, name string, cb func(string)) bool {
|
||||
if strings.HasPrefix(name, ice.SRC) && kit.FileExists(name) {
|
||||
return false
|
||||
}
|
||||
for _, key := range []string{name, strings.TrimPrefix(name, ice.USR_VOLCANOS)} {
|
||||
if b, ok := ice.Info.Pack[key]; ok {
|
||||
if cb != nil {
|
||||
cb(name)
|
||||
}
|
||||
w.Write(b)
|
||||
return true // 读取数据
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
web.AddRewrite(func(w http.ResponseWriter, r *http.Request) bool {
|
||||
if ice.Info.Dump(w, r.URL.Path, func(name string) { web.RenderType(w, name, "") }) {
|
||||
return true // 输出数据
|
||||
}
|
||||
return false
|
||||
})
|
||||
nfs.AddRewrite(func(msg *ice.Message, name string) []byte {
|
||||
if kit.FileExists(name) {
|
||||
return nil
|
||||
}
|
||||
if strings.HasPrefix(name, ice.SRC) && kit.FileExists(name) {
|
||||
return nil
|
||||
}
|
||||
for _, key := range []string{name, path.Join(m.Option(nfs.DIR_ROOT), name), path.Join(ice.PS, name), strings.TrimPrefix(name, ice.USR_VOLCANOS)} {
|
||||
if b, ok := ice.Info.Pack[key]; ok && len(b) > 0 {
|
||||
m.Logs(BINPACK, len(b), key)
|
||||
return b // 读取数据
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}},
|
||||
mdb.CREATE: {Name: "create", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
|
||||
if f, p, e := kit.Create(ice.SRC_BINPACK_GO); m.Assert(e) {
|
||||
@ -122,6 +84,7 @@ func init() {
|
||||
import (
|
||||
"encoding/base64"
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -130,7 +93,9 @@ func init() {
|
||||
|
||||
defer fmt.Fprintln(f, `
|
||||
for k, v := range pack {
|
||||
ice.Info.Pack[k], _ = base64.StdEncoding.DecodeString(v)
|
||||
if b, e := base64.StdEncoding.DecodeString(v); e == nil {
|
||||
nfs.PackFile.WriteFile(k, b)
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
@ -188,5 +153,5 @@ func init() {
|
||||
}
|
||||
m.Echo(string(ice.Info.Pack[arg[0]]))
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ import (
|
||||
const CASE = "case"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
CASE: {Name: "case dev zone id auto", Help: "用例", Actions: ice.MergeAction(ice.Actions{
|
||||
mdb.CREATE: {Name: "create name address", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(web.SPIDE, mdb.CREATE, arg)
|
||||
@ -122,5 +122,5 @@ func init() {
|
||||
m.Option(cli.CMD_DIR, kit.Select(path.Dir(arg[0]), arg[0], strings.HasSuffix(arg[0], "/")))
|
||||
m.Cmdy(cli.SYSTEM, "go", "test", nfs.PWD, "-v", "-run="+arg[1])
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -3,20 +3,32 @@ package code
|
||||
import (
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
const FAVOR = "favor"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
FAVOR: {Name: "favor zone id auto insert", Help: "收藏夹", Actions: ice.MergeAction(ice.Actions{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
FAVOR: {Name: "favor zone id auto insert test page", Help: "收藏夹", Actions: ice.MergeAction(ice.Actions{
|
||||
mdb.INSERT: {Name: "insert zone=数据结构 type=go name=hi text=hello path file line", Help: "添加"},
|
||||
INNER: {Name: "inner", Help: "源码", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.ProcessCommand(INNER, m.OptionSplit("path,file,line"), arg...)
|
||||
}},
|
||||
"test": {Name: "test zone=hi count=10", Help: "测试", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmd(mdb.INSERT, m.PrefixKey(), "", mdb.HASH, m.OptionSimple(mdb.ZONE))
|
||||
for i := 0; i < kit.Int(m.Option(mdb.COUNT)); i++ {
|
||||
m.Cmd(mdb.INSERT, m.PrefixKey(), "", mdb.ZONE, m.Option(mdb.ZONE), mdb.NAME, i)
|
||||
}
|
||||
m.Conf(m.PrefixKey(), kit.Keys(mdb.HASH, kit.Hashs(m.Option(mdb.ZONE)), kit.Keym(mdb.LIMIT)), 20)
|
||||
m.Conf(m.PrefixKey(), kit.Keys(mdb.HASH, kit.Hashs(m.Option(mdb.ZONE)), kit.Keym(mdb.LEAST)), 10)
|
||||
m.Conf(m.PrefixKey(), kit.Keys(mdb.HASH, kit.Hashs(m.Option(mdb.ZONE)), kit.Keym(mdb.FSIZE)), 500)
|
||||
m.Cmdy(nfs.DIR, "var/data/", kit.Dict(nfs.DIR_DEEP, true))
|
||||
m.Echo(kit.Formats(m.Confv(m.PrefixKey())))
|
||||
}},
|
||||
}, mdb.ZoneAction(mdb.SHORT, mdb.ZONE, mdb.FIELD, "time,id,type,name,text,path,file,line")), Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.ZoneSelect(m, arg...).PushAction(kit.Select(mdb.REMOVE, INNER, len(arg) > 0))
|
||||
mdb.ZoneSelectPage(m, arg...).PushAction(kit.Select(mdb.REMOVE, INNER, len(arg) > 0))
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -7,11 +7,13 @@ import (
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/aaa"
|
||||
"shylinux.com/x/icebergs/base/cli"
|
||||
"shylinux.com/x/icebergs/base/gdb"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
"shylinux.com/x/icebergs/base/tcp"
|
||||
"shylinux.com/x/icebergs/base/web"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
"shylinux.com/x/toolkits/file"
|
||||
)
|
||||
|
||||
func _install_path(m *ice.Message, link string) string {
|
||||
@ -22,7 +24,7 @@ func _install_path(m *ice.Message, link string) string {
|
||||
if p := path.Join(ice.USR_INSTALL, path.Base(link)); kit.FileExists(p) {
|
||||
return path.Join(ice.USR_INSTALL, strings.Split(m.Cmdx(cli.SYSTEM, "sh", "-c", kit.Format("tar tf %s| head -n1", p), ice.Option{cli.CMD_OUTPUT, ""}), ice.PS)[0])
|
||||
}
|
||||
m.Error(true, ice.ErrNotFound)
|
||||
m.ErrorNotImplement(link)
|
||||
return ""
|
||||
}
|
||||
func _install_download(m *ice.Message) {
|
||||
@ -99,7 +101,7 @@ func _install_spawn(m *ice.Message, arg ...string) {
|
||||
|
||||
target := path.Join(ice.USR_LOCAL_DAEMON, m.Option(tcp.PORT))
|
||||
source := _install_path(m, "")
|
||||
nfs.MkdirAll(m, target)
|
||||
file.MkdirAll(target, ice.MOD_DIR)
|
||||
defer m.Echo(target)
|
||||
|
||||
if m.Option(INSTALL) == "" && kit.FileExists(kit.Path(source, "_install")) {
|
||||
@ -119,7 +121,7 @@ func _install_start(m *ice.Message, arg ...string) {
|
||||
case func(string):
|
||||
cb(p)
|
||||
default:
|
||||
m.Error(true, ice.ErrNotImplement)
|
||||
m.ErrorNotImplement(cb)
|
||||
}
|
||||
|
||||
if m.Cmdy(cli.DAEMON, arg[1:], args); cli.IsSuccess(m) {
|
||||
@ -132,7 +134,7 @@ func _install_stop(m *ice.Message, arg ...string) {
|
||||
m.Cmd(cli.DAEMON, cli.STOP, kit.Dict(mdb.HASH, value[mdb.HASH]))
|
||||
}
|
||||
})
|
||||
m.Cmd(cli.SYSTEM, cli.KILL, m.Option(cli.PID))
|
||||
m.Cmd(gdb.SIGNAL, gdb.KILL, m.Option(cli.PID))
|
||||
}
|
||||
func _install_service(m *ice.Message, arg ...string) {
|
||||
arg = kit.Split(path.Base(arg[0]), "-.")[:1]
|
||||
@ -152,11 +154,7 @@ const (
|
||||
const INSTALL = "install"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
INSTALL: {Name: INSTALL, Help: "安装", Value: kit.Data(
|
||||
mdb.SHORT, mdb.NAME, mdb.FIELD, "time,name,path,link", nfs.PATH, ice.USR_INSTALL,
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
INSTALL: {Name: "install name port path auto download", Help: "安装", Meta: kit.Dict(), Actions: ice.MergeAction(ice.Actions{
|
||||
web.DOWNLOAD: {Name: "download link path", Help: "下载", Hand: func(m *ice.Message, arg ...string) {
|
||||
_install_download(m)
|
||||
@ -188,7 +186,7 @@ func init() {
|
||||
cli.STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) {
|
||||
_install_stop(m, arg...)
|
||||
}},
|
||||
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
}, mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,name,path,link", nfs.PATH, ice.USR_INSTALL)), Hand: func(m *ice.Message, arg ...string) {
|
||||
switch len(arg) {
|
||||
case 0: // 源码列表
|
||||
mdb.HashSelect(m, arg...)
|
||||
@ -201,7 +199,7 @@ func init() {
|
||||
m.Cmdy(nfs.CAT, kit.Select(nfs.PWD, arg, 2))
|
||||
}
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
||||
func InstallAction(args ...ice.Any) ice.Actions {
|
||||
|
@ -22,9 +22,7 @@ func init() {
|
||||
LOGIN_OAUTH = "https://github.com/login/oauth/"
|
||||
API_GITHUB = "https://api.github.com/"
|
||||
)
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
OAUTH: {Name: OAUTH, Help: "授权", Value: kit.Data(mdb.FIELD, "time,hash,code,access_token,scope,token_type")},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
OAUTH: {Name: "oauth hash auto", Help: "授权", Actions: ice.MergeAction(ice.Actions{
|
||||
ctx.CONFIG: {Name: "config client_id client_secret redirect_uri", Help: "配置", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.ConfigOption(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI)
|
||||
@ -60,7 +58,7 @@ func init() {
|
||||
m.Option(web.SPIDE_HEADER, web.Accept, web.ContentJSON, web.Authorization, "token "+m.Append(ACCESS_TOKEN))
|
||||
m.Cmd(web.SPIDE_DELETE, API_GITHUB+"user/keys/"+m.Option(mdb.ID))
|
||||
}},
|
||||
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
}, mdb.HashAction(mdb.FIELD, "time,hash,code,access_token,scope,token_type")), Hand: func(m *ice.Message, arg ...string) {
|
||||
if mdb.HashSelect(m, arg...).PushAction("user", "public", ACCESS_TOKEN, mdb.REMOVE); len(arg) == 0 {
|
||||
m.Action(mdb.CREATE)
|
||||
m.Echo(kit.MergeURL2(LOGIN_OAUTH, "authorize", m.ConfigSimple(REDIRECT_URI, CLIENT_ID), SCOPE, "read:user read:public_key write:public_key repo"))
|
||||
@ -82,5 +80,5 @@ func init() {
|
||||
m.RenderCmd(m.PrefixKey(), m.Cmdx(m.PrefixKey(), mdb.CREATE, m.OptionSimple(CODE)))
|
||||
}
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -24,11 +24,7 @@ const (
|
||||
const PPROF = "pprof"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
PPROF: {Name: PPROF, Help: "性能分析", Value: kit.Data(
|
||||
mdb.SHORT, mdb.ZONE, mdb.FIELD, "time,id,text,file", PPROF, kit.List(GO, "tool", PPROF),
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
PPROF: {Name: "pprof zone id auto", Help: "性能分析", Actions: ice.MergeAction(ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
web.AddRewrite(func(w http.ResponseWriter, r *http.Request) bool {
|
||||
@ -65,9 +61,10 @@ func init() {
|
||||
m.Cmd(cli.DAEMON, m.Configv(PPROF), "-http="+p, m.Option(BINNARY), m.Option(nfs.FILE))
|
||||
m.Echo("http://%s/ui/top", p).ProcessInner()
|
||||
}},
|
||||
}, mdb.ZoneAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
}, mdb.ZoneAction(mdb.SHORT, mdb.ZONE, mdb.FIELD, "time,id,text,file", PPROF, kit.List(GO, "tool", PPROF))), Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Fields(len(arg), "time,zone,count,binnary,service,seconds", m.Config(mdb.FIELD))
|
||||
if mdb.ZoneSelect(m, arg...); len(arg) == 0 {
|
||||
m.EchoAnchor(m.MergeLink("/code/pprof/"))
|
||||
m.PushAction(ice.RUN, mdb.REMOVE)
|
||||
m.Action(mdb.CREATE)
|
||||
return
|
||||
@ -83,5 +80,5 @@ func init() {
|
||||
m.R.URL.Path = "/debug" + m.R.URL.Path
|
||||
http.DefaultServeMux.ServeHTTP(m.W, m.R)
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
const TEMPLATE = "template"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
TEMPLATE: {Name: "template name auto", Help: "模板", Actions: ice.MergeAction(ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
for _, _template := range _template_list {
|
||||
@ -40,7 +40,7 @@ func init() {
|
||||
m.Action(mdb.CREATE)
|
||||
}
|
||||
m.PushAction(nfs.DEFS, mdb.REMOVE)
|
||||
}}},
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -158,82 +158,78 @@ func _vimer_go_complete(m *ice.Message, name string, arg ...string) *ice.Message
|
||||
const VIMER = "vimer"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{
|
||||
Configs: ice.Configs{
|
||||
VIMER: {Name: VIMER, Help: "编辑器", Value: kit.Data()},
|
||||
},
|
||||
Commands: ice.Commands{
|
||||
VIMER: {Name: "vimer path=src/ file=main.go line=1 list", Help: "编辑器", Meta: kit.Dict(ice.DisplayLocal("", INNER)), Actions: ice.Actions{
|
||||
nfs.SAVE: {Name: "save type file path", Help: "保存", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Option(nfs.CONTENT, kit.Select(_vimer_defs(m, kit.Ext(m.Option(nfs.FILE))), m.Option(nfs.CONTENT)))
|
||||
m.Cmdy(nfs.SAVE, path.Join(m.Option(nfs.PATH), m.Option(nfs.FILE)))
|
||||
}},
|
||||
nfs.TRASH: {Name: "trash path", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(nfs.TRASH, arg[0])
|
||||
}},
|
||||
AUTOGEN: {Name: "create name=hi help=示例 type=Zone,Hash,Lists,Data,Code main=main.go zone key", Help: "模块", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(AUTOGEN, mdb.CREATE, arg)
|
||||
}},
|
||||
COMPILE: {Name: "compile", Help: "编译", Hand: func(m *ice.Message, arg ...string) {
|
||||
if msg := m.Cmd(COMPILE, ice.SRC_MAIN_GO, ice.BIN_ICE_BIN); cli.IsSuccess(msg) {
|
||||
m.Cmd(UPGRADE, cli.RESTART)
|
||||
} else {
|
||||
_inner_make(m, msg)
|
||||
}
|
||||
}},
|
||||
nfs.SCRIPT: {Name: "script file=hi/hi.js", Help: "脚本", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Option(mdb.TEXT, strings.TrimSpace(kit.Select(_vimer_defs(m, kit.Ext(m.Option(nfs.FILE))), m.Option(mdb.TEXT))))
|
||||
m.Cmdy(TEMPLATE, nfs.DEFS)
|
||||
}},
|
||||
nfs.WEBSITE: {Name: "website file=hi.zml", Help: "网页", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Option(mdb.TEXT, strings.TrimSpace(kit.Select(_vimer_defs(m, kit.Ext(m.Option(nfs.FILE))), m.Option(mdb.TEXT))))
|
||||
m.Option(nfs.FILE, path.Join(nfs.WEBSITE, m.Option(nfs.FILE)))
|
||||
m.Cmdy(TEMPLATE, nfs.DEFS)
|
||||
}},
|
||||
web.DREAM: {Name: "dream name=hi repos", Help: "空间", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(web.DREAM, cli.START, arg)
|
||||
}},
|
||||
PUBLISH: {Name: "publish", Help: "发布", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(PUBLISH, ice.CONTEXTS)
|
||||
}},
|
||||
|
||||
mdb.SEARCH: {Name: "search type name text", Help: "搜索", Hand: func(m *ice.Message, arg ...string) {
|
||||
if arg[0] == mdb.FOREACH && arg[1] == "" {
|
||||
m.PushSearch(mdb.TYPE, "go", mdb.NAME, "src/main.go", mdb.TEXT, m.MergeCmd(""))
|
||||
}
|
||||
}},
|
||||
mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
|
||||
_vimer_inputs(m, arg...)
|
||||
}},
|
||||
"complete": {Name: "complete", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
|
||||
_vimer_complete(m, arg...)
|
||||
}},
|
||||
"listTags": {Name: "listTags", Help: "索引", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy("web.code.vim.tags", "listTags", arg)
|
||||
}},
|
||||
|
||||
"unpack": {Name: "unpack", Help: "导出文件", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(BINPACK, mdb.EXPORT)
|
||||
}},
|
||||
DEVPACK: {Name: "devpack", Help: "开发模式", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmd(nfs.LINK, ice.GO_SUM, path.Join(ice.SRC_DEBUG, ice.GO_SUM))
|
||||
m.Cmd(nfs.LINK, ice.GO_MOD, path.Join(ice.SRC_DEBUG, ice.GO_MOD))
|
||||
m.Cmdy(nfs.CAT, ice.GO_MOD)
|
||||
m.Cmdy(WEBPACK, mdb.REMOVE)
|
||||
m.ProcessInner()
|
||||
m.ToastSuccess()
|
||||
}},
|
||||
BINPACK: {Name: "binpack", Help: "打包模式", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(WEBPACK, mdb.CREATE)
|
||||
m.Cmdy(AUTOGEN, BINPACK)
|
||||
m.ProcessInner()
|
||||
m.ToastSuccess()
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(INNER, arg)
|
||||
m.Option("plug", m.Config("show.plug"))
|
||||
m.Option("exts", m.Config("show.exts"))
|
||||
m.Option("tabs", m.Config("show.tabs"))
|
||||
Index.MergeCommands(ice.Commands{
|
||||
VIMER: {Name: "vimer path=src/ file=main.go line=1 list", Help: "编辑器", Meta: kit.Dict(ice.DisplayLocal("", INNER)), Actions: ice.Actions{
|
||||
nfs.SAVE: {Name: "save type file path", Help: "保存", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Option(nfs.CONTENT, kit.Select(_vimer_defs(m, kit.Ext(m.Option(nfs.FILE))), m.Option(nfs.CONTENT)))
|
||||
m.Cmdy(nfs.SAVE, path.Join(m.Option(nfs.PATH), m.Option(nfs.FILE)))
|
||||
}},
|
||||
}})
|
||||
nfs.TRASH: {Name: "trash path", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(nfs.TRASH, arg[0])
|
||||
}},
|
||||
AUTOGEN: {Name: "create name=hi help=示例 type=Zone,Hash,Data,Code main=main.go zone key", Help: "模块", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(AUTOGEN, mdb.CREATE, arg)
|
||||
}},
|
||||
COMPILE: {Name: "compile", Help: "编译", Hand: func(m *ice.Message, arg ...string) {
|
||||
if msg := m.Cmd(COMPILE, ice.SRC_MAIN_GO, ice.BIN_ICE_BIN); cli.IsSuccess(msg) {
|
||||
m.Cmd(UPGRADE, cli.RESTART)
|
||||
} else {
|
||||
_inner_make(m, msg)
|
||||
}
|
||||
}},
|
||||
nfs.SCRIPT: {Name: "script file=hi/hi.js", Help: "脚本", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Option(mdb.TEXT, strings.TrimSpace(kit.Select(_vimer_defs(m, kit.Ext(m.Option(nfs.FILE))), m.Option(mdb.TEXT))))
|
||||
m.Cmdy(TEMPLATE, nfs.DEFS)
|
||||
}},
|
||||
nfs.WEBSITE: {Name: "website file=hi.zml", Help: "网页", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Option(mdb.TEXT, strings.TrimSpace(kit.Select(_vimer_defs(m, kit.Ext(m.Option(nfs.FILE))), m.Option(mdb.TEXT))))
|
||||
m.Option(nfs.FILE, path.Join(nfs.WEBSITE, m.Option(nfs.FILE)))
|
||||
m.Cmdy(TEMPLATE, nfs.DEFS)
|
||||
}},
|
||||
web.DREAM: {Name: "dream name=hi repos", Help: "空间", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(web.DREAM, cli.START, arg)
|
||||
}},
|
||||
PUBLISH: {Name: "publish", Help: "发布", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(PUBLISH, ice.CONTEXTS)
|
||||
}},
|
||||
|
||||
mdb.SEARCH: {Name: "search type name text", Help: "搜索", Hand: func(m *ice.Message, arg ...string) {
|
||||
if arg[0] == mdb.FOREACH && arg[1] == "" {
|
||||
m.PushSearch(mdb.TYPE, "go", mdb.NAME, "src/main.go", mdb.TEXT, m.MergeCmd(""))
|
||||
}
|
||||
}},
|
||||
mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
|
||||
_vimer_inputs(m, arg...)
|
||||
}},
|
||||
"complete": {Name: "complete", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
|
||||
_vimer_complete(m, arg...)
|
||||
}},
|
||||
"listTags": {Name: "listTags", Help: "索引", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy("web.code.vim.tags", "listTags", arg)
|
||||
}},
|
||||
|
||||
"unpack": {Name: "unpack", Help: "导出文件", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(BINPACK, mdb.EXPORT)
|
||||
}},
|
||||
DEVPACK: {Name: "devpack", Help: "开发模式", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmd(nfs.LINK, ice.GO_SUM, path.Join(ice.SRC_DEBUG, ice.GO_SUM))
|
||||
m.Cmd(nfs.LINK, ice.GO_MOD, path.Join(ice.SRC_DEBUG, ice.GO_MOD))
|
||||
m.Cmdy(nfs.CAT, ice.GO_MOD)
|
||||
m.Cmdy(WEBPACK, mdb.REMOVE)
|
||||
m.ProcessInner()
|
||||
m.ToastSuccess()
|
||||
}},
|
||||
BINPACK: {Name: "binpack", Help: "打包模式", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(WEBPACK, mdb.CREATE)
|
||||
m.Cmdy(AUTOGEN, BINPACK)
|
||||
m.ProcessInner()
|
||||
m.ToastSuccess()
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(INNER, arg)
|
||||
m.Option("plug", m.Config("show.plug"))
|
||||
m.Option("exts", m.Config("show.exts"))
|
||||
m.Option("tabs", m.Config("show.tabs"))
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
@ -46,7 +46,6 @@ func _webpack_cache(m *ice.Message, dir string, write bool) {
|
||||
|
||||
m.Option(nfs.DIR_ROOT, "")
|
||||
m.Option(nfs.DIR_DEEP, true)
|
||||
m.Option(nfs.DIR_PACK, true)
|
||||
m.Option(nfs.DIR_TYPE, nfs.CAT)
|
||||
|
||||
// m.Cmd(nfs.DIR, ice.SRC).Tables(func(value ice.Maps) {
|
||||
|
@ -22,8 +22,7 @@ func _xterm_socket(m *ice.Message, h, t string) {
|
||||
m.Option(mdb.TEXT, t)
|
||||
}
|
||||
func _xterm_get(m *ice.Message, h string, must bool) (f *os.File) {
|
||||
f, _ = mdb.HashCache(m, h, func() ice.Any {
|
||||
m.Debug("what %v", must)
|
||||
f, _ = mdb.HashTarget(m, h, func() ice.Any {
|
||||
if !must {
|
||||
return nil
|
||||
}
|
||||
@ -49,7 +48,6 @@ func _xterm_get(m *ice.Message, h string, must bool) (f *os.File) {
|
||||
})
|
||||
return tty
|
||||
}).(*os.File)
|
||||
m.Debug("what %v", f)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -14,14 +14,10 @@ const (
|
||||
const SALARY = "salary"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
SALARY: {Name: SALARY, Help: "工资", Value: kit.Data(
|
||||
mdb.SHORT, MONTH, mdb.FIELD, "month,company,amount,income,tax",
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
SALARY: {Name: "salary month auto create", Help: "工资", Actions: ice.MergeAction(ice.Actions{
|
||||
mdb.CREATE: {Name: "create month company amount income tax 公积金 养老保险 医疗保险 生育保险 工伤保险 失业保险 企业公积金 企业养老保险 企业医疗保险 企业生育保险 企业工伤保险 企业失业保险", Help: "添加"},
|
||||
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
}, mdb.HashAction(mdb.SHORT, MONTH, mdb.FIELD, "month,company,amount,income,tax")), Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.HashSelect(m, arg...)
|
||||
amount, income, tax := 0, 0, 0
|
||||
m.Tables(func(value ice.Maps) {
|
||||
@ -31,5 +27,5 @@ func init() {
|
||||
})
|
||||
m.StatusTime(AMOUNT, amount, INCOME, income, TAX, tax)
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
const COUNT = "count"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
COUNT: {Name: "count begin_time@date end_time@date auto insert", Help: "倒计时", Meta: kit.Dict(
|
||||
ice.Display(""),
|
||||
), Actions: ice.MergeAction(ice.Actions{
|
||||
@ -44,5 +44,5 @@ func init() {
|
||||
)
|
||||
})
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ const (
|
||||
const PLAN = "plan"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
PLAN: {Name: "plan scale=week,day,week,month,year,long begin_time@date list", Help: "计划", Meta: kit.Dict(
|
||||
ice.Display("/plugin/local/team/plan.js"),
|
||||
), Actions: ice.MergeAction(ice.Actions{
|
||||
@ -95,5 +95,5 @@ func init() {
|
||||
_plan_list(m, begin_time, end_time)
|
||||
m.PushPodCmd(m.CommandKey(), arg...)
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -56,11 +56,7 @@ const (
|
||||
const TASK = "task"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
TASK: {Name: TASK, Help: "任务", Value: kit.Data(
|
||||
mdb.SHORT, mdb.ZONE, mdb.FIELD, "begin_time,id,status,level,score,type,name,text",
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
Index.MergeCommands(ice.Commands{
|
||||
TASK: {Name: "task zone id auto insert export import", Help: "任务", Actions: ice.MergeAction(ice.Actions{
|
||||
mdb.INSERT: {Name: "insert zone type=once,step,week name text begin_time@date close_time@date", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(mdb.INSERT, m.Prefix(TASK), "", mdb.HASH, m.OptionSimple(mdb.ZONE))
|
||||
@ -93,7 +89,7 @@ func init() {
|
||||
END: {Name: "end", Help: "完成", Hand: func(m *ice.Message, arg ...string) {
|
||||
_task_modify(m, STATUS, FINISH)
|
||||
}},
|
||||
}, mdb.ZoneAction(), ctx.CmdAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
}, mdb.ZoneAction(mdb.SHORT, mdb.ZONE, mdb.FIELD, "begin_time,id,status,level,score,type,name,text"), ctx.CmdAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
if mdb.ZoneSelect(m, arg...); len(arg) > 0 {
|
||||
status := map[string]int{}
|
||||
m.Tables(func(value ice.Maps) {
|
||||
@ -103,5 +99,5 @@ func init() {
|
||||
m.Status(status)
|
||||
}
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ import (
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
"shylinux.com/x/icebergs/base/ssh"
|
||||
"shylinux.com/x/icebergs/base/web"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
@ -76,7 +75,7 @@ func init() {
|
||||
m.Cmdy(nfs.DIR, "src/", kit.Dict(nfs.DIR_DEEP, ice.TRUE, nfs.DIR_REG, ".*\\.shy"), nfs.DIR_CLI_FIELDS)
|
||||
m.Cmdy(nfs.DIR, "src/help/", kit.Dict(nfs.DIR_DEEP, ice.TRUE, nfs.DIR_REG, ".*\\.shy"), nfs.DIR_CLI_FIELDS)
|
||||
}},
|
||||
web.STORY: {Name: "story", Help: "运行", Hand: func(m *ice.Message, arg ...string) {
|
||||
"story": {Name: "story", Help: "运行", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(arg[0], ctx.ACTION, ice.RUN, arg[2:])
|
||||
}},
|
||||
ice.PLAY: {Name: "play", Help: "演示"},
|
||||
|
11
data.go
11
data.go
@ -1,6 +1,7 @@
|
||||
package ice
|
||||
|
||||
import (
|
||||
"path"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@ -94,7 +95,7 @@ func (m *Message) Richs(prefix string, chain Any, raw Any, cb Any) (res Map) {
|
||||
case func(*sync.Mutex, string, Map):
|
||||
wg, mu := &sync.WaitGroup{}, &sync.Mutex{}
|
||||
defer wg.Wait()
|
||||
res = miss.Richs(kit.Keys(prefix, chain), cache, raw, func(key string, value Map) {
|
||||
res = miss.Richs(path.Join(prefix, kit.Keys(chain)), cache, raw, func(key string, value Map) {
|
||||
wg.Add(1)
|
||||
m.Go(func() {
|
||||
defer wg.Done()
|
||||
@ -102,7 +103,7 @@ func (m *Message) Richs(prefix string, chain Any, raw Any, cb Any) (res Map) {
|
||||
})
|
||||
})
|
||||
default:
|
||||
res = miss.Richs(kit.Keys(prefix, chain), cache, raw, cb)
|
||||
res = miss.Richs(path.Join(prefix, kit.Keys(chain)), cache, raw, cb)
|
||||
}
|
||||
return res
|
||||
|
||||
@ -113,7 +114,7 @@ func (m *Message) Rich(prefix string, chain Any, data Any) string {
|
||||
cache = kit.Data()
|
||||
m.Confv(prefix, chain, cache)
|
||||
}
|
||||
return miss.Rich(kit.Keys(prefix, chain), cache, data)
|
||||
return miss.Rich(path.Join(prefix, kit.Keys(chain)), cache, data)
|
||||
}
|
||||
func (m *Message) Grow(prefix string, chain Any, data Any) int {
|
||||
cache := m.Confm(prefix, chain)
|
||||
@ -121,7 +122,7 @@ func (m *Message) Grow(prefix string, chain Any, data Any) int {
|
||||
cache = kit.Data()
|
||||
m.Confv(prefix, chain, cache)
|
||||
}
|
||||
return miss.Grow(kit.Keys(prefix, chain), cache, data)
|
||||
return miss.Grow(path.Join(prefix, kit.Keys(chain)), cache, data)
|
||||
}
|
||||
func (m *Message) Grows(prefix string, chain Any, match string, value string, cb Any) Map {
|
||||
cache := m.Confm(prefix, chain)
|
||||
@ -139,7 +140,7 @@ func (m *Message) Grows(prefix string, chain Any, match string, value string, cb
|
||||
}
|
||||
}
|
||||
|
||||
return miss.Grows(kit.Keys(prefix, chain), cache,
|
||||
return miss.Grows(path.Join(prefix, kit.Keys(chain)), cache,
|
||||
kit.Int(kit.Select("0", strings.TrimPrefix(m.Option(CACHE_OFFEND), "-"))),
|
||||
kit.Int(kit.Select("10", m.Option(CACHE_LIMIT))),
|
||||
match, value, cb)
|
||||
|
34
exec.go
34
exec.go
@ -3,6 +3,7 @@ package ice
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -61,29 +62,6 @@ func (m *Message) Sleep300ms(arg ...Any) *Message { return m.Sleep("300ms", arg.
|
||||
func (m *Message) Sleep30ms(arg ...Any) *Message { return m.Sleep("30ms", arg...) }
|
||||
func (m *Message) Sleep3s(arg ...Any) *Message { return m.Sleep("3s", arg...) }
|
||||
func (m *Message) Sleep30s(arg ...Any) *Message { return m.Sleep("30s", arg...) }
|
||||
func (m *Message) Hold(n int) *Message {
|
||||
for ctx := m.target; ctx != nil; ctx = ctx.context {
|
||||
if ctx.wg != nil {
|
||||
ctx.wg.Add(n)
|
||||
break
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
func (m *Message) Done(ok bool) bool {
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
defer func() { recover() }()
|
||||
|
||||
for ctx := m.target; ctx != nil; ctx = ctx.context {
|
||||
if ctx.wg != nil {
|
||||
ctx.wg.Done()
|
||||
break
|
||||
}
|
||||
}
|
||||
return ok
|
||||
}
|
||||
func (m *Message) Call(sync bool, cb func(*Message) *Message) *Message {
|
||||
wait := make(chan bool, 2)
|
||||
|
||||
@ -117,8 +95,9 @@ func (m *Message) Back(res *Message) *Message {
|
||||
}
|
||||
return m
|
||||
}
|
||||
func (m *Message) Go(cb Any) *Message {
|
||||
task.Put(kit.FileLine(cb, 3), func(task *task.Task) error {
|
||||
|
||||
func (m *Message) Go(cb Any, arg ...string) *Message {
|
||||
task.Put(kit.Select(kit.FileLine(cb, 3), arg, 0), func(task *task.Task) error {
|
||||
m.TryCatch(m, true, func(m *Message) {
|
||||
switch cb := cb.(type) {
|
||||
case func(*Message):
|
||||
@ -126,7 +105,7 @@ func (m *Message) Go(cb Any) *Message {
|
||||
case func():
|
||||
cb()
|
||||
default:
|
||||
m.Error(true, ErrNotImplement)
|
||||
m.ErrorNotImplement(cb)
|
||||
}
|
||||
})
|
||||
return nil
|
||||
@ -146,7 +125,8 @@ func (m *Message) Event(key string, arg ...string) *Message {
|
||||
return m
|
||||
}
|
||||
func (m *Message) Right(arg ...Any) bool {
|
||||
key := strings.ReplaceAll(kit.Keys(arg...), PS, PT)
|
||||
key := path.Join(strings.ReplaceAll(kit.Keys(arg...), PT, PS))
|
||||
key = strings.TrimPrefix(strings.TrimSuffix(strings.ReplaceAll(key, PS, PT), PT), PT)
|
||||
return m.Option(MSG_USERROLE) == ROOT || !m.Warn(m.Cmdx(ROLE, RIGHT, m.Option(MSG_USERROLE), key) != OK,
|
||||
ErrNotRight, kit.Join(kit.Simple(arg), PT), USERROLE, m.Option(MSG_USERROLE), FILELINE, kit.FileLine(2, 3))
|
||||
}
|
||||
|
4
info.go
4
info.go
@ -1,7 +1,6 @@
|
||||
package ice
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
@ -36,6 +35,7 @@ var Info = struct {
|
||||
NodeName string
|
||||
CtxShare string
|
||||
CtxRiver string
|
||||
PidPath string
|
||||
|
||||
Help string
|
||||
cans string
|
||||
@ -45,7 +45,6 @@ var Info = struct {
|
||||
names Map
|
||||
|
||||
render map[string]func(*Message, string, ...Any) string
|
||||
Dump func(w io.Writer, name string, cb func(string)) bool
|
||||
Log func(m *Message, p, l, s string)
|
||||
}{
|
||||
Help: `
|
||||
@ -73,7 +72,6 @@ source: https://shylinux.com/x/icebergs
|
||||
names: Map{},
|
||||
|
||||
render: map[string]func(*Message, string, ...Any) string{},
|
||||
Dump: func(w io.Writer, name string, cb func(string)) bool { return false },
|
||||
Log: func(m *Message, p, l, s string) {},
|
||||
}
|
||||
|
||||
|
57
init.go
57
init.go
@ -3,11 +3,11 @@ package ice
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
kit "shylinux.com/x/toolkits"
|
||||
log "shylinux.com/x/toolkits/logs"
|
||||
"shylinux.com/x/toolkits/conf"
|
||||
"shylinux.com/x/toolkits/logs"
|
||||
)
|
||||
|
||||
type Frame struct{}
|
||||
@ -16,8 +16,6 @@ func (f *Frame) Spawn(m *Message, c *Context, arg ...string) Server {
|
||||
return &Frame{}
|
||||
}
|
||||
func (f *Frame) Begin(m *Message, arg ...string) Server {
|
||||
defer m.Cost(LOG_BEGIN, ICE)
|
||||
|
||||
list := map[*Context]*Message{m.target: m}
|
||||
m.Travel(func(p *Context, s *Context) {
|
||||
s.root = m.target
|
||||
@ -29,20 +27,17 @@ func (f *Frame) Begin(m *Message, arg ...string) Server {
|
||||
return f
|
||||
}
|
||||
func (f *Frame) Start(m *Message, arg ...string) bool {
|
||||
defer m.Cost(LOG_START, ICE)
|
||||
|
||||
m.Cap(CTX_STREAM, strings.Split(m.Time(), SP)[1])
|
||||
m.Cmdy("mdb._init")
|
||||
m.Cmdy(INIT, arg)
|
||||
|
||||
for _, k := range kit.Split(Getenv("ctx_daemon")) {
|
||||
for _, k := range kit.Split(Getenv(CTX_DAEMON)) {
|
||||
m.Start(k)
|
||||
}
|
||||
m.Cmd(arg)
|
||||
return true
|
||||
}
|
||||
func (f *Frame) Close(m *Message, arg ...string) bool {
|
||||
defer m.Cost(LOG_CLOSE, ICE)
|
||||
|
||||
list := map[*Context]*Message{m.target: m}
|
||||
m.Travel(func(p *Context, s *Context) {
|
||||
if msg, ok := list[p]; ok && msg != nil {
|
||||
@ -50,6 +45,7 @@ func (f *Frame) Close(m *Message, arg ...string) bool {
|
||||
s.Close(list[s], arg...)
|
||||
}
|
||||
})
|
||||
conf.Close()
|
||||
return true
|
||||
}
|
||||
|
||||
@ -57,7 +53,6 @@ var Index = &Context{Name: ICE, Help: "冰山模块", Configs: map[string]*Confi
|
||||
HELP: {Value: kit.Data(INDEX, Info.Help)},
|
||||
}, Commands: map[string]*Command{
|
||||
CTX_INIT: {Hand: func(m *Message, arg ...string) {
|
||||
defer m.Cost(CTX_INIT)
|
||||
m.root.Travel(func(p *Context, c *Context) {
|
||||
if cmd, ok := c.Commands[CTX_INIT]; ok && p != nil {
|
||||
c._command(m.Spawn(c), cmd, CTX_INIT, arg...)
|
||||
@ -72,16 +67,12 @@ var Index = &Context{Name: ICE, Help: "冰山模块", Configs: map[string]*Confi
|
||||
m.Echo(m.Config(INDEX))
|
||||
}},
|
||||
EXIT: {Name: "exit", Help: "结束", Hand: func(m *Message, arg ...string) {
|
||||
m.root.Option(EXIT, kit.Select("0", arg, 0))
|
||||
defer m.Target().Close(m.root.Spawn(), arg...)
|
||||
|
||||
m.root.Option(EXIT, kit.Select("0", arg, 0))
|
||||
m.Cmd(SOURCE, ETC_EXIT_SHY)
|
||||
m.root.Cmd(CTX_EXIT)
|
||||
}},
|
||||
CTX_EXIT: {Hand: func(m *Message, arg ...string) {
|
||||
defer m.Cost(CTX_EXIT)
|
||||
m.Option("cmd_dir", "")
|
||||
m.Option("dir_root", "")
|
||||
m.root.Travel(func(p *Context, c *Context) {
|
||||
if cmd, ok := c.Commands[CTX_EXIT]; ok && p != nil {
|
||||
m.TryCatch(m.Spawn(c), true, func(msg *Message) {
|
||||
@ -89,59 +80,35 @@ var Index = &Context{Name: ICE, Help: "冰山模块", Configs: map[string]*Confi
|
||||
})
|
||||
}
|
||||
})
|
||||
_exit <- kit.Int(m.Option(EXIT))
|
||||
}},
|
||||
}, server: &Frame{}, wg: &sync.WaitGroup{}}
|
||||
}, server: &Frame{}}
|
||||
var Pulse = &Message{time: time.Now(), code: 0,
|
||||
meta: map[string][]string{}, data: Map{},
|
||||
source: Index, target: Index, Hand: true,
|
||||
}
|
||||
|
||||
var _exit = make(chan int, 1)
|
||||
|
||||
func init() { Index.root, Pulse.root = Index, Pulse }
|
||||
|
||||
func Run(arg ...string) string {
|
||||
list := []string{}
|
||||
for k := range Info.File {
|
||||
if strings.HasPrefix(k, Info.Make.Path+PS) {
|
||||
list = append(list, k)
|
||||
}
|
||||
}
|
||||
for _, k := range list {
|
||||
Info.File["/require/"+strings.TrimPrefix(k, Info.Make.Path+PS)] = Info.File[k]
|
||||
delete(Info.File, k)
|
||||
}
|
||||
|
||||
if len(arg) == 0 { // 进程参数
|
||||
if arg = append(arg, os.Args[1:]...); kit.Env("ctx_arg") != "" {
|
||||
arg = append(arg, kit.Split(kit.Env("ctx_arg"))...)
|
||||
}
|
||||
arg = kit.Simple(arg, os.Args[1:], kit.Split(kit.Env("ctx_arg")))
|
||||
}
|
||||
|
||||
Pulse.meta[MSG_DETAIL] = arg
|
||||
switch Index.Merge(Index).Begin(Pulse.Spawn(), arg...); kit.Select("", arg, 0) {
|
||||
case SERVE, SPACE: // 启动服务
|
||||
switch strings.Split(os.Getenv("TERM"), "-")[0] {
|
||||
case "xterm", "screen":
|
||||
Info.Colors = true
|
||||
default:
|
||||
Info.Colors = false
|
||||
}
|
||||
if log.LogDisable = false; Index.Start(Pulse, arg...) {
|
||||
Pulse.TryCatch(Pulse, true, func(Pulse *Message) { Index.wg.Wait() })
|
||||
os.Exit(<-_exit)
|
||||
if Index.Start(Pulse, arg...) {
|
||||
conf.Wait()
|
||||
os.Exit(kit.Int(Pulse.Option(EXIT)))
|
||||
}
|
||||
default: // 执行命令
|
||||
if len(arg) == 0 {
|
||||
if logs.Disable(true); len(arg) == 0 {
|
||||
arg = append(arg, HELP)
|
||||
}
|
||||
|
||||
Pulse.Cmd(INIT)
|
||||
if Pulse.Cmdy(arg); strings.TrimSpace(Pulse.Result()) == "" {
|
||||
Pulse.Table()
|
||||
}
|
||||
Pulse.Sleep30ms()
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(Pulse.Result(), NL) {
|
||||
|
118
logs.go
118
logs.go
@ -7,15 +7,13 @@ import (
|
||||
"time"
|
||||
|
||||
kit "shylinux.com/x/toolkits"
|
||||
log "shylinux.com/x/toolkits/logs"
|
||||
"shylinux.com/x/toolkits/logs"
|
||||
)
|
||||
|
||||
func (m *Message) log(level string, str string, arg ...Any) *Message {
|
||||
if log.LogDisable {
|
||||
return m // 禁用日志
|
||||
}
|
||||
if str = strings.TrimSpace(kit.Format(str, arg...)); Info.Log != nil {
|
||||
Info.Log(m, m.FormatPrefix(), level, str) // 日志分流
|
||||
_source := logs.FileLineMeta(logs.FileLine(3, 3))
|
||||
if Info.Log != nil {
|
||||
Info.Log(m, m.FormatPrefix(), level, logs.Format(str, append(arg, _source)...)) // 日志分流
|
||||
}
|
||||
|
||||
// 日志颜色
|
||||
@ -33,14 +31,6 @@ func (m *Message) log(level string, str string, arg ...Any) *Message {
|
||||
}
|
||||
}
|
||||
|
||||
// 文件行号
|
||||
switch level {
|
||||
case LOG_INFO, LOG_CMDS, "refer", "form":
|
||||
case LOG_BEGIN:
|
||||
default:
|
||||
suffix += SP + kit.FileLine(3, 3)
|
||||
}
|
||||
|
||||
// 长度截断
|
||||
switch level {
|
||||
case LOG_INFO, LOG_SEND, LOG_RECV:
|
||||
@ -50,21 +40,31 @@ func (m *Message) log(level string, str string, arg ...Any) *Message {
|
||||
}
|
||||
|
||||
// 输出日志
|
||||
log.Info(kit.Format("%02d %9s %s%s %s%s", m.code,
|
||||
kit.Format("%4s->%-4s", m.source.Name, m.target.Name), prefix, level, str, suffix))
|
||||
logs.Infof(str, append(arg, logs.PrefixMeta(kit.Format("%02d %4s->%-4s %s%s ", m.code, m.source.Name, m.target.Name, prefix, level)), logs.SuffixMeta(suffix), _source)...)
|
||||
return m
|
||||
}
|
||||
func (m *Message) join(arg ...Any) string {
|
||||
args := kit.Simple(arg...)
|
||||
list := []string{}
|
||||
for i := 0; i < len(args); i += 2 {
|
||||
if i == len(args)-1 {
|
||||
list = append(list, args[i])
|
||||
func (m *Message) join(arg ...Any) (string, []Any) {
|
||||
list, meta := []string{}, []Any{}
|
||||
for i := 0; i < len(arg); i += 2 {
|
||||
switch v := arg[i].(type) {
|
||||
case logs.Meta:
|
||||
i--
|
||||
meta = append(meta, v)
|
||||
continue
|
||||
}
|
||||
if key := strings.TrimSpace(kit.Format(arg[i])); i == len(arg)-1 {
|
||||
list = append(list, key)
|
||||
} else {
|
||||
list = append(list, strings.TrimSpace(args[i])+kit.Select("", DF, !strings.HasSuffix(strings.TrimSpace(args[i]), DF)), kit.Format(args[i+1]))
|
||||
switch v := arg[i+1].(type) {
|
||||
case logs.Meta:
|
||||
list = append(list, key)
|
||||
meta = append(meta, v)
|
||||
continue
|
||||
}
|
||||
list = append(list, key+kit.Select("", DF, !strings.HasSuffix(key, DF)), kit.Format(kit.Select("", kit.Simple(arg[i+1]), 0)))
|
||||
}
|
||||
}
|
||||
return kit.Join(list, SP)
|
||||
return kit.Join(list, SP), meta
|
||||
}
|
||||
|
||||
func (m *Message) Log(level string, str string, arg ...Any) *Message {
|
||||
@ -73,10 +73,6 @@ func (m *Message) Log(level string, str string, arg ...Any) *Message {
|
||||
func (m *Message) Info(str string, arg ...Any) *Message {
|
||||
return m.log(LOG_INFO, str, arg...)
|
||||
}
|
||||
func (m *Message) Cost(arg ...Any) *Message {
|
||||
list := []string{m.FormatCost(), m.join(arg...)}
|
||||
return m.log(LOG_COST, kit.Join(list, SP))
|
||||
}
|
||||
func (m *Message) Warn(err Any, arg ...Any) bool {
|
||||
switch err := err.(type) {
|
||||
case error:
|
||||
@ -91,21 +87,30 @@ func (m *Message) Warn(err Any, arg ...Any) bool {
|
||||
case nil:
|
||||
return false
|
||||
}
|
||||
m.log(LOG_WARN, m.join(kit.Simple(arg...)))
|
||||
|
||||
str, meta := m.join(arg...)
|
||||
m.log(LOG_WARN, str, meta...)
|
||||
m.error(arg...)
|
||||
return true
|
||||
}
|
||||
func (m *Message) error(arg ...Any) {
|
||||
if len(arg) == 0 {
|
||||
arg = append(arg, "", "")
|
||||
} else if len(arg) == 1 {
|
||||
arg = append(arg, "")
|
||||
}
|
||||
m.meta[MSG_RESULT] = kit.Simple(ErrWarn, arg[0], arg[1], SP, m.join(kit.Simple(arg[2:]...)))
|
||||
return true
|
||||
str, meta := m.join(arg[2:]...)
|
||||
m.meta[MSG_RESULT] = kit.Simple(ErrWarn, arg[0], arg[1], str, meta)
|
||||
}
|
||||
func (m *Message) Error(err bool, str string, arg ...Any) bool {
|
||||
func (m *Message) ErrorNotImplement(arg ...Any) {
|
||||
m.Error(true, append(kit.List(ErrNotImplement), arg...)...)
|
||||
}
|
||||
func (m *Message) Error(err bool, arg ...Any) bool {
|
||||
if err {
|
||||
m.Echo(ErrWarn).Echo(str, arg...)
|
||||
m.error(arg...)
|
||||
m.log(LOG_ERROR, m.FormatStack(1, 100))
|
||||
m.log(LOG_ERROR, str, arg...)
|
||||
str, meta := m.join(arg...)
|
||||
m.log(LOG_ERROR, str, meta)
|
||||
m.log(LOG_ERROR, m.FormatChain())
|
||||
return true
|
||||
}
|
||||
@ -117,43 +122,62 @@ func (m *Message) Debug(str string, arg ...Any) {
|
||||
}
|
||||
m.log(LOG_DEBUG, str, arg...)
|
||||
}
|
||||
func (m *Message) Cost(arg ...Any) *Message {
|
||||
str, meta := m.join(arg...)
|
||||
if len(arg) == 0 {
|
||||
str = kit.Join(m.meta[MSG_DETAIL], SP)
|
||||
}
|
||||
list := []string{m.FormatCost(), str}
|
||||
return m.log(LOG_COST, kit.Join(list, SP), meta...)
|
||||
}
|
||||
|
||||
func (m *Message) Logs(level string, arg ...Any) *Message {
|
||||
return m.log(level, m.join(arg...))
|
||||
str, meta := m.join(arg...)
|
||||
return m.log(level, str, meta...)
|
||||
}
|
||||
func (m *Message) Log_AUTH(arg ...Any) *Message {
|
||||
return m.log(LOG_AUTH, m.join(arg...))
|
||||
str, meta := m.join(arg...)
|
||||
return m.log(LOG_AUTH, str, meta...)
|
||||
}
|
||||
func (m *Message) Log_SEND(arg ...Any) *Message {
|
||||
return m.log(LOG_AUTH, m.join(arg...))
|
||||
str, meta := m.join(arg...)
|
||||
return m.log(LOG_AUTH, str, meta...)
|
||||
}
|
||||
func (m *Message) Log_CREATE(arg ...Any) *Message {
|
||||
return m.log(LOG_CREATE, m.join(arg...))
|
||||
str, meta := m.join(arg...)
|
||||
return m.log(LOG_CREATE, str, meta...)
|
||||
}
|
||||
func (m *Message) Log_REMOVE(arg ...Any) *Message {
|
||||
return m.log(LOG_REMOVE, m.join(arg...))
|
||||
str, meta := m.join(arg...)
|
||||
return m.log(LOG_REMOVE, str, meta...)
|
||||
}
|
||||
func (m *Message) Log_INSERT(arg ...Any) *Message {
|
||||
return m.log(LOG_INSERT, m.join(arg...))
|
||||
str, meta := m.join(arg...)
|
||||
return m.log(LOG_INSERT, str, meta...)
|
||||
}
|
||||
func (m *Message) Log_DELETE(arg ...Any) *Message {
|
||||
return m.log(LOG_DELETE, m.join(arg...))
|
||||
str, meta := m.join(arg...)
|
||||
return m.log(LOG_DELETE, str, meta...)
|
||||
}
|
||||
func (m *Message) Log_MODIFY(arg ...Any) *Message {
|
||||
return m.log(LOG_MODIFY, m.join(arg...))
|
||||
str, meta := m.join(arg...)
|
||||
return m.log(LOG_MODIFY, str, meta...)
|
||||
}
|
||||
func (m *Message) Log_SELECT(arg ...Any) *Message {
|
||||
return m.log(LOG_SELECT, m.join(arg...))
|
||||
str, meta := m.join(arg...)
|
||||
return m.log(LOG_SELECT, str, meta...)
|
||||
}
|
||||
func (m *Message) Log_EXPORT(arg ...Any) *Message {
|
||||
return m.log(LOG_EXPORT, m.join(arg...))
|
||||
str, meta := m.join(arg...)
|
||||
return m.log(LOG_EXPORT, str, meta...)
|
||||
}
|
||||
func (m *Message) Log_IMPORT(arg ...Any) *Message {
|
||||
return m.log(LOG_IMPORT, m.join(arg...))
|
||||
str, meta := m.join(arg...)
|
||||
return m.log(LOG_IMPORT, str, meta...)
|
||||
}
|
||||
|
||||
func (m *Message) FormatPrefix() string {
|
||||
return kit.Format("%s %d %s->%s", m.Time(), m.code, m.source.Name, m.target.Name)
|
||||
return kit.Format("%s %d %s->%s", logs.FmtTime(logs.Now()), m.code, m.source.Name, m.target.Name)
|
||||
}
|
||||
func (m *Message) FormatTime() string {
|
||||
return m.Time()
|
||||
@ -187,7 +211,7 @@ func (m *Message) FormatStack(s, n int) string {
|
||||
case "reflect", "runtime", "http", "task", "icebergs":
|
||||
default:
|
||||
switch kit.Select("", ls, 1) {
|
||||
case "(*Frame)":
|
||||
// case "(*Frame)":
|
||||
default:
|
||||
list = append(list, kit.Format("%s:%d\t%s", file, frame.Line, name))
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user