1
0
forked from x/icebergs
This commit is contained in:
harveyshao 2022-08-01 18:09:36 +08:00
parent 1ec7aeff79
commit 8e7a403b35
150 changed files with 2845 additions and 2970 deletions

View File

@ -1,39 +1,29 @@
package aaa package aaa
import ( import (
"path"
"strings"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
kit "shylinux.com/x/toolkits" 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 { 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) { func _role_black(m *ice.Message, userrole, chain string) {
m.Richs(ROLE, nil, userrole, func(key string, value ice.Map) { mdb.HashSelectUpdate(m, userrole, func(value ice.Map) {
list := value[BLACK].(ice.Map)
m.Log_INSERT(ROLE, userrole, BLACK, chain) m.Log_INSERT(ROLE, userrole, BLACK, chain)
list := value[BLACK].(ice.Map)
list[chain] = true list[chain] = true
}) })
} }
func _role_white(m *ice.Message, userrole, chain string) { func _role_white(m *ice.Message, userrole, chain string) {
m.Richs(ROLE, nil, userrole, func(key string, value ice.Map) { mdb.HashSelectUpdate(m, userrole, func(value ice.Map) {
list := value[WHITE].(ice.Map)
m.Log_INSERT(ROLE, userrole, WHITE, chain) m.Log_INSERT(ROLE, userrole, WHITE, chain)
list := value[WHITE].(ice.Map)
list[chain] = true list[chain] = true
}) })
} }
@ -42,7 +32,7 @@ func _role_right(m *ice.Message, userrole string, keys ...string) (ok bool) {
return true // 超级权限 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 ok = true
list := value[BLACK].(ice.Map) list := value[BLACK].(ice.Map)
for i := 0; i < len(keys); i++ { 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 return ok
} }
func _role_list(m *ice.Message, userrole string) *ice.Message {
func RoleRight(m *ice.Message, userrole string, keys ...string) bool { mdb.HashSelectDetail(m, kit.Select(VOID, userrole), func(value ice.Map) {
return _role_right(m, userrole, kit.Split(kit.Keys(keys), ice.PT)...) 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 ( const (
@ -91,10 +92,8 @@ const (
const ROLE = "role" const ROLE = "role"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
ROLE: {Name: ROLE, Help: "角色", Value: kit.Data(mdb.SHORT, mdb.NAME)}, ROLE: {Name: "role role auto insert", Help: "角色", Actions: ice.MergeAction(ice.Actions{
}, Commands: ice.Commands{
ROLE: {Name: "role role auto insert", Help: "角色", Actions: ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { 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, TECH, BLACK, kit.Dict(), WHITE, kit.Dict()))
m.Rich(ROLE, nil, kit.Dict(mdb.NAME, VOID, WHITE, kit.Dict(), BLACK, 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) 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) { 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)) m.Log_INSERT(ROLE, m.Option(ROLE), m.Option(mdb.ZONE), m.Option(mdb.KEY))
list := value[m.Option(mdb.ZONE)].(ice.Map) 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) { 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)) m.Log_DELETE(ROLE, m.Option(ROLE), m.Option(mdb.ZONE), m.Option(mdb.KEY))
list := value[m.Option(mdb.ZONE)].(ice.Map) 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) m.Echo(ice.OK)
} }
}}, }},
}, Hand: func(m *ice.Message, arg ...string) { }, mdb.HashAction(mdb.SHORT, mdb.NAME)), Hand: func(m *ice.Message, arg ...string) {
_role_list(m, kit.Select("", arg, 0)) _role_list(m, kit.Select("", arg, 0)).PushAction(mdb.DELETE)
m.PushAction(mdb.DELETE)
}}, }},
}}) })
}
func RoleRight(m *ice.Message, userrole string, arg ...string) bool {
return m.Cmdx(ROLE, RIGHT, userrole, arg) == ice.OK
} }

View File

@ -4,54 +4,44 @@ import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
kit "shylinux.com/x/toolkits" 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_USERROLE, VOID)
m.Option(ice.MSG_USERNAME, "") m.Option(ice.MSG_USERNAME, "")
m.Option(ice.MSG_USERNICK, "") m.Option(ice.MSG_USERNICK, "")
if sessid == "" { if sessid == "" {
return false return
} }
m.Richs(SESS, nil, sessid, func(value ice.Map) { _source := logs.FileLineMeta(logs.FileLine(-1, 3))
if value = kit.GetMeta(value); m.Warn(kit.Time(kit.Format(value[mdb.TIME])) < kit.Time(m.Time()), ice.ErrNotValid) { 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 // 会话超时 return // 会话超时
} }
if m.Richs(USER, nil, value[USERNAME], func(value ice.Map) { m.Log_AUTH(
m.Log_AUTH( USERROLE, m.Option(ice.MSG_USERROLE, value[USERROLE]),
USERROLE, m.Option(ice.MSG_USERROLE, value[USERROLE]), USERNAME, m.Option(ice.MSG_USERNAME, value[USERNAME]),
USERNAME, m.Option(ice.MSG_USERNAME, value[USERNAME]), USERNICK, m.Option(ice.MSG_USERNICK, value[USERNICK]),
USERNICK, m.Option(ice.MSG_USERNICK, value[USERNICK]), _source,
) )
}) == 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]),
)
}
}) })
return m.Option(ice.MSG_USERNAME) != ""
} }
func _sess_create(m *ice.Message, username string) string { func _sess_create(m *ice.Message, username string) string {
if username == "" { if username == "" {
return "" return ""
} }
msg := m.Cmd(USER, username)
h := m.Cmdx(mdb.INSERT, SESS, "", mdb.HASH, mdb.TIME, m.Time(m.Conf(SESS, kit.Keym(mdb.EXPIRE))), if msg.Length() > 0 {
USERROLE, UserRole(m, username), USERNAME, username, USERNICK, UserNick(m, username), h := mdb.HashCreate(m, msg.AppendSimple(USERROLE, USERNAME, USERNICK), IP, m.Option(ice.MSG_USERIP), UA, m.Option(ice.MSG_USERUA)).Result()
IP, m.Option(ice.MSG_USERIP), UA, m.Option(ice.MSG_USERUA), m.Event(SESS_CREATE, SESS, h, USERNAME, username)
) return h
m.Event(SESS_CREATE, SESS, h, USERNAME, username) } else {
return h 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
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)
} }
const ( const (
@ -59,10 +49,11 @@ const (
UA = "ua" UA = "ua"
) )
const ( const (
CHECK = "check"
GRANT = "grant" GRANT = "grant"
LOGIN = "login" LOGIN = "login"
LOGOUT = "logout" LOGOUT = "logout"
EXPIRE = "expire" SESSID = "sessid"
) )
const ( const (
SESS_CREATE = "sess.create" SESS_CREATE = "sess.create"
@ -70,15 +61,21 @@ const (
const SESS = "sess" const SESS = "sess"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
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{
SESS: {Name: "sess hash auto prunes", Help: "会话", Actions: ice.MergeAction(ice.Actions{ SESS: {Name: "sess hash auto prunes", Help: "会话", Actions: ice.MergeAction(ice.Actions{
mdb.CREATE: {Name: "create username", Help: "创建"}, mdb.CREATE: {Name: "create username", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { _sess_create(m, m.Option(USERNAME))
mdb.HashSelect(m, arg...) }},
}}, 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) != ""
} }

View File

@ -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))) 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 ( const (
SECRET = "secret" SECRET = "secret"
PERIOD = "period" PERIOD = "period"
@ -55,20 +53,15 @@ const (
const TOTP = "totp" const TOTP = "totp"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
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{
TOTP: {Name: "totp name auto create", Help: "令牌", Actions: ice.MergeAction(ice.Actions{ 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) { mdb.CREATE: {Name: "create name=hi secret period=30 number=6", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
if m.Option(SECRET) == "" { // 创建密钥 if m.Option(SECRET) == "" { // 创建密钥
m.Option(SECRET, _totp_gen(kit.Int64(m.Option(PERIOD)))) m.Option(SECRET, _totp_gen(kit.Int64(m.Option(PERIOD))))
} }
mdb.HashCreate(m, m.OptionSimple(mdb.NAME, SECRET, PERIOD, NUMBER))
m.Cmd(mdb.INSERT, TOTP, "", mdb.HASH, 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) { mdb.HashSelect(m.Spawn(), arg...).Tables(func(value ice.Maps) {
if len(arg) > 0 { if len(arg) > 0 {
m.OptionFields(mdb.DETAIL) 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) }

View File

@ -4,95 +4,52 @@ import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
"shylinux.com/x/toolkits/logs"
) )
func _user_exists(m *ice.Message, name string) bool { func _user_login(m *ice.Message, name, word string) {
return m.Richs(USER, nil, name, nil) != nil if m.Warn(name == "", ice.ErrNotValid, name) {
} return
func _user_login(m *ice.Message, name, word string) (ok bool) { }
if !_user_exists(m, name) { if !mdb.HashSelectDetail(m, name, nil) {
_user_create(m, VOID, name, word) _user_create(m, VOID, name, word)
} }
m.Richs(USER, nil, name, func(key string, value ice.Map) { _source := logs.FileLineMeta(logs.FileLine(-1, 3))
if ok = !m.Warn(word != "" && word != value[PASSWORD], ice.ErrNotRight); ok { mdb.HashSelectDetail(m, name, func(value ice.Map) {
m.Log_AUTH( if m.Warn(word != "" && word != kit.Format(kit.Value(value, kit.Keys(mdb.EXTRA, PASSWORD))), ice.ErrNotRight) {
USERROLE, m.Option(ice.MSG_USERROLE, value[USERROLE]), return
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 ok
} }
func _user_create(m *ice.Message, role, name, word string) { func _user_create(m *ice.Message, name, word string, arg ...string) {
if name == "" { if m.Warn(name == "", ice.ErrNotValid, name) {
return return
} }
if word == "" { if word == "" {
if m.Richs(USER, nil, name, func(key string, value ice.Map) { word = m.CmdAppend(USER, name, PASSWORD)
word = kit.Format(value[PASSWORD])
}) == nil {
word = kit.Hashs()
}
} }
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) 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 ( const (
BACKGROUND = "background"
AVATAR = "avatar" AVATAR = "avatar"
GENDER = "gender" GENDER = "gender"
MOBILE = "mobile" MOBILE = "mobile"
EMAIL = "email" EMAIL = "email"
BACKGROUND = "background"
CITY = "city" CITY = "city"
COUNTRY = "country" COUNTRY = "country"
LANGUAGE = "language" LANGUAGE = "language"
@ -114,24 +71,50 @@ const (
const USER = "user" const USER = "user"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
USER: {Name: USER, Help: "用户", Value: kit.Data(
mdb.SHORT, USERNAME, mdb.FIELD, "time,userrole,username,usernick,userzone",
)},
}, Commands: ice.Commands{
USER: {Name: "user username auto create", Help: "用户", Actions: ice.MergeAction(ice.Actions{ 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) { mdb.SEARCH: {Name: "search type name text", Help: "搜索", Hand: func(m *ice.Message, arg ...string) {
if arg[0] == USER { mdb.HashSelectSearch(m, arg)
_user_search(m, arg[1], kit.Select("", arg, 2))
}
}}, }},
mdb.CREATE: {Name: "create userrole=void,tech username password", Help: "创建", Hand: func(m *ice.Message, arg ...string) { mdb.CREATE: {Name: "create username password userrole=void,tech", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
if !_user_exists(m, m.Option(USERNAME)) { _user_create(m, m.Option(USERNAME), m.Option(PASSWORD), m.OptionSimple(USERROLE)...)
_user_create(m, m.Option(USERROLE), m.Option(USERNAME), m.Option(PASSWORD))
}
}}, }},
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { LOGIN: {Name: "login username password", Help: "登录", Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelect(m, arg...) _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) != ""
} }

View File

@ -6,63 +6,67 @@ import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/gdb"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
func _daemon_exec(m *ice.Message, cmd *exec.Cmd) { func _daemon_exec(m *ice.Message, cmd *exec.Cmd) {
if r, ok := m.Optionv(CMD_INPUT).(io.Reader); ok { 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 { if w := _system_out(m, CMD_OUTPUT); w != nil {
cmd.Stdout = w cmd.Stdout, cmd.Stderr = w, w
cmd.Stderr = w
} }
if w := _system_out(m, CMD_ERRPUT); w != nil { if w := _system_out(m, CMD_ERRPUT); w != nil {
cmd.Stderr = w 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) { if e := cmd.Start(); m.Warn(e, ice.ErrNotStart, cmd.Args) {
mdb.HashModify(m, h, STATUS, ERROR, ERROR, e)
return // 启动失败 return // 启动失败
} }
mdb.HashSelectUpdate(m, h, func(value ice.Map) { value[PID] = cmd.Process.Pid })
m.Echo("%d", cmd.Process.Pid) m.Echo("%d", cmd.Process.Pid)
m.Go(func() { 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),
)
if e := cmd.Wait(); !m.Warn(e, ice.ErrNotStart, cmd.Args) && cmd.ProcessState.ExitCode() == 0 { 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.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 { } else {
if m.Conf(DAEMON, kit.Keys(mdb.HASH, h, kit.Keym(STATUS))) == START { mdb.HashSelectUpdate(m, h, func(value ice.Map) {
m.Cmd(mdb.MODIFY, DAEMON, "", mdb.HASH, mdb.HASH, h, STATUS, ERROR, ERROR, e) if value[STATUS] == START {
} value[STATUS], value[ERROR] = ERROR, e
}
})
} }
status := mdb.HashSelectFields(m, h, STATUS)
switch m.Sleep300ms(); cb := m.OptionCB(DAEMON).(type) { switch m.Sleep300ms(); cb := m.OptionCB(DAEMON).(type) {
case func(string) bool: 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) m.Cmdy(DAEMON, cmd.Path, cmd.Args)
} }
case func(string): case func(string):
cb(m.Conf(DAEMON, kit.Keys(mdb.HASH, h, kit.Keym(STATUS)))) cb(status)
case func(): case func():
cb() cb()
case nil:
default: default:
m.Error(true, ice.ErrNotImplement) m.ErrorNotImplement(cb)
} }
for _, p := range kit.Simple(CMD_INPUT, CMD_OUTPUT, CMD_ERRPUT) { for _, p := range kit.Simple(CMD_INPUT, CMD_OUTPUT, CMD_ERRPUT) {
kit.Close(m.Optionv(p)) kit.Close(m.Optionv(p))
} }
}) })
m.Sleep("100ms")
} }
const ( const (
@ -87,10 +91,10 @@ const (
RELOAD = "reload" RELOAD = "reload"
RESTART = "restart" RESTART = "restart"
START = "start"
STOP = "stop"
OPEN = "open" OPEN = "open"
CLOSE = "close" CLOSE = "close"
START = "start"
STOP = "stop"
BEGIN = "begin" BEGIN = "begin"
END = "end" END = "end"
@ -99,61 +103,51 @@ const (
BACK = "back" BACK = "back"
FROM = "from" FROM = "from"
MAIN = "main" MAIN = "main"
KILL = "kill"
) )
const DAEMON = "daemon" const DAEMON = "daemon"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
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{
DAEMON: {Name: "daemon hash auto start prunes", Help: "守护进程", Actions: ice.MergeAction(ice.Actions{ DAEMON: {Name: "daemon hash auto start prunes", Help: "守护进程", Actions: ice.MergeAction(ice.Actions{
ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) { 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) { mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
m.OptionFields(m.Config(mdb.FIELD)) mdb.HashPrunesValue(m, STATUS, ERROR)
m.Cmdy(mdb.PRUNES, DAEMON, "", mdb.HASH, STATUS, STOP) mdb.HashPrunesValue(m, STATUS, STOP)
m.Cmdy(mdb.PRUNES, DAEMON, "", mdb.HASH, STATUS, ERROR)
}}, }},
START: {Name: "start cmd env dir", Help: "添加", Hand: func(m *ice.Message, arg ...string) { START: {Name: "start cmd env dir", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
m.Option(CMD_DIR, m.Option(DIR)) m.Option(CMD_DIR, m.Option(DIR))
m.Option(CMD_ENV, kit.Split(m.Option(ENV), " =")) 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) { 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) { STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) {
m.OptionFields(m.Config(mdb.FIELD)) m.OptionFields(m.Config(mdb.FIELD))
m.Cmd(mdb.SELECT, DAEMON, "", mdb.HASH, m.OptionSimple(mdb.HASH)).Tables(func(value ice.Maps) { mdb.HashSelect(m, m.Option(mdb.HASH)).Tables(func(value ice.Maps) {
m.Cmd(mdb.MODIFY, DAEMON, "", mdb.HASH, m.OptionSimple(mdb.HASH), STATUS, STOP) mdb.HashModify(m, m.OptionSimple(mdb.HASH), STATUS, STOP)
m.Cmdy(SYSTEM, KILL, value[PID]) m.Cmd(gdb.SIGNAL, gdb.KILL, value[PID])
}) })
if IsSuccess(m) {
m.SetAppend()
}
}}, }},
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { }, mdb.HashAction(mdb.FIELD, "time,hash,status,pid,cmd,dir,env")), Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelect(m, arg...).Set(ctx.ACTION).Tables(func(value ice.Maps) { if mdb.HashSelect(m, arg...).Tables(func(value ice.Maps) {
switch value[STATUS] { switch value[STATUS] {
case START: case START:
m.PushButton(RESTART, STOP) m.PushButton(RESTART, STOP)
default: default:
m.PushButton(mdb.REMOVE) m.PushButton(mdb.REMOVE)
} }
}) }); len(arg) == 0 || m.Length() > 0 {
if len(arg) == 0 || m.Length() > 0 {
return return
} }
if len(arg) == 1 { if len(arg) == 1 {
arg = kit.Split(arg[0]) arg = kit.Split(arg[0])
} }
_daemon_exec(m, _system_cmd(m, arg...)) _daemon_exec(m, _system_cmd(m, arg...))
}}, }},
}}) })
} }

View File

@ -5,18 +5,12 @@ import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/gdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits" 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 { 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) 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" const FOREVER = "forever"
func init() { func init() {
const SERVE = "serve" Index.MergeCommands(ice.Commands{
const RESTART = "restart"
Index.Merge(&ice.Context{Commands: ice.Commands{
FOREVER: {Name: "forever auto", Help: "启动", Actions: ice.Actions{ FOREVER: {Name: "forever auto", Help: "启动", Actions: ice.Actions{
RESTART: {Name: "restart", Help: "重启", Hand: func(m *ice.Message, arg ...string) { gdb.START: {Name: "start", Help: "服务", Hand: func(m *ice.Message, arg ...string) {
_forever_kill(m, "INT")
}},
SERVE: {Name: "serve", Help: "服务", Hand: func(m *ice.Message, arg ...string) {
env := []string{PATH, BinPath(), HOME, kit.Select(kit.Path(""), os.Getenv(HOME))} 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) != "" { if kit.Env(k) != "" {
env = append(env, k, kit.Env(k)) env = append(env, k, kit.Env(k))
} }
@ -49,24 +38,27 @@ func init() {
m.Cmd(FOREVER, STOP) m.Cmd(FOREVER, STOP)
m.Cmdy(FOREVER, kit.Select(os.Args[0], nfs.PWD+ice.BIN_ICE_BIN, kit.FileExists(ice.BIN_ICE_BIN)), 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) { gdb.RESTART: {Name: "restart", Help: "重启", Hand: func(m *ice.Message, arg ...string) {
_forever_kill(m, "QUIT") 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) { }, Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 { if len(arg) == 0 {
_forever_kill(m, "") m.Cmdy(RUNTIME, BOOTINFO)
return return
} }
for { 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)) { if m.Sleep("1s"); IsSuccess(m.Cmd(SYSTEM, arg)) {
println(kit.Format("%s exit", kit.Now())) logs.Println("exit")
return break
} }
} }
}}}, }},
}) })
} }

View File

@ -1,6 +1,7 @@
package cli package cli
import ( import (
"runtime"
"strings" "strings"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
@ -8,18 +9,9 @@ import (
kit "shylinux.com/x/toolkits" 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 ( const (
OSID = "OSID" CMD = "cmd"
OSID = "osid"
ALPINE = "alpine" ALPINE = "alpine"
CENTOS = "centos" CENTOS = "centos"
UBUNTU = "ubuntu" UBUNTU = "ubuntu"
@ -28,31 +20,49 @@ const (
const MIRRORS = "mirrors" const MIRRORS = "mirrors"
func init() { func init() {
Index.Merge(&ice.Context{Commands: ice.Commands{ Index.MergeCommands(ice.Commands{
MIRRORS: {Name: "mirrors cli auto", Help: "软件镜像", Actions: ice.MergeAction(ice.Actions{ MIRRORS: {Name: "mirrors cli auto", Help: "软件镜像", Actions: ice.MergeAction(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
m.Go(func() { m.Conf(m.PrefixKey(), kit.Keys(mdb.HASH), "")
m.Sleep("1s") IsAlpine(m, "curl")
IsAlpine(m, "curl", "system apk add curl") IsAlpine(m, "make")
IsAlpine(m, "make", "system apk add make") IsAlpine(m, "gcc")
IsAlpine(m, "gcc", "system apk add gcc") IsAlpine(m, "vim")
IsAlpine(m, "vim", "system apk add vim") IsAlpine(m, "tmux")
IsAlpine(m, "tmux", "system apk add tmux")
if IsAlpine(m, "git", "system apk add git"); !IsAlpine(m, "go", "system apk add git go") { IsAlpine(m, "git")
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")) 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: "创建"}, ALPINE: {Name: "alpine cli cmd", Help: "安装", Hand: func(m *ice.Message, arg ...string) {
}, mdb.HashAction(mdb.SHORT, "cli", mdb.FIELD, "time,cli,cmd"))}, 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
} }

View File

@ -31,6 +31,7 @@ func _parse_color(str string) color.Color {
for k := range _trans_web { for k := range _trans_web {
list = append(list, k) list = append(list, k)
} }
kit.Sort(list)
str = list[rand.Intn(len(list))] str = list[rand.Intn(len(list))]
} }
if strings.HasPrefix(str, "#") { 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 ( const (
FG = "fg" FG = "fg"
BG = "bg" BG = "bg"
SIZE = "size"
DARK = 255 DARK = 255
LIGHT = 127 LIGHT = 127
SIZE = "size"
) )
const ( const (
COLOR = "color" COLOR = "color"
@ -129,7 +118,7 @@ const (
const QRCODE = "qrcode" const QRCODE = "qrcode"
func init() { 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{ 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.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
ice.AddRender(ice.RENDER_QRCODE, func(m *ice.Message, cmd string, args ...ice.Any) 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) { mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {
switch arg[0] { switch arg[0] {
case "text": case mdb.TEXT:
m.Push("text", "hi") m.Push(arg[0], "hi", "hello", "world")
m.Push("text", "hello") case FG, BG:
m.Push("text", "world") m.Push(arg[0], RED, GREEN, BLUE)
case "fg", "bg":
m.Push("color", "red")
m.Push("color", "green")
m.Push("color", "blue")
} }
}}, }},
}, Hand: func(m *ice.Message, arg ...string) { }, Hand: func(m *ice.Message, arg ...string) {
m.Option(SIZE, kit.Select("240", arg, 3)) m.Option(SIZE, kit.Select("240", arg, 3))
m.Option(BG, kit.Select(WHITE, arg, 2)) m.Option(BG, kit.Select(WHITE, arg, 2))
m.Option(FG, kit.Select(BLUE, arg, 1)) m.Option(FG, kit.Select(BLUE, arg, 1))
if m.IsCliUA() { 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 { } else {
_qrcode_web(m, kit.Select(m.Option(ice.MSG_USERWEB), arg, 0)) _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) }

View File

@ -9,6 +9,7 @@ import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/gdb"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits" 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, GOOS), runtime.GOOS)
m.Conf(RUNTIME, kit.Keys(HOST, PID), os.Getpid()) 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, HOME), kit.Env(HOME))
m.Conf(RUNTIME, kit.Keys(HOST, MAXPROCS), runtime.GOMAXPROCS(0))
// 启动信息 boot // 启动目录 boot
if name, e := os.Hostname(); e == nil { m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME), kit.Env("HOSTNAME"))
m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME), kit.Select(name, 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 { m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME), path.Base(kit.Env("PWD")))
name = path.Base(kit.Select(name, kit.Env("PWD"))) if name, e := os.Getwd(); e == nil && name != "" {
name = kit.Slice(strings.Split(name, ice.PS), -1)[0] m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME), path.Base(name))
name = kit.Slice(strings.Split(name, "\\"), -1)[0]
m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME), name)
} }
m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME), kit.Select(kit.UserName(), kit.Select(kit.Env("WORKSPACE_GIT_USERNAME"), kit.Env(CTX_USER)))) 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.HostName = m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME))
ice.Info.PathName = m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME)) ice.Info.PathName = m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME))
ice.Info.UserName = m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME)) ice.Info.UserName = m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME))
aaa.UserRoot(ice.Pulse) 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) 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]) bin := _system_find(m, os.Args[0])
m.Conf(RUNTIME, kit.Keys(BOOT, ice.BIN), bin) m.Conf(RUNTIME, kit.Keys(BOOT, ice.BIN), bin)
if s, e := os.Stat(bin); e == nil { 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 { if f, e := os.Open(bin); e == nil {
defer f.Close() 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 // 环境变量 conf
for _, k := range []string{CTX_SHY, CTX_DEV, CTX_OPS, CTX_ARG, CTX_PID, CTX_USER, CTX_SHARE, CTX_RIVER, CTX_DAEMON} { for _, k := range ENV_LIST {
m.Conf(RUNTIME, kit.Keys(CONF, k), kit.Env(k)) 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) { m.Cmd(nfs.CAT, "/etc/os-release", func(text string) {
if ls := kit.Split(text, "="); len(ls) > 1 { if ls := kit.Split(text, "="); len(ls) > 1 {
switch ls[0] { switch ls[0] {
@ -119,11 +127,11 @@ const (
WINDOWS = "windows" WINDOWS = "windows"
) )
const ( const (
SHELL = "SHELL"
TERM = "TERM"
USER = "USER"
HOME = "HOME"
PATH = "PATH" PATH = "PATH"
HOME = "HOME"
USER = "USER"
TERM = "TERM"
SHELL = "SHELL"
) )
const ( const (
CTX_SHY = "ctx_shy" CTX_SHY = "ctx_shy"
@ -131,9 +139,9 @@ const (
CTX_OPS = "ctx_ops" CTX_OPS = "ctx_ops"
CTX_POD = "ctx_pod" CTX_POD = "ctx_pod"
CTX_ARG = "ctx_arg" 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_USER = "ctx_user"
CTX_SHARE = "ctx_share" CTX_SHARE = "ctx_share"
CTX_RIVER = "ctx_river" CTX_RIVER = "ctx_river"
@ -141,37 +149,37 @@ const (
MAKE_DOMAIN = "make.domain" 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 ( const (
HOSTNAME = "hostname" HOSTNAME = "hostname"
PATHNAME = "pathname" PATHNAME = "pathname"
USERNAME = "username" USERNAME = "username"
) )
const ( const (
MAXPROCS = "maxprocs"
IFCONFIG = "ifconfig" IFCONFIG = "ifconfig"
HOSTINFO = "hostinfo" HOSTINFO = "hostinfo"
USERINFO = "userinfo" USERINFO = "userinfo"
PROCINFO = "procinfo" PROCINFO = "procinfo"
PROCKILL = "prockill" PROCKILL = "prockill"
BOOTINFO = "bootinfo"
DISKINFO = "diskinfo" DISKINFO = "diskinfo"
BOOTINFO = "bootinfo"
MAXPROCS = "maxprocs"
) )
const RUNTIME = "runtime" const RUNTIME = "runtime"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
RUNTIME: {Name: RUNTIME, Help: "运行环境", Value: kit.Dict()}, RUNTIME: {Name: "runtime info=ifconfig,hostinfo,hostname,userinfo,procinfo,diskinfo,bootinfo,api,cli,cmd,env auto", Help: "运行环境", Actions: ice.Actions{
}, Commands: ice.Commands{
RUNTIME: {Name: "runtime info=ifconfig,hostinfo,hostname,userinfo,procinfo,bootinfo,diskinfo,env,file,route auto", Help: "运行环境", Actions: ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
m.Cmd(RUNTIME, MAXPROCS, "1") cs := m.Target().Configs
_runtime_init(m) if _, ok := cs[RUNTIME]; !ok {
}}, cs[RUNTIME] = &ice.Config{Value: kit.Dict()}
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))))
} }
m.Echo("%d", runtime.GOMAXPROCS(0)) _runtime_init(m)
}}, }},
IFCONFIG: {Name: "ifconfig", Help: "网卡配置", Hand: func(m *ice.Message, arg ...string) { IFCONFIG: {Name: "ifconfig", Help: "网卡配置", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy("tcp.host") m.Cmdy("tcp.host")
@ -193,13 +201,37 @@ func init() {
m.StatusTimeCount() m.StatusTimeCount()
}}, }},
PROCKILL: {Name: "prockill", Help: "结束进程", Hand: func(m *ice.Message, arg ...string) { 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() m.ProcessRefresh30ms()
}}, }},
DISKINFO: {Name: "diskinfo", Help: "磁盘信息", Hand: func(m *ice.Message, arg ...string) { DISKINFO: {Name: "diskinfo", Help: "磁盘信息", Hand: func(m *ice.Message, arg ...string) {
_runtime_diskinfo(m) _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() { for _, v := range os.Environ() {
ls := strings.SplitN(v, "=", 2) ls := strings.SplitN(v, "=", 2)
m.Push(mdb.NAME, ls[0]) m.Push(mdb.NAME, ls[0])
@ -207,22 +239,6 @@ func init() {
} }
m.StatusTimeCount() 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) { MAKE_DOMAIN: {Name: "make.domain", Help: "编译主机", Hand: func(m *ice.Message, arg ...string) {
if os.Getenv(CTX_DEV) == "" || os.Getenv(CTX_POD) == "" { if os.Getenv(CTX_DEV) == "" || os.Getenv(CTX_POD) == "" {
m.Echo(m.Conf(RUNTIME, MAKE_DOMAIN)) m.Echo(m.Conf(RUNTIME, MAKE_DOMAIN))
@ -234,8 +250,7 @@ func init() {
if len(arg) > 0 && arg[0] == BOOTINFO { if len(arg) > 0 && arg[0] == BOOTINFO {
arg = arg[1:] arg = arg[1:]
} }
m.Cmdy(ctx.CONFIG, RUNTIME, arg) m.Cmdy(ctx.CONFIG, RUNTIME, arg).DisplayStoryJSON()
m.DisplayStoryJSON()
}}, }},
}}) })
} }

View File

@ -12,43 +12,38 @@ import (
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
"shylinux.com/x/toolkits/file"
) )
func _system_cmd(m *ice.Message, arg ...string) *exec.Cmd { func _system_cmd(m *ice.Message, arg ...string) *exec.Cmd {
// 定制目录
if text := kit.ReadFile(ice.ETC_PATH); len(text) > 0 { if text := kit.ReadFile(ice.ETC_PATH); len(text) > 0 {
if file := _system_find(m, arg[0], strings.Split(text, ice.NL)...); file != "" { if file := _system_find(m, arg[0], strings.Split(text, ice.NL)...); file != "" {
m.Debug("cmd: %v", file) m.Log_SELECT("etc path cmd", file)
arg[0] = file arg[0] = file // 配置目录
} }
} }
// 环境变量
env := kit.Simple(m.Optionv(CMD_ENV)) env := kit.Simple(m.Optionv(CMD_ENV))
for i := 0; i < len(env)-1; i += 2 { for i := 0; i < len(env)-1; i += 2 {
if env[i] == PATH { if env[i] == PATH {
if file := _system_find(m, arg[0], strings.Split(env[i+1], ice.DF)...); file != "" { if file := _system_find(m, arg[0], strings.Split(env[i+1], ice.DF)...); file != "" {
m.Debug("cmd: %v", file) m.Log_SELECT("env path cmd", file)
arg[0] = file arg[0] = file // 环境变量
} }
} }
} }
// 自动安装
if _system_find(m, arg[0]) == "" { if _system_find(m, arg[0]) == "" {
if cmds := m.Cmd(MIRRORS, arg[0]).Append("cmd"); cmds != "" { m.Cmd(MIRRORS, CMD, arg[0])
m.Cmd(kit.Split(cmds)) if file := _system_find(m, arg[0]); file != "" {
if file := _system_find(m, arg[0]); file != "" { m.Log_SELECT("mirrors cmd", file)
m.Debug("cmd: %v", file) arg[0] = file // 软件镜像
arg[0] = file
}
} }
} }
cmd := exec.Command(arg[0], arg[1:]...) cmd := exec.Command(arg[0], arg[1:]...)
// 运行目录 // 运行目录
if cmd.Dir = m.Option(CMD_DIR); len(cmd.Dir) > 0 { if cmd.Dir = m.Option(CMD_DIR); len(cmd.Dir) > 0 {
if m.Log_EXPORT(CMD_DIR, cmd.Dir); !kit.FileExists(cmd.Dir) { 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 return cmd
} }
func _system_out(m *ice.Message, out string) io.Writer { 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 { if w, ok := m.Optionv(out).(io.Writer); ok {
return w return w
} else if m.Option(out) == "" { } else if m.Option(out) == "" {
return nil 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.Log_EXPORT(out, p)
m.Optionv(out, f) m.Optionv(out, f)
return f return f
@ -95,20 +88,18 @@ func _system_find(m *ice.Message, bin string, dir ...string) string {
return "" return ""
} }
func _system_exec(m *ice.Message, cmd *exec.Cmd) { func _system_exec(m *ice.Message, cmd *exec.Cmd) {
// 输入流
if r, ok := m.Optionv(CMD_INPUT).(io.Reader); ok { 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 { 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 { if w := _system_out(m, CMD_ERRPUT); w != nil {
cmd.Stderr = w cmd.Stderr = w
} }
} else { } else {
out := bytes.NewBuffer(make([]byte, 0, ice.MOD_BUFS)) out := bytes.NewBuffer(make([]byte, 0, ice.MOD_BUFS))
err := 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() { defer func() {
m.Push(CMD_OUT, out.String()) m.Push(CMD_OUT, out.String())
m.Push(CMD_ERR, err.String()) m.Push(CMD_ERR, err.String())
@ -116,7 +107,6 @@ func _system_exec(m *ice.Message, cmd *exec.Cmd) {
m.SetAppend() 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())) 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 ( const (
CMD_DIR = "cmd_dir" CMD_DIR = "cmd_dir"
@ -145,16 +125,14 @@ const (
CMD_OUTPUT = "cmd_output" CMD_OUTPUT = "cmd_output"
CMD_ERRPUT = "cmd_errput" CMD_ERRPUT = "cmd_errput"
CMD_OUT = "cmd_out"
CMD_ERR = "cmd_err" CMD_ERR = "cmd_err"
CMD_OUT = "cmd_out"
) )
const SYSTEM = "system" const SYSTEM = "system"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
SYSTEM: {Name: SYSTEM, Help: "系统命令", Value: kit.Data(mdb.FIELD, "time,id,cmd")},
}, Commands: ice.Commands{
SYSTEM: {Name: "system cmd run", Help: "系统命令", Actions: ice.Actions{ SYSTEM: {Name: "system cmd run", Help: "系统命令", Actions: ice.Actions{
nfs.FIND: {Name: "find", Help: "查找", Hand: func(m *ice.Message, arg ...string) { nfs.FIND: {Name: "find", Help: "查找", Hand: func(m *ice.Message, arg ...string) {
m.Echo(_system_find(m, arg[0], arg[1:]...)) m.Echo(_system_find(m, arg[0], arg[1:]...))
@ -168,37 +146,28 @@ func init() {
m.Cmdy(nfs.CAT, ice.ETC_PATH) m.Cmdy(nfs.CAT, ice.ETC_PATH)
}}, }},
}, Hand: func(m *ice.Message, arg ...string) { }, 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 { if len(arg) == 1 {
arg = kit.Split(arg[0]) 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...)) _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) { 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...)
} }

View File

@ -12,7 +12,7 @@ import (
) )
func _command_list(m *ice.Message, name string) { 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) { switch kit.Ext(name) {
case nfs.JS: case nfs.JS:
m.Push(DISPLAY, ice.FileURI(name)) m.Push(DISPLAY, ice.FileURI(name))
@ -22,8 +22,8 @@ func _command_list(m *ice.Message, name string) {
name = ice.GetFileCmd(name) name = ice.GetFileCmd(name)
default: default:
if file, msg := name, m.Cmd(mdb.RENDER, kit.Ext(name)); msg.Length() > 0 { if msg := m.Cmd(mdb.RENDER, kit.Ext(name)); msg.Length() > 0 {
m.Push(ARGS, kit.Format(kit.List(file))) m.Push(ARGS, kit.Format(kit.List(name)))
name = kit.Keys(msg.Append(mdb.TEXT), msg.Append(mdb.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), kit.SimpleKV("", s.Cap(ice.CTX_FOLLOW), cmd.Name, cmd.Help),
CONTEXT, s.Cap(ice.CTX_FOLLOW), COMMAND, key, CONTEXT, s.Cap(ice.CTX_FOLLOW), COMMAND, key,
INDEX, kit.Keys(s.Cap(ice.CTX_FOLLOW), 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 { func CmdAction(args ...ice.Any) ice.Actions {
return ice.Actions{ice.CTX_INIT: mdb.AutoConfig(args...), return ice.Actions{ice.CTX_INIT: mdb.AutoConfig(args...),
COMMAND: {Name: "command", Help: "命令", Hand: func(m *ice.Message, arg ...string) { 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)
}
}},
}})
}

View File

@ -2,7 +2,6 @@ package ctx
import ( import (
"encoding/json" "encoding/json"
"os"
"path" "path"
"strings" "strings"
@ -10,23 +9,12 @@ import (
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits" 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) { func _config_save(m *ice.Message, name string, arg ...string) {
name = path.Join(m.Config(nfs.PATH), name) name = path.Join(ice.VAR_CONF, name)
if f, p, e := kit.Create(name); m.Assert(e) { if f, p, e := miss.CreateFile(name); m.Assert(e) {
defer f.Close() defer f.Close()
msg := m.Spawn(m.Source()) 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 s, e := json.MarshalIndent(data, "", " "); m.Assert(e) {
if n, e := f.Write(s); m.Assert(e) { if _, e := f.Write(s); m.Assert(e) {
m.Log_EXPORT(CONFIG, name, nfs.FILE, p, nfs.SIZE, n) // m.Log_EXPORT(CONFIG, name, nfs.FILE, p, nfs.SIZE, n)
} }
} }
m.Echo(p) m.Echo(p)
} }
} }
func _config_load(m *ice.Message, name string, arg ...string) { func _config_load(m *ice.Message, name string, arg ...string) {
name = path.Join(m.Config(nfs.PATH), name) name = path.Join(ice.VAR_CONF, name)
if f, e := os.Open(name); e == nil { if f, e := miss.OpenFile(name); e == nil {
defer f.Close() defer f.Close()
msg := m.Spawn(m.Source()) msg := m.Spawn(m.Source())
@ -58,7 +46,7 @@ func _config_load(m *ice.Message, name string, arg ...string) {
// 加载配置 // 加载配置
for k, v := range data { for k, v := range data {
msg.Search(k, func(p *ice.Context, s *ice.Context, key string) { 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 { if s.Configs[key] == nil {
s.Configs[key] = &ice.Config{} 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))) m.Echo(kit.Formats(msg.Confv(key)))
} }
} }
func _config_rich(m *ice.Message, key string, sub string, arg ...string) { func _config_list(m *ice.Message) {
m.Rich(key, sub, kit.Data(arg)) for k, v := range m.Source().Configs {
} if k[0] == '/' || k[0] == '_' {
func _config_grow(m *ice.Message, key string, sub string, arg ...string) { continue // 内部配置
m.Grow(key, sub, kit.Dict(arg)) }
m.Push(mdb.KEY, k)
m.Push(mdb.NAME, v.Name)
m.Push(mdb.VALUE, kit.Format(v.Value))
}
m.Sort(mdb.KEY)
} }
const ( const (
@ -99,9 +93,7 @@ const (
const CONFIG = "config" const CONFIG = "config"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
CONFIG: {Name: CONFIG, Help: "配置", Value: kit.Data(nfs.PATH, ice.VAR_CONF)},
}, Commands: ice.Commands{
CONFIG: {Name: "config key auto reset", Help: "配置", Actions: ice.Actions{ CONFIG: {Name: "config key auto reset", Help: "配置", Actions: ice.Actions{
SAVE: {Name: "save", Help: "保存", Hand: func(m *ice.Message, arg ...string) { SAVE: {Name: "save", Help: "保存", Hand: func(m *ice.Message, arg ...string) {
_config_save(m, arg[0], arg[1:]...) _config_save(m, arg[0], arg[1:]...)
@ -110,10 +102,10 @@ func init() {
_config_load(m, arg[0], arg[1:]...) _config_load(m, arg[0], arg[1:]...)
}}, }},
RICH: {Name: "rich", Help: "富有", Hand: func(m *ice.Message, arg ...string) { 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) { 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": {Name: "list", Help: "列表", Hand: func(m *ice.Message, arg ...string) {
list := []ice.Any{} list := []ice.Any{}
@ -134,5 +126,5 @@ func init() {
_config_make(m, arg[0], arg[1:]...) _config_make(m, arg[0], arg[1:]...)
m.DisplayStoryJSON() m.DisplayStoryJSON()
}}, }},
}}) })
} }

View File

@ -5,6 +5,7 @@ import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits" 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) 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" const CONTEXT = "context"
func init() { 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{ 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) { "spide": {Name: "spide", Help: "架构图", Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 || arg[1] == CONTEXT { // 模块列表 if len(arg) == 0 || arg[1] == CONTEXT { // 模块列表
m.Cmdy(CONTEXT, kit.Select(ice.ICE, arg, 0), 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]) { // 命令列表 } else if index := kit.Keys(arg[1]); strings.HasSuffix(index, arg[2]) { // 命令列表
m.Cmdy(CONTEXT, index, COMMAND).Tables(func(value ice.Maps) { m.Cmdy(CONTEXT, index, COMMAND).Tables(func(value ice.Maps) {
m.Push("file", arg[1]) m.Push(nfs.FILE, arg[1])
}) })
} else { // 命令详情 } 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
} }

View File

@ -12,7 +12,7 @@ import (
const MESSAGE = "message" const MESSAGE = "message"
func init() { func init() {
Index.Merge(&ice.Context{Commands: ice.Commands{ Index.MergeCommands(ice.Commands{
MESSAGE: {Name: "message", Help: "消息", Hand: func(m *ice.Message, arg ...string) { MESSAGE: {Name: "message", Help: "消息", Hand: func(m *ice.Message, arg ...string) {
t := reflect.TypeOf(m) t := reflect.TypeOf(m)
for i := 0; i < t.NumMethod(); i++ { for i := 0; i < t.NumMethod(); i++ {
@ -22,5 +22,5 @@ func init() {
m.Push(mdb.TEXT, strings.Split(p, ice.ICEBERGS+"/")[1]) m.Push(mdb.TEXT, strings.Split(p, ice.ICEBERGS+"/")[1])
} }
}}, }},
}}) })
} }

View File

@ -6,33 +6,19 @@ import (
kit "shylinux.com/x/toolkits" 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" const EVENT = "event"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
EVENT: {Name: EVENT, Help: "事件流", Value: kit.Data(mdb.SHORT, EVENT, mdb.FIELD, "time,id,cmd")}, EVENT: {Name: "event event id auto listen happen", Help: "事件流", Actions: ice.MergeAction(ice.Actions{
}, Commands: ice.Commands{
EVENT: {Name: "event event id auto listen", Help: "事件流", Actions: ice.MergeAction(ice.Actions{
LISTEN: {Name: "listen event cmd", Help: "监听", Hand: func(m *ice.Message, arg ...string) { 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) { 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) { }, mdb.ZoneAction(mdb.SHORT, EVENT, mdb.FIELD, "time,id,cmd"))},
if mdb.ZoneSelect(m, arg...); len(arg) == 0 { })
m.PushAction(HAPPEN, mdb.REMOVE)
}
}},
}})
} }

View File

@ -2,6 +2,7 @@ package gdb
import ( import (
"os" "os"
"strings"
"time" "time"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
@ -10,48 +11,56 @@ import (
type Frame struct { type Frame struct {
s chan os.Signal s chan os.Signal
t time.Duration
e chan bool
} }
func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server { func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server {
return &Frame{} return &Frame{}
} }
func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server { 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.s = make(chan os.Signal, ice.MOD_CHAN)
f.e = make(chan bool, 1)
return f return f
} }
func (f *Frame) Start(m *ice.Message, arg ...string) bool { 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 { for {
select { select {
case <-f.e: case <-time.Tick(t):
return true if enable {
m.Cmd(TIMER, HAPPEN)
}
// case <-time.Tick(f.t): case s, ok := <-f.s:
// // m.Cmd(TIMER, ACTION) if !ok {
return true
case s := <-f.s: }
m.Cmd(SIGNAL, HAPPEN, SIGNAL, s) m.Cmd(SIGNAL, HAPPEN, SIGNAL, s)
} }
} }
return true return true
} }
func (f *Frame) Close(m *ice.Message, arg ...string) bool { func (f *Frame) Close(m *ice.Message, arg ...string) bool {
f.e <- true close(f.s)
return true return true
} }
const GDB = "gdb" const GDB = "gdb"
var Index = &ice.Context{Name: GDB, Help: "事件模块", Commands: ice.Commands{ var Index = &ice.Context{Name: GDB, Help: "事件模块", Commands: ice.Commands{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { m.Load(TIMER, ROUTINE) }},
m.Load(TIMER) ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) { m.Save(TIMER, ROUTINE) }},
}},
ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) {
m.Save(TIMER)
}},
}} }}
func init() { ice.Index.Register(Index, &Frame{}, ROUTINE, SIGNAL, EVENT, TIMER) } func init() { ice.Index.Register(Index, &Frame{}, SIGNAL, TIMER, EVENT, ROUTINE) }

View File

@ -4,31 +4,43 @@ import (
"path" "path"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
"shylinux.com/x/toolkits/logs"
) )
const ROUTINE = "routine" const ROUTINE = "routine"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
ROUTINE: {Name: ROUTINE, Help: "协程池", Value: kit.Data(mdb.SHORT, "time,hash,status,fileline")},
}, Commands: ice.Commands{
ROUTINE: {Name: "routine hash auto prunes", Help: "协程池", Actions: ice.MergeAction(ice.Actions{ ROUTINE: {Name: "routine hash auto prunes", Help: "协程池", Actions: ice.MergeAction(ice.Actions{
mdb.CREATE: {Name: "create fileline status", Help: "创建"}, mdb.CREATE: {Name: "create name", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) { m.Go(func() {
m.OptionFields(m.Config(mdb.SHORT)) cb := m.OptionCB(ROUTINE)
m.Cmdy(mdb.PRUNES, ROUTINE, "", mdb.HASH, cli.STATUS, cli.STOP) h := mdb.HashCreate(m, m.OptionSimple(mdb.NAME), mdb.STATUS, START, ice.CMD, logs.FileLine(cb, 100)).Result()
m.Cmdy(mdb.PRUNES, ROUTINE, "", mdb.HASH, cli.STATUS, cli.ERROR) 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) { "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...) 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.HashActionStatus(mdb.FIELD, "time,hash,name,status,cmd", mdb.ACTION, "inner"))},
mdb.HashSelect(m, arg...) })
m.PushAction("inner", mdb.REMOVE)
}},
}})
} }

View File

@ -1,23 +1,22 @@
package gdb package gdb
import ( import (
"fmt"
"os" "os"
"os/signal" "os/signal"
"path"
"syscall" "syscall"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits" 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) { func _signal_listen(m *ice.Message, s int, arg ...string) {
if f, ok := m.Target().Server().(*Frame); ok { if f, ok := m.Target().Server().(*Frame); ok {
m.Cmdy(mdb.INSERT, SIGNAL, "", mdb.HASH, arg)
signal.Notify(f.s, syscall.Signal(s)) signal.Notify(f.s, syscall.Signal(s))
mdb.HashCreate(m, SIGNAL, s, arg)
} }
} }
func _signal_action(m *ice.Message, arg ...string) { 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])) 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()) { func SignalNotify(m *ice.Message, sig int, cb func()) {
ch := make(chan os.Signal) 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)
}},
}})
}

View File

@ -4,62 +4,43 @@ import (
"time" "time"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
func _timer_action(m *ice.Message, arg ...string) { func _timer_action(m *ice.Message, now time.Time, arg ...string) {
now := time.Now().UnixNano() mdb.HashSelects(m).Tables(func(value ice.Maps) {
m.OptionFields(m.Config(mdb.FIELD)) if value[mdb.COUNT] == "0" {
m.Richs(TIMER, "", mdb.FOREACH, func(key string, value ice.Map) {
if value = kit.GetMeta(value); value[cli.STATUS] == cli.STOP {
return return
} }
if kit.Time(value[mdb.TIME]) > kit.Int64(now) {
order := kit.Int(value[ORDER]) return
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])
}
} }
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 ( const (
DELAY = "delay" DELAY = "delay"
INTERVAL = "interval" INTERVAL = "interval"
ORDER = "order"
NEXT = "next"
TICK = "tick" TICK = "tick"
) )
const TIMER = "timer" const TIMER = "timer"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
TIMER: {Name: TIMER, Help: "定时器", Value: kit.Data( TIMER: {Name: "timer hash auto create prunes", Help: "定时器", Actions: ice.MergeAction(ice.Actions{
mdb.FIELD, "time,hash,delay,interval,order,next,cmd", TICK, "1s", mdb.CREATE: {Name: "create name=hi delay=10ms interval=10s count=3 cmd=runtime", Help: "创建"},
)},
}, 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)
}},
mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) { mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
m.OptionFields(m.Config(mdb.FIELD)) mdb.HashPrunesValue(m, mdb.COUNT, "0")
m.Cmdy(mdb.PRUNES, TIMER, "", mdb.HASH, ORDER, 0)
}}, }},
HAPPEN: {Name: "happen", Help: "执行", Hand: func(m *ice.Message, arg ...string) { 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) { RESTART: {Name: "restart count=3", Help: "重启", Hand: func(m *ice.Message, arg ...string) {
m.Fields(len(arg), m.Config(mdb.FIELD), "time,id,res") mdb.HashModify(m, m.OptionSimple(mdb.HashShort(m)), arg)
mdb.ZoneSelect(m, arg...) }},
}}, }, mdb.HashAction(mdb.FIELD, "time,hash,name,delay,interval,count,cmd", TICK, "10s"))},
}}) })
} }

View File

@ -385,9 +385,7 @@ const (
const MATRIX = "matrix" const MATRIX = "matrix"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
MATRIX: {Name: MATRIX, Help: "魔方矩阵", Value: kit.Data()},
}, Commands: ice.Commands{
MATRIX: {Name: "matrix hash npage text auto", Help: "魔方矩阵", Actions: ice.Actions{ MATRIX: {Name: "matrix hash npage text auto", Help: "魔方矩阵", Actions: ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
// _lex_load(m.Load()) // _lex_load(m.Load())
@ -399,7 +397,7 @@ func init() {
case func(string, *Matrix): case func(string, *Matrix):
cb(h, mat) cb(h, mat)
default: default:
m.Error(true, ice.ErrNotImplement) m.ErrorNotImplement(cb)
} }
m.Echo(h) m.Echo(h)
}}, }},
@ -538,5 +536,5 @@ func init() {
m.Push("word", string(word)) m.Push("word", string(word))
}) })
}}, }},
}}) })
} }

View File

@ -1,3 +1,4 @@
package lex package lex
const REGEXP = "regexp" const REGEXP = "regexp"
const PREFIX = "prefix"

View File

@ -4,6 +4,7 @@ import (
"strings" "strings"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits" 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 { func _split_list(m *ice.Message, file string, arg ...string) ice.Map {
const DEEP = "_deep" const DEEP = "_deep"
stack, deep := []int{}, 0 stack, deep := []int{}, 0
list := kit.List(kit.Data(DEEP, -1)) list, line := kit.List(kit.Data(DEEP, -1)), ""
line := ""
m.Cmd(nfs.CAT, file, func(text string) { m.Cmd(nfs.CAT, file, func(text string) {
if strings.HasPrefix(strings.TrimSpace(text), "# ") {
return // 注释
}
if strings.TrimSpace(text) == "" { if strings.TrimSpace(text) == "" {
return // 空行 return // 空行
} }
if line += text; strings.Count(text, "`")%2 == 1 { if line += text; strings.Count(text, "`")%2 == 1 {
return // 多行 return // 多行
} }
if strings.HasPrefix(strings.TrimSpace(text), "# ") {
return // 注释
}
stack, deep = _split_deep(stack, text) stack, deep = _split_deep(stack, text)
data := kit.Data(DEEP, deep) 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) ls = cb(ls, data)
case func([]string): case func([]string):
cb(ls) cb(ls)
case nil:
default: 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-- { for i := len(list) - 1; i >= 0; i-- {
if deep > kit.Int(kit.Value(list[i], kit.Keym(DEEP))) { 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) list = append(list, data)
break break
} }
@ -90,9 +91,6 @@ func _split_list(m *ice.Message, file string, arg ...string) ice.Map {
}) })
return list[0].(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 ( const (
SPLIT_SPACE = "split.space" SPLIT_SPACE = "split.space"
@ -103,17 +101,17 @@ const (
const SPLIT = "split" const SPLIT = "split"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
SPLIT: {Name: "split", Help: "解析", Value: kit.Data()}, SPLIT: {Name: "split path key auto", Help: "分词", Hand: func(m *ice.Message, arg ...string) {
}, Commands: 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) { if len(arg) == 0 || strings.HasSuffix(arg[0], ice.PS) {
m.Cmdy(nfs.DIR, arg) m.Cmdy(nfs.DIR, arg)
return return
} }
m.Echo(kit.Format(_split_list(m, arg[0], kit.Split(kit.Join(arg[1:]))...))).DisplayStoryJSON()
m.Echo(kit.Format(_split_list(m, arg[0], kit.Split(kit.Join(arg[1:]))...)))
m.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)
} }

View File

@ -2,6 +2,7 @@ package log
import ( import (
"bufio" "bufio"
"os"
"path" "path"
"strings" "strings"
@ -9,7 +10,7 @@ import (
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
log "shylinux.com/x/toolkits/logs" "shylinux.com/x/toolkits/logs"
) )
type Log struct { type Log struct {
@ -25,6 +26,13 @@ func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server
return &Frame{} return &Frame{}
} }
func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server { 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) f.p = make(chan *Log, ice.MOD_BUFS)
ice.Info.Log = func(msg *ice.Message, p, l, s string) { ice.Info.Log = func(msg *ice.Message, p, l, s string) {
f.p <- &Log{m: msg, p: p, l: l, s: s} 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 { select {
case l, ok := <-f.p: case l, ok := <-f.p:
if !ok { if !ok {
break return true
} }
file := kit.Select(BENCH, m.Conf(SHOW, kit.Keys(l.l, FILE))) 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()}, SHOW: {Name: SHOW, Help: "日志分流", Value: kit.Dict()},
}, Commands: ice.Commands{ }, Commands: ice.Commands{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
if log.LogDisable {
return // 禁用日志
}
if !strings.Contains(ice.Getenv("ctx_daemon"), "log") { if !strings.Contains(ice.Getenv("ctx_daemon"), "log") {
return // 没有日志 return // 没有日志
} }
@ -140,7 +145,7 @@ var Index = &ice.Context{Name: "log", Help: "日志模块", Configs: ice.Configs
m.Conf(SHOW, kit.Keys(k, FILE), key) 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)) m.Cap(ice.CTX_STREAM, path.Base(p))
value[FILE] = bufio.NewWriter(f) value[FILE] = bufio.NewWriter(f)
m.Log_CREATE(nfs.FILE, p) m.Log_CREATE(nfs.FILE, p)

View File

@ -2,31 +2,10 @@ package mdb
import ( import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
kit "shylinux.com/x/toolkits"
) )
const ENGINE = "engine" const ENGINE = "engine"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{ENGINE: {Name: "engine type name text auto", Help: "引擎", Actions: RenderAction()}})
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)
}
}},
}})
} }

View File

@ -2,27 +2,34 @@ package mdb
import ( import (
"encoding/json" "encoding/json"
"os"
"path" "path"
"strings"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
"shylinux.com/x/toolkits/miss"
) )
func _hash_fields(m *ice.Message) []string { 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) { func _hash_inputs(m *ice.Message, prefix, chain string, field, value string) {
defer m.RLock(prefix, chain)() defer m.RLock(prefix, chain)()
list := map[string]int{} list := map[string]int{}
m.Richs(prefix, chain, FOREACH, func(key string, val ice.Map) { m.Richs(prefix, chain, FOREACH, func(val Map) {
if val = kit.GetMeta(val); kit.Format(val[COUNT]) != "" { val = kit.GetMeta(val)
list[kit.Format(val[field])] = kit.Int(val[COUNT]) list[kit.Format(val[field])] += kit.Int(kit.Select("1", val[COUNT]))
} else {
list[kit.Format(val[field])]++
}
}) })
for k, i := range list { for k, i := range list {
m.Push(field, k) m.Push(field, k)
@ -30,18 +37,30 @@ func _hash_inputs(m *ice.Message, prefix, chain string, field, value string) {
} }
m.SortIntR(COUNT) 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)() defer m.Lock(prefix, chain)()
if m.Option(ice.MSG_DOMAIN) != "" { if value := m.Confm(prefix, kit.Keys(HASH, arg[1])); value != nil {
m.Conf(prefix, kit.Keys(chain, kit.Keym(SHORT)), m.Conf(prefix, kit.Keym(SHORT))) 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]) m.Log_INSERT(KEY, path.Join(prefix, chain), arg[0], arg[1])
if expire := m.Conf(prefix, kit.Keys(chain, kit.Keym(EXPIRE))); expire != "" { if expire := m.Conf(prefix, kit.Keys(chain, kit.Keym(EXPIRE))); expire != "" {
arg = kit.Simple(TIME, m.Time(expire), arg) arg = kit.Simple(TIME, m.Time(expire), arg)
} }
if m.Option(ice.MSG_DOMAIN) != "" {
m.Echo(m.Rich(prefix, chain, kit.Data(arg))) 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) { func _hash_delete(m *ice.Message, prefix, chain, field, value string) {
defer m.Lock(prefix, chain)() defer m.Lock(prefix, chain)()
@ -49,7 +68,7 @@ func _hash_delete(m *ice.Message, prefix, chain, field, value string) {
if field != HASH { if field != HASH {
field, value = HASH, kit.Select(kit.Hashs(value), m.Option(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.Log_DELETE(KEY, path.Join(prefix, chain), field, value, VALUE, kit.Format(val))
m.Conf(prefix, kit.Keys(chain, HASH, key), "") 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) { func _hash_modify(m *ice.Message, prefix, chain string, field, value string, arg ...string) {
defer m.Lock(prefix, chain)() defer m.Lock(prefix, chain)()
m.Richs(prefix, chain, value, func(key string, val ice.Map) { m.Richs(prefix, chain, value, func(key string, val Map) {
val = kit.GetMeta(val)
m.Log_MODIFY(KEY, path.Join(prefix, chain), field, value, arg) m.Log_MODIFY(KEY, path.Join(prefix, chain), field, value, arg)
for i := 0; i < len(arg); i += 2 { _mdb_modify(m, val, field, arg...)
if arg[i] == field {
continue
}
kit.Value(val, arg[i], kit.Select("", arg, i+1))
}
}) })
} }
func _hash_select(m *ice.Message, prefix, chain, field, value string) { 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 value = RANDOMS
} }
fields := _hash_fields(m) fields := _hash_fields(m)
m.Richs(prefix, chain, value, func(key string, val ice.Map) { m.Richs(prefix, chain, value, func(key string, value Map) {
switch val = kit.GetMeta(val); cb := m.OptionCB(SELECT).(type) { _mdb_select(m, key, value, fields, nil)
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)
}
}
}) })
if !m.FieldsIsDetail() { if !m.FieldsIsDetail() {
m.SortTimeR(TIME) m.SortTimeR(TIME)
@ -97,9 +99,9 @@ func _hash_prunes(m *ice.Message, prefix, chain string, arg ...string) {
defer m.RLock(prefix, chain)() defer m.RLock(prefix, chain)()
fields := _hash_fields(m) 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) { 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) { if !cb(key, val) {
return 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) { func _hash_export(m *ice.Message, prefix, chain, file string) {
defer m.Lock(prefix, chain)() 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) m.Assert(e)
defer f.Close() 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) { func _hash_import(m *ice.Message, prefix, chain, file string) {
defer m.Lock(prefix, chain)() defer m.Lock(prefix, chain)()
f, e := os.Open(kit.Keys(file, JSON)) f, e := miss.OpenFile(kit.Keys(file, JSON))
if m.Warn(e) { m.Assert(e)
return
}
defer f.Close() defer f.Close()
list := ice.Map{} list := Map{}
m.Assert(json.NewDecoder(f).Decode(&list)) m.Assert(json.NewDecoder(f).Decode(&list))
count := 0 count := 0
@ -157,41 +157,12 @@ func _hash_import(m *ice.Message, prefix, chain, file string) {
m.Echo("%d", count) m.Echo("%d", count)
} }
const (
HASH_FIELD = "time,hash,type,name,text"
)
const HASH = "hash" const HASH = "hash"
func AutoConfig(args ...ice.Any) *ice.Action { func HashAction(args ...Any) ice.Actions {
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 {
return ice.Actions{ice.CTX_INIT: AutoConfig(args...), return ice.Actions{ice.CTX_INIT: AutoConfig(args...),
INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) { HashInputs(m, arg) }}, 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) }}, 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) }}, 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 := HashAction(args...)
list[PRUNES] = &ice.Action{Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) { list[PRUNES] = &ice.Action{Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
m.OptionFields(m.Config(FIELD)) m.OptionFields(m.Config(FIELD))
m.Cmdy(PRUNES, m.PrefixKey(), "", HASH, STATUS, "error") m.Cmdy(PRUNES, m.PrefixKey(), "", HASH, STATUS, ice.ERROR)
m.Cmdy(PRUNES, m.PrefixKey(), "", HASH, STATUS, "close") 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 return list
} }
func HashInputs(m *ice.Message, arg ...ice.Any) *ice.Message { func HashShort(m *ice.Message) string {
return m.Cmdy(INPUTS, m.PrefixKey(), "", HASH, kit.Simple(arg...)) return kit.Select(HASH, m.Config(SHORT), m.Config(SHORT) != UNIQ)
} }
func HashCreate(m *ice.Message, arg ...ice.Any) *ice.Message { func HashField(m *ice.Message) string { return kit.Select(HASH_FIELD, m.Config(FIELD)) }
field := m.Config(FIELD) func HashArgs(m *ice.Message, arg ...Any) []string {
args := kit.Simple(arg...) return _mdb_args(m, HashField(m), 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 HashRemove(m *ice.Message, arg ...ice.Any) *ice.Message { func HashInputs(m *ice.Message, arg ...Any) *ice.Message {
m.OptionFields(m.Config(FIELD)) return m.Cmdy(INPUTS, m.PrefixKey(), "", HASH, HashArgs(m, arg))
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 HashModify(m *ice.Message, arg ...ice.Any) *ice.Message { func HashCreate(m *ice.Message, arg ...Any) *ice.Message {
field := m.Config(FIELD) return m.Cmdy(INSERT, m.PrefixKey(), "", HASH, HashArgs(m, arg...))
args := kit.Simple(arg...) }
for i := 0; i < len(args); i += 2 { func HashRemove(m *ice.Message, arg ...Any) *ice.Message {
if !strings.Contains(field, args[i]) { return m.Cmdy(DELETE, m.PrefixKey(), "", HASH, m.OptionSimple(HashShort(m)), arg)
args[i] = kit.Keys("extra", args[i]) }
} func HashModify(m *ice.Message, arg ...Any) *ice.Message {
} return m.Cmd(MODIFY, m.PrefixKey(), "", HASH, m.OptionSimple(HashShort(m)), HashArgs(m, arg...))
return m.Cmd(MODIFY, m.PrefixKey(), "", HASH, args)
} }
func HashSelect(m *ice.Message, arg ...string) *ice.Message { func HashSelect(m *ice.Message, arg ...string) *ice.Message {
m.Fields(len(arg), m.Config(FIELD)) m.Fields(len(kit.Slice(arg, 0, 1)), HashField(m))
m.Cmdy(SELECT, m.PrefixKey(), "", HASH, m.Config(SHORT), arg) m.Cmdy(SELECT, m.PrefixKey(), "", HASH, HashShort(m), arg)
m.PushAction(m.Config("action"), REMOVE) if m.PushAction(m.Config(ACTION), REMOVE); !m.FieldsIsDetail() {
m.StatusTimeCount() return m.StatusTimeCount()
return m } else {
} return m.StatusTime()
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))
} }
}
func HashPrunes(m *ice.Message, cb func(Maps) bool) *ice.Message {
expire := kit.Time(kit.Select(m.Time("-72h"), m.Option(EXPIRE))) expire := kit.Time(kit.Select(m.Time("-72h"), m.Option(EXPIRE)))
m.Cmd(m.CommandKey()).Tables(func(value ice.Maps) { m.Cmd(m.CommandKey()).Tables(func(value Maps) {
if kit.Time(value[TIME]) > expire { if cb != nil && !cb(value) || kit.Time(value[TIME]) < expire {
return 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 return m
} }
func HashExport(m *ice.Message, arg ...ice.Any) *ice.Message { func HashExport(m *ice.Message, arg ...Any) *ice.Message {
m.OptionFields(m.Config(FIELD)) return m.Cmdy(EXPORT, m.PrefixKey(), "", HASH, arg)
return m.Cmd(EXPORT, m.PrefixKey(), "", HASH, kit.Simple(arg...))
} }
func HashImport(m *ice.Message, arg ...ice.Any) *ice.Message { func HashImport(m *ice.Message, arg ...Any) *ice.Message {
return m.Cmd(IMPORT, m.PrefixKey(), "", HASH, kit.Simple(arg...)) 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()() defer m.Lock()()
p := m.Confv(m.PrefixKey(), kit.Keys(HASH, h, "_cache")) p := m.Confv(m.PrefixKey(), kit.Keys(HASH, h, TARGET))
if pp, ok := p.(ice.Map); ok && len(pp) == 0 { if pp, ok := p.(Map); ok && len(pp) == 0 {
p = nil p = nil
} }
if add != nil && p == nil { if p == nil && add != nil {
p = add() p = add()
m.Confv(m.PrefixKey(), kit.Keys(HASH, h, "_cache"), p) // 添加 m.Confv(m.PrefixKey(), kit.Keys(HASH, h, TARGET), p)
} }
return 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
}

View File

@ -2,24 +2,23 @@ package mdb
import ( import (
"encoding/csv" "encoding/csv"
"os"
"path" "path"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
"shylinux.com/x/toolkits/miss"
) )
func _list_fields(m *ice.Message) []string { 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) { func _list_inputs(m *ice.Message, prefix, chain string, field, value string) {
defer m.RLock(prefix, chain)()
list := map[string]int{} list := map[string]int{}
m.Grows(prefix, chain, "", "", func(index int, val ice.Map) { m.Grows(prefix, chain, "", "", func(val ice.Map) {
if val = kit.GetMeta(val); kit.Format(val[COUNT]) != "" { val = kit.GetMeta(val)
list[kit.Format(val[field])] = kit.Int(val[COUNT]) list[kit.Format(val[field])] += kit.Int(kit.Select("1", val[COUNT]))
} else {
list[kit.Format(val[field])]++
}
}) })
for k, i := range list { for k, i := range list {
m.Push(field, k) m.Push(field, k)
@ -28,43 +27,34 @@ func _list_inputs(m *ice.Message, prefix, chain string, field, value string) {
m.SortIntR(COUNT) m.SortIntR(COUNT)
} }
func _list_insert(m *ice.Message, prefix, chain string, arg ...string) { 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.Log_INSERT(KEY, path.Join(prefix, chain), arg[0], arg[1])
m.Echo("%d", m.Grow(prefix, chain, kit.Dict(arg))) 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) { 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) { 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) m.Log_MODIFY(KEY, path.Join(prefix, chain), field, value, arg)
for i := 0; i < len(arg); i += 2 { _mdb_modify(m, val, field, arg...)
if arg[i] == field {
continue
}
kit.Value(val, arg[i], kit.Select("", arg, i+1))
}
}) })
} }
func _list_select(m *ice.Message, prefix, chain, field, value string) { func _list_select(m *ice.Message, prefix, chain, field, value string) {
defer m.RLock(prefix, chain)()
if value == "" { if value == "" {
field = "" field = ""
} }
fields := _list_fields(m) 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) { m.Grows(prefix, chain, kit.Select(m.Option(ice.CACHE_FIELD), field), kit.Select(m.Option(ice.CACHE_VALUE), value), func(value ice.Map) {
switch val = kit.GetMeta(val); cb := m.OptionCB(SELECT).(type) { _mdb_select(m, "", value, fields, nil)
case func(fields []string, value ice.Map):
cb(fields, val)
default:
if m.OptionFields() == DETAIL {
m.Push(DETAIL, val)
} else {
m.Push("", val, fields)
}
}
}) })
} }
func _list_export(m *ice.Message, prefix, chain, file string) { 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) m.Assert(e)
defer f.Close() defer f.Close()
@ -72,7 +62,7 @@ func _list_export(m *ice.Message, prefix, chain, file string) {
defer w.Flush() defer w.Flush()
count := 0 count := 0
head := kit.Split(m.OptionFields()) head := kit.Split(m.Config(FIELD))
m.Grows(prefix, chain, "", "", func(index int, val ice.Map) { m.Grows(prefix, chain, "", "", func(index int, val ice.Map) {
if val = kit.GetMeta(val); index == 0 { if val = kit.GetMeta(val); index == 0 {
if len(head) == 0 || head[0] == ice.CACHE_DETAIL { // 默认表头 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) m.Echo(p)
} }
func _list_import(m *ice.Message, prefix, chain, file string) { 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) m.Assert(e)
defer f.Close() 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.Log_IMPORT(KEY, kit.Keys(prefix, chain), COUNT, count)
m.Echo("%d", 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" const LIST = "list"
func ListAction(args ...ice.Any) ice.Actions { func ListAction(args ...ice.Any) ice.Actions {
return ice.Actions{ice.CTX_INIT: AutoConfig(args...), return ice.Actions{ice.CTX_INIT: AutoConfig(args...),
INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) { 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) { INSERT: {Name: "insert", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(INSERT, m.PrefixKey(), "", LIST, arg) m.Cmdy(INSERT, m.PrefixKey(), "", LIST, ListArgs(m, arg))
}}, }},
DELETE: {Name: "delete", Help: "删除", Hand: func(m *ice.Message, arg ...string) { DELETE: {Name: "delete", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(DELETE, m.PrefixKey(), "", LIST, m.OptionSimple(ID), arg) m.Cmdy(DELETE, m.PrefixKey(), "", LIST, m.OptionSimple(ID), arg)
}}, }},
MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) { 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) { SELECT: {Name: "select", Help: "列表", Hand: func(m *ice.Message, arg ...string) {
m.Option(ice.CACHE_LIMIT, "-1") ListSelect(m, arg...)
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)
}}, }},
PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) { PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(PRUNES, m.PrefixKey(), "", LIST, arg) 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) { PREV: {Name: "prev", Help: "上一页", Hand: func(m *ice.Message, arg ...string) {
PrevPage(m, m.Config(COUNT), kit.Slice(arg, 1)...) PrevPage(m, m.Config(COUNT), kit.Slice(arg, 1)...)
}}, }},
NEXT: {Name: "next", Help: "下一页", Hand: func(m *ice.Message, arg ...string) { NEXT: {Name: "next", Help: "下一页", Hand: func(m *ice.Message, arg ...string) {
NextPage(m, m.Config(COUNT), kit.Slice(arg, 1)...) NextPageLimit(m, m.Config(COUNT), kit.Slice(arg, 1)...)
}},
SELECT: {Name: "select", Help: "列表", Hand: func(m *ice.Message, arg ...string) {
ListSelect(m, arg...)
}}, }},
} }
} }
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 { func ListSelect(m *ice.Message, arg ...string) *ice.Message {
m.OptionPage(kit.Slice(arg, 1)...) m.OptionPage(kit.Slice(arg, 1)...)
m.Fields(len(kit.Slice(arg, 0, 1)), m.Config(FIELD)) m.Fields(len(kit.Slice(arg, 0, 1)), ListField(m))
m.Cmdy(SELECT, m.PrefixKey(), "", LIST, ID, arg) if m.Cmdy(SELECT, m.PrefixKey(), "", LIST, ID, arg); !m.FieldsIsDetail() {
if !m.FieldsIsDetail() {
m.StatusTimeCountTotal(m.Config(COUNT)) m.StatusTimeCountTotal(m.Config(COUNT))
} else {
m.StatusTime()
} }
return m 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()
}
}

View File

@ -8,26 +8,73 @@ import (
kit "shylinux.com/x/toolkits" 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 { func _file_name(m *ice.Message, arg ...string) string {
if len(arg) > 3 && strings.Contains(arg[3], ice.PS) { if len(arg) > 3 && strings.Contains(arg[3], ice.PS) {
return arg[3] return arg[3]
} }
return path.Join(ice.USR_LOCAL_EXPORT, m.Option(ice.MSG_DOMAIN), path.Join(arg[:2]...), arg[2]) 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 { func _mdb_args(m *ice.Message, field string, arg ...Any) []string {
return kit.Keys(m.Option(ice.MSG_DOMAIN), chain) 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 ( const (
DICT = kit.MDB_DICT DICT = kit.MDB_DICT
META = kit.MDB_META META = kit.MDB_META
UNIQ = kit.MDB_UNIQ
UNIQ = kit.MDB_UNIQ
FOREACH = kit.MDB_FOREACH FOREACH = kit.MDB_FOREACH
RANDOMS = kit.MDB_RANDOMS RANDOMS = kit.MDB_RANDOMS
) )
@ -36,7 +83,6 @@ const (
ID = kit.MDB_ID ID = kit.MDB_ID
KEY = kit.MDB_KEY KEY = kit.MDB_KEY
TIME = kit.MDB_TIME TIME = kit.MDB_TIME
// ZONE = kit.MDB_ZONE
TYPE = kit.MDB_TYPE TYPE = kit.MDB_TYPE
NAME = kit.MDB_NAME NAME = kit.MDB_NAME
TEXT = kit.MDB_TEXT TEXT = kit.MDB_TEXT
@ -71,6 +117,7 @@ const (
const ( const (
DETAIL = "detail" DETAIL = "detail"
RANDOM = "random" RANDOM = "random"
ACTION = "action"
INPUTS = "inputs" INPUTS = "inputs"
CREATE = "create" CREATE = "create"
@ -91,103 +138,70 @@ const (
PREV = "prev" PREV = "prev"
PAGE = "page" PAGE = "page"
OFFEND = "offend" OFFEND = "offend"
JSON = "json"
CSV = "csv"
) )
const ( const (
CACHE_CLEAR_ON_EXIT = "cache.clear.on.exit" 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" const MDB = "mdb"
var Index = &ice.Context{Name: MDB, Help: "数据模块", Commands: ice.Commands{ var Index = &ice.Context{Name: MDB, Help: "数据模块", Commands: ice.Commands{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {}}, ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {}},
ice.CTX_EXIT: {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) { 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": case "index":
m.OptionFields(arg[3]) m.OptionFields(arg[0])
m.Cmdy("command", "search", "command", "", "") m.Cmdy("command", SEARCH, "command", kit.Select("", arg, 1))
} default:
switch arg[2] { switch arg[2] {
case ZONE: // inputs key sub type zone field value 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)) _zone_inputs(m, arg[0], _domain_chain(m, arg[1]), arg[3], kit.Select(NAME, arg, 4), kit.Select("", arg, 5))
case HASH: case HASH:
_hash_inputs(m, arg[0], _domain_chain(m, arg[1]), kit.Select(NAME, arg, 3), kit.Select("", arg, 4)) _hash_inputs(m, arg[0], _domain_chain(m, arg[1]), kit.Select(NAME, arg, 3), kit.Select("", arg, 4))
case LIST: case LIST:
_list_inputs(m, arg[0], _domain_chain(m, arg[1]), kit.Select(NAME, arg, 3), kit.Select("", arg, 4)) _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) { INSERT: {Name: "insert key sub type arg...", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
defer m.ProcessRefresh3ms()
switch arg[2] { switch arg[2] {
case ZONE: // insert key sub type zone arg... 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: case HASH:
_hash_insert(m, arg[0], _domain_chain(m, arg[1]), arg[3:]...) _hash_insert(m, arg[0], _domain_chain(m, arg[1]), arg[3:]...)
case LIST: case LIST:
_list_insert(m, arg[0], _domain_chain(m, arg[1]), arg[3:]...) _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) { DELETE: {Name: "delete key sub type field value", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
defer m.ProcessRefresh3ms()
switch arg[2] { switch arg[2] {
case ZONE: // delete key sub type zone field value 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: case HASH:
_hash_delete(m, arg[0], _domain_chain(m, arg[1]), arg[3], arg[4]) _hash_delete(m, arg[0], _domain_chain(m, arg[1]), arg[3], arg[4])
case LIST: 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) { MODIFY: {Name: "modify key sub type field value arg...", Help: "编辑", Hand: func(m *ice.Message, arg ...string) {
switch arg[2] { switch arg[2] {
case ZONE: // modify key sub type zone id field value 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: case HASH:
_hash_modify(m, arg[0], _domain_chain(m, arg[1]), arg[3], arg[4], arg[5:]...) _hash_modify(m, arg[0], _domain_chain(m, arg[1]), arg[3], arg[4], arg[5:]...)
case LIST: 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) { PRUNES: {Name: "prunes key sub type [field value]...", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
switch arg[2] { switch arg[2] {
case ZONE: // prunes key sub type zone field value 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: case HASH:
_hash_prunes(m, arg[0], _domain_chain(m, arg[1]), arg[3:]...) _hash_prunes(m, arg[0], _domain_chain(m, arg[1]), arg[3:]...)
m.Tables(func(value ice.Maps) { m.Tables(func(value ice.Maps) { _hash_delete(m, arg[0], _domain_chain(m, arg[1]), HASH, value[HASH]) })
_hash_delete(m, arg[0], _domain_chain(m, arg[1]), HASH, value[HASH])
})
case LIST: 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) { 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] { switch file := _file_name(m, arg...); arg[2] {
case ZONE: case ZONE:
m.OptionFields(ZoneShort(m), m.Config(FIELD))
_zone_export(m, arg[0], _domain_chain(m, arg[1]), file) _zone_export(m, arg[0], _domain_chain(m, arg[1]), file)
case HASH: case HASH:
_hash_export(m, arg[0], _domain_chain(m, arg[1]), file) _hash_export(m, arg[0], _domain_chain(m, arg[1]), file)
case LIST: case LIST:
m.OptionFields(m.Config(FIELD))
_list_export(m, arg[0], _domain_chain(m, arg[1]), file) _list_export(m, arg[0], _domain_chain(m, arg[1]), file)
} }
}}, }},
@ -249,3 +263,35 @@ func init() {
SEARCH, ENGINE, PLUGIN, RENDER, 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...)
}
}
}}
}

View File

@ -2,34 +2,10 @@ package mdb
import ( import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
kit "shylinux.com/x/toolkits"
) )
const PLUGIN = "plugin" const PLUGIN = "plugin"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{PLUGIN: {Name: "plugin type name text auto", Help: "插件", Actions: RenderAction()}})
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")))
}
}},
}})
} }

View File

@ -8,28 +8,31 @@ import (
const RENDER = "render" const RENDER = "render"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{RENDER: {Name: "render type name text auto", Help: "渲染", Actions: RenderAction()}})
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{ func RenderAction(args ...ice.Any) ice.Actions {
CREATE: {Name: "create type name text", Help: "创建", Hand: func(m *ice.Message, arg ...string) { return ice.MergeAction(ice.Actions{
m.Option(NAME, kit.Select(m.Option(TYPE), m.Option(NAME))) ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
m.Option(TYPE, kit.Ext(m.Option(TYPE))) if cs := m.Target().Configs; cs[m.CommandKey()] == nil {
m.Cmdy(INSERT, m.PrefixKey(), "", HASH, m.OptionSimple("type,name,text")) cs[m.CommandKey()] = &ice.Config{Value: kit.Data(SHORT, TYPE)}
}},
}, 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")))
} }
}}, }},
}}) 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...)
}},
})
} }

View File

@ -2,32 +2,10 @@ package mdb
import ( import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
kit "shylinux.com/x/toolkits"
) )
const SEARCH = "search" const SEARCH = "search"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{SEARCH: {Name: "search type name text auto", Help: "搜索", Actions: RenderAction()}})
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)
}
}},
}})
} }

View File

@ -2,63 +2,62 @@ package mdb
import ( import (
"encoding/csv" "encoding/csv"
"os"
"path" "path"
"sort"
"strings"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
"shylinux.com/x/toolkits/logs"
"shylinux.com/x/toolkits/miss"
) )
func _zone_fields(m *ice.Message) []string { 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) { 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 { if zone == RANDOM {
zone = RANDOMS zone = RANDOMS
} }
fields := _zone_fields(m) fields := _zone_fields(m)
cb := m.OptionCB(SELECT) defer m.RLock(prefix, chain)()
m.Richs(prefix, chain, kit.Select(FOREACH, zone), func(key string, val ice.Map) { m.Richs(prefix, chain, kit.Select(FOREACH, zone), func(key string, val Map) {
if val = kit.GetMeta(val); zone == "" { chain := kit.Keys(chain, HASH, key)
if m.OptionFields() == DETAIL { defer m.RLock(prefix, chain)()
m.Push(DETAIL, val) m.Grows(prefix, chain, ID, id, func(value ice.Map) {
} else { _mdb_select(m, key, value, fields, val)
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)
}
}
}) })
}) })
} }
func _zone_export(m *ice.Message, prefix, chain, file string) { 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) m.Assert(e)
defer f.Close() defer f.Close()
@ -66,21 +65,24 @@ func _zone_export(m *ice.Message, prefix, chain, file string) {
defer w.Flush() defer w.Flush()
fields := _zone_fields(m) fields := _zone_fields(m)
fields = append(fields, EXTRA) if kit.IndexOf(fields, EXTRA) == -1 {
fields = append(fields, EXTRA)
}
w.Write(fields) w.Write(fields)
keys := []string{} keys := []string{}
m.Richs(prefix, chain, FOREACH, func(key string, val ice.Map) { m.Richs(prefix, chain, FOREACH, func(key string, val ice.Map) { keys = append(keys, key) })
keys = append(keys, key) kit.Sort(keys)
})
sort.Strings(keys)
count := 0 count := 0
defer m.Lock(prefix, chain)()
for _, key := range keys { for _, key := range keys {
m.Richs(prefix, chain, key, func(key string, val ice.Map) { m.Richs(prefix, chain, key, func(key string, val ice.Map) {
val = kit.GetMeta(val) 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) value = kit.GetMeta(value)
list := []string{} list := []string{}
@ -98,10 +100,8 @@ func _zone_export(m *ice.Message, prefix, chain, file string) {
m.Echo(p) m.Echo(p)
} }
func _zone_import(m *ice.Message, prefix, chain, file string) { func _zone_import(m *ice.Message, prefix, chain, file string) {
f, e := os.Open(kit.Keys(file, CSV)) f, e := miss.OpenFile(kit.Keys(file, CSV))
if m.Warn(e) { m.Assert(e)
return
}
defer f.Close() defer f.Close()
r := csv.NewReader(f) r := csv.NewReader(f)
@ -111,6 +111,7 @@ func _zone_import(m *ice.Message, prefix, chain, file string) {
list := ice.Maps{} list := ice.Maps{}
zkey := kit.Select(head[0], m.OptionFields()) zkey := kit.Select(head[0], m.OptionFields())
defer m.Lock(prefix, chain)()
for { for {
line, e := r.Read() line, e := r.Read()
if e != nil { 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)) 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++ count++
} }
@ -143,61 +148,36 @@ func _zone_import(m *ice.Message, prefix, chain, file string) {
m.Echo("%d", count) m.Echo("%d", count)
} }
const (
ZONE_FIELD = "zone,id,time,type,name,text"
)
const ZONE = "zone" const ZONE = "zone"
func ZoneAction(args ...ice.Any) ice.Actions { 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...), return ice.Actions{ice.CTX_INIT: AutoConfig(args...),
INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) { INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
arg[0] = strings.TrimPrefix(arg[0], "extra.") ZoneInputs(m, arg)
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)
}
}}, }},
CREATE: {Name: "create zone", Help: "创建", Hand: func(m *ice.Message, arg ...string) { 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) { 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) { INSERT: {Name: "insert", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 { ZoneInsert(m, arg)
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:])
}}, }},
MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) { 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) { SELECT: {Name: "select", Help: "列表", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(MODIFY, m.PrefixKey(), "", ZONE, m.Option(_zone(m)), m.Option(ID), arg) ZoneSelect(m, arg...)
}}, }},
EXPORT: {Name: "export", Help: "导出", Hand: func(m *ice.Message, arg ...string) { EXPORT: {Name: "export", Help: "导出", Hand: func(m *ice.Message, arg ...string) {
m.Option(ice.CACHE_LIMIT, "-1") ZoneExport(m, arg)
m.OptionFields(_zone(m), m.Config(FIELD))
m.Cmdy(EXPORT, m.PrefixKey(), "", ZONE)
}}, }},
IMPORT: {Name: "import", Help: "导入", Hand: func(m *ice.Message, arg ...string) { IMPORT: {Name: "import", Help: "导入", Hand: func(m *ice.Message, arg ...string) {
m.OptionFields(_zone(m)) ZoneImport(m, arg)
m.Cmdy(IMPORT, m.PrefixKey(), "", ZONE)
}}, }},
PREV: {Name: "prev", Help: "上一页", Hand: func(m *ice.Message, arg ...string) { PREV: {Name: "prev", Help: "上一页", Hand: func(m *ice.Message, arg ...string) {
PrevPage(m, arg[0], arg[1:]...) 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) { NEXT: {Name: "next", Help: "下一页", Hand: func(m *ice.Message, arg ...string) {
NextPageLimit(m, arg[0], arg[1:]...) 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 { func ZoneSelect(m *ice.Message, arg ...string) *ice.Message {
arg = kit.Slice(arg, 0, 2) arg = kit.Slice(arg, 0, 2)
m.Fields(len(arg), kit.Fields(TIME, m.Config(SHORT), COUNT), m.Config(FIELD)) 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) != "" { if m.Config(SHORT) != "" {
m.Sort(m.Config(SHORT)) m.Sort(m.Config(SHORT))
} }
m.PushAction(REMOVE) m.PushAction(m.Config(ACTION), REMOVE)
}
if len(arg) == 0 {
m.StatusTimeCount() m.StatusTimeCount()
} } else if len(arg) == 1 {
if len(arg) == 1 { m.StatusTimeCountTotal(m.Conf("", kit.Keys(HASH, HashSelectFields(m, arg[0], HASH), kit.Keym(COUNT))))
m.StatusTimeCountTotal(m.Conf(m.PrefixKey(), kit.Keys(HASH, kit.Hashs(arg[0]), kit.Keym("count"))))
} }
return m 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 { func ZoneSelectAll(m *ice.Message, arg ...string) *ice.Message {
m.Option(ice.CACHE_LIMIT, "-1") m.Option(ice.CACHE_LIMIT, "-1")
return ZoneSelect(m, arg...) return ZoneSelect(m, arg...)

View File

@ -4,78 +4,41 @@ import (
"bufio" "bufio"
"bytes" "bytes"
"io" "io"
"os"
"path" "path"
"strings" "strings"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/mdb"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
type ReadCloser struct { func _cat_find(m *ice.Message, name string) (io.ReadCloser, error) {
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 {
if m.Option(CAT_CONTENT) != "" { if m.Option(CAT_CONTENT) != "" {
return NewReadCloser(bytes.NewBufferString(m.Option(CAT_CONTENT))) return NewReadCloser(bytes.NewBufferString(m.Option(CAT_CONTENT))), nil
} }
return OpenFile(m, path.Join(m.Option(DIR_ROOT), name))
// 模块回调 }
for _, h := range rewriteList { func _cat_size(m *ice.Message, p string) (nline int) {
switch h := h.(type) { if f, e := OpenFile(m, p); m.Warn(e) {
case func(m *ice.Message, name string) io.ReadCloser: defer f.Close()
if r := h(m, name); r != nil { for bio := bufio.NewScanner(f); bio.Scan(); nline++ {
return r bio.Text()
}
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 nline
// 本地文件 }
if f, e := os.Open(path.Join(m.Option(DIR_ROOT), name)); e == nil { func _cat_hash(m *ice.Message, p string) string {
return f 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) { func _cat_list(m *ice.Message, name string) {
if m.Warn(!_cat_right(m, name), ice.ErrNotRight) { if !m.Right(m, name) {
return // 没有权限 return // 没有权限
} }
f, e := _cat_find(m, name)
f := _cat_find(m, name) if m.Warn(e, ice.ErrNotFound, name) {
if m.Warn(f == nil, ice.ErrNotFound, name) {
return // 没有文件 return // 没有文件
} }
defer f.Close() defer f.Close()
@ -97,15 +60,15 @@ func _cat_list(m *ice.Message, name string) {
for bio := bufio.NewScanner(f); bio.Scan(); { for bio := bufio.NewScanner(f); bio.Scan(); {
cb(bio.Text()) cb(bio.Text())
} }
case func([]string, string): case func([]string, string):
for bio := bufio.NewScanner(f); bio.Scan(); { for bio := bufio.NewScanner(f); bio.Scan(); {
cb(kit.Split(bio.Text()), bio.Text()) cb(kit.Split(bio.Text()), bio.Text())
} }
case nil:
default: buf, begin := make([]byte, ice.MOD_BUFS), 0
buf := make([]byte, ice.MOD_BUFS) for {
for begin := 0; true; { if n, e := f.Read(buf[begin:]); !m.Warn(e, ice.ErrNotValid, name) {
if n, e := f.Read(buf[begin:]); !m.Warn(e, ice.ErrNotFound, name) {
m.Log_IMPORT(FILE, name, SIZE, n) m.Log_IMPORT(FILE, name, SIZE, n)
if begin += n; begin < len(buf) { if begin += n; begin < len(buf) {
buf = buf[:begin] buf = buf[:begin]
@ -117,6 +80,8 @@ func _cat_list(m *ice.Message, name string) {
} }
} }
m.Echo(string(buf)) m.Echo(string(buf))
default:
m.ErrorNotImplement(cb)
} }
} }
@ -125,6 +90,7 @@ const (
TEMPLATE = "template" TEMPLATE = "template"
WEBSITE = "website" WEBSITE = "website"
STDIO = "stdio"
SOURCE = "source" SOURCE = "source"
SCRIPT = "script" SCRIPT = "script"
BINARY = "binary" BINARY = "binary"
@ -155,15 +121,15 @@ const (
YML = "yml" YML = "yml"
ZML = "zml" ZML = "zml"
PNG = "png"
JPG = "jpg"
MP4 = "mp4"
PWD = "./" PWD = "./"
PS = ice.PS
PT = ice.PT
) )
const (
PATH = "path"
FILE = "file"
LINE = "line"
SIZE = "size"
)
const CAT = "cat" const CAT = "cat"
func init() { func init() {
@ -177,20 +143,13 @@ func init() {
), ),
)}, )},
}, Commands: ice.Commands{ }, Commands: ice.Commands{
CAT: {Name: "cat path auto", Help: "文件", Actions: ice.Actions{ CAT: {Name: "cat path auto", Help: "文件", Hand: func(m *ice.Message, arg ...string) {
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) {
if len(arg) == 0 || strings.HasSuffix(arg[0], ice.PS) { if len(arg) == 0 || strings.HasSuffix(arg[0], ice.PS) {
m.Cmdy(DIR, arg) m.Cmdy(DIR, arg)
return return
} }
if m.Option(DIR_ROOT) != "" { 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]) _cat_list(m, arg[0])
}}, }},

View File

@ -1,9 +1,6 @@
package nfs package nfs
import ( import (
"bufio"
"crypto/sha1"
"io/ioutil"
"os" "os"
"path" "path"
"regexp" "regexp"
@ -15,57 +12,38 @@ import (
kit "shylinux.com/x/toolkits" 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 { 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 // 没有权限 return m // 没有权限
} }
if len(ice.Info.Pack) > 0 && m.Option(DIR_PACK) == ice.TRUE { list, e := ReadDir(m, path.Join(root, name))
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))
if e != nil { // 单个文件 if e != nil { // 单个文件
ls, _ := ioutil.ReadDir(path.Dir(path.Join(root, name))) ls, _ := ReadDir(m, path.Dir(path.Join(root, name)))
for _, k := range ls { for _, s := range ls {
if k.Name() == path.Base(name) { if s.Name() == path.Base(name) {
list = append(list, k) list = append(list, s)
} }
} }
name = path.Dir(name) 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 { for _, f := range list {
if f.Name() == ice.PT || f.Name() == ".." { if f.Name() == ice.PT || f.Name() == ".." {
continue continue
@ -74,7 +52,7 @@ func _dir_list(m *ice.Message, root string, name string, level int, deep bool, d
continue 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) 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())) { 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) { 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 continue
case nil: case nil:
default: default:
m.Error(true, "what: %v: %v", ice.ErrNotImplement, cb) m.ErrorNotImplement(cb)
} }
for _, field := range fields { 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: case mdb.TYPE:
m.Push(field, kit.Select(CAT, DIR, isDir)) m.Push(field, kit.Select(CAT, DIR, isDir))
case "tree": case TREE:
if level == 0 { if level == 0 {
m.Push(field, f.Name()) m.Push(field, f.Name())
} else { } else {
m.Push(field, strings.Repeat("| ", level-1)+"|-"+f.Name()) m.Push(field, strings.Repeat("| ", level-1)+"|-"+f.Name())
} }
case "full": case FULL:
m.Push(field, path.Join(root, name, f.Name())+kit.Select("", ice.PS, isDir)) m.Push(field, p+kit.Select("", ice.PS, isDir))
case PATH: 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: case FILE:
m.Push(field, f.Name()+kit.Select("", ice.PS, isDir)) m.Push(field, f.Name()+kit.Select("", ice.PS, isDir))
case mdb.NAME: case NAME:
m.Push(field, f.Name()) m.Push(field, f.Name())
case SIZE: case SIZE:
if isDir { if isDir {
if ls, e := ioutil.ReadDir(path.Join(root, name, f.Name())); e == nil { m.Push(field, _dir_size(m, p))
m.Push(field, len(ls))
} else {
m.Push(field, 0)
}
} else { } else {
m.Push(field, kit.FmtSize(f.Size())) m.Push(field, kit.FmtSize(f.Size()))
} }
case LINE: case LINE:
if isDir { if isDir {
if ls, e := ioutil.ReadDir(path.Join(root, name, f.Name())); e == nil { m.Push(field, _dir_size(m, p))
m.Push(field, len(ls))
} else {
m.Push(field, 0)
}
} else { } else {
nline := 0 m.Push(field, _cat_size(m, p))
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)
} }
case mdb.HASH, "hashs": case mdb.HASH, "hashs":
var h [20]byte h := ""
if isDir { if isDir {
if d, e := ioutil.ReadDir(p); m.Assert(e) { h = _dir_hash(m, p)
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, "")))
}
} else { } else {
if f, e := ioutil.ReadFile(path.Join(name, f.Name())); m.Assert(e) { h = _cat_hash(m, p)
h = sha1.Sum(f)
}
} }
m.Debug("what %v %v", h, p)
m.Push(mdb.HASH, kit.Select(kit.Format(h[:6]), kit.Format(h[:]), field == mdb.HASH)) m.Push(mdb.HASH, kit.Select(h[:6], h[:], field == mdb.HASH))
case mdb.LINK: 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: 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()) { switch p := m.MergeURL2("/share/local/"+p, ice.POD, m.Option(ice.MSG_USERPOD)); kit.Ext(f.Name()) {
case "png", "jpg": case PNG, JPG:
m.PushImages(field, p) m.PushImages(field, p)
case "mp4": case MP4:
m.PushVideos(field, p) m.PushVideos(field, p)
default: default:
m.Push(field, "") m.Push(field, "")
} }
case "action": case mdb.ACTION:
if m.IsCliUA() || m.Option(ice.MSG_USERROLE) == aaa.VOID { if m.IsCliUA() || m.Option(ice.MSG_USERROLE) == aaa.VOID {
break 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 { 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 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")) const (
msg.Tables(func(value ice.Maps) { TYPE_ALL = "all"
if !strings.Contains(value[mdb.NAME], name) { TYPE_CAT = "cat"
return TYPE_DIR = "dir"
} TYPE_BOTH = "both"
if value[mdb.TYPE] == CAT { )
value[mdb.TYPE] = kit.Ext(value[mdb.NAME]) const (
} DIR_ROOT = "dir_root"
m.PushSearch(value) 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)) m.Copy(m.Cmd(DIR, PWD).Sort(sort))
return m 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()
}},
}})
}

View File

@ -9,11 +9,11 @@ import (
const FIND = "find" const FIND = "find"
func init() { 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) { 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) { for _, file := range strings.Split(m.Cmdx("cli.system", FIND, PWD, "-name", arg[1]), ice.NL) {
m.Push(FILE, strings.TrimPrefix(file, PWD)) m.Push(FILE, strings.TrimPrefix(file, PWD))
} }
}}, }},
}}) })
} }

View File

@ -5,10 +5,10 @@ import ice "shylinux.com/x/icebergs"
const GREP = "grep" const GREP = "grep"
func init() { 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) { GREP: {Name: "grep path word auto", Help: "搜索", Hand: func(m *ice.Message, arg ...string) {
m.Option("cmd_dir", arg[0]) 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", ":") m.Split(m.Cmdx("cli.system", GREP, "--exclude=.[a-z]*", "--exclude-dir=.[a-z]*", "-rni", arg[1]), "file:line:text", ":")
}}, }},
}}) })
} }

View File

@ -1,9 +1,107 @@
package nfs 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: "存储模块"} var Index = &ice.Context{Name: "nfs", Help: "存储模块"}
func init() { func init() {
ice.Index.Register(Index, nil, TAR, CAT, DIR, DEFS, SAVE, PUSH, COPY, LINK, TAIL, TRASH, GREP) 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
View 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()
}},
})
}

View File

@ -1,17 +1,16 @@
package nfs package nfs
import ( import (
"fmt"
"io" "io"
"os"
"path" "path"
"strings"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
func _defs_file(m *ice.Message, name string, text ...string) { 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 return
} }
for i, v := range text { for i, v := range text {
@ -21,11 +20,11 @@ func _defs_file(m *ice.Message, name string, text ...string) {
_save_file(m, name, text...) _save_file(m, name, text...)
} }
func _save_file(m *ice.Message, name string, text ...string) { 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() defer f.Close()
for _, v := range text { 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) 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) { func _push_file(m *ice.Message, name string, text ...string) {
p := path.Join(m.Option(DIR_ROOT), name) if f, p, e := AppendFile(m, path.Join(m.Option(DIR_ROOT), name)); m.Assert(e) {
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) {
defer f.Close() defer f.Close()
for _, k := range text { 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) 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) { 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() defer f.Close()
for _, v := range from { 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() defer s.Close()
if n, e := io.Copy(f, s); !m.Warn(e, ice.ErrNotFound, name) { 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) { 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 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)) MkdirAll(m, path.Dir(name))
if e := os.Link(from, name); e != nil { if m.Warn(Link(m, from, name)) {
if m.Warn(os.Symlink(from, name), ice.ErrWarn, from) { if m.Warn(Symlink(m, from, name), ice.ErrWarn, from) {
return return
} }
} }
m.Log_EXPORT(name, "from", from) m.Log_EXPORT(FILE, name, FROM, from)
m.Echo(name) m.Echo(name)
} }
const ( const (
CONTENT = "content" CONTENT = "content"
FROM = "from"
) )
const DEFS = "defs" const DEFS = "defs"
const SAVE = "save" const SAVE = "save"
@ -92,7 +91,7 @@ const COPY = "copy"
const LINK = "link" const LINK = "link"
func init() { 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: {Name: "defs file text...", Help: "默认", Hand: func(m *ice.Message, arg ...string) {
_defs_file(m, arg[0], arg[1:]...) _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: {Name: "link file from", Help: "链接", Hand: func(m *ice.Message, arg ...string) {
_link_file(m, arg[0], arg[1]) _link_file(m, arg[0], arg[1])
}}, }},
}}) })
} }

View File

@ -36,11 +36,7 @@ func _tail_count(m *ice.Message, name string) string {
const TAIL = "tail" const TAIL = "tail"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
TAIL: {Name: TAIL, Help: "日志流", Value: kit.Data(
mdb.SHORT, mdb.NAME, mdb.FIELD, "time,id,file,text",
)},
}, Commands: ice.Commands{
TAIL: {Name: "tail name id auto page filter:text create", Help: "日志流", Actions: ice.MergeAction(ice.Actions{ 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) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
m.Richs(TAIL, "", mdb.FOREACH, func(key string, value ice.Map) { 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) { mdb.CREATE: {Name: "create file name", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
_tail_create(m, arg...) _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.Fields(len(kit.Slice(arg, 0, 2)), "time,name,count,file", m.Config(mdb.FIELD))
m.OptionPage(kit.Slice(arg, 2)...) m.OptionPage(kit.Slice(arg, 2)...)
@ -76,5 +72,5 @@ func init() {
m.StatusTimeCountTotal(_tail_count(m, arg[0])) m.StatusTimeCountTotal(_tail_count(m, arg[0]))
} }
}}, }},
}}) })
} }

View File

@ -15,7 +15,7 @@ import (
const TAR = "tar" const TAR = "tar"
func init() { func init() {
Index.Merge(&ice.Context{Commands: ice.Commands{ Index.MergeCommands(ice.Commands{
TAR: {Name: "tar file path auto", Help: "打包", Actions: ice.Actions{ TAR: {Name: "tar file path auto", Help: "打包", Actions: ice.Actions{
mdb.IMPORT: {Name: "import", Help: "导入", Hand: func(m *ice.Message, arg ...string) { mdb.IMPORT: {Name: "import", Help: "导入", Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 1 { if len(arg) == 1 {
@ -63,18 +63,18 @@ func init() {
} }
header.Name = strings.TrimPrefix(p, dir_root+ice.PS) 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 return
} }
file, err := os.Open(p) file, err := os.Open(p)
if m.Warn(err != nil, "err: %v", err) { if m.Warn(err) {
return return
} }
defer file.Close() defer file.Close()
m.PushNoticeGrow(kit.Format("%v %v %v\n", header.Name, kit.FmtSize(f.Size()), kit.FmtSize(total))) 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 return
} }
@ -84,5 +84,5 @@ func init() {
} }
m.StatusTimeCountTotal(kit.FmtSize(total)) m.StatusTimeCountTotal(kit.FmtSize(total))
}}, }},
}}) })
} }

View File

@ -1,7 +1,6 @@
package nfs package nfs
import ( import (
"os"
"path" "path"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
@ -10,61 +9,59 @@ import (
) )
func _trash_create(m *ice.Message, name string) { func _trash_create(m *ice.Message, name string) {
if s, e := os.Stat(name); m.Assert(e) { if m.Warn(name == "", ice.ErrNotValid, name) {
p := path.Join(ice.VAR_TRASH, path.Base(name)) return
if !s.IsDir() { }
if f, e := os.Open(name); m.Assert(e) { s, e := StatFile(m, name)
defer f.Close() if m.Warn(e, ice.ErrNotFound, name) {
p = path.Join(ice.VAR_TRASH, kit.HashsPath(f)) 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)) MkdirAll(m, path.Dir(p))
if os.RemoveAll(p); !m.Warn(os.Rename(name, p)) { if RemoveAll(m, p); !m.Warn(Rename(m, name, p)) {
m.Cmd(mdb.INSERT, TRASH, "", mdb.HASH, FILE, p, FROM, name) mdb.HashCreate(m, FROM, name, FILE, p)
}
} }
} }
const (
FROM = "from"
)
const TRASH = "trash" const TRASH = "trash"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
TRASH: {Name: TRASH, Help: "回收站", Value: kit.Data(
mdb.SHORT, FROM, mdb.FIELD, "time,hash,file,from", PATH, ice.VAR_TRASH,
)},
}, Commands: ice.Commands{
TRASH: {Name: "trash hash auto prunes", Help: "回收站", Actions: ice.MergeAction(ice.Actions{ TRASH: {Name: "trash hash auto prunes", Help: "回收站", Actions: ice.MergeAction(ice.Actions{
mdb.REVERT: {Name: "revert", Help: "恢复", Hand: func(m *ice.Message, arg ...string) { mdb.REVERT: {Name: "revert", Help: "恢复", Hand: func(m *ice.Message, arg ...string) {
os.Rename(m.Option(FILE), m.Option(FROM)) Rename(m, m.Option(FILE), m.Option(FROM))
m.Cmd(mdb.DELETE, TRASH, "", mdb.HASH, m.OptionSimple(mdb.HASH)) mdb.HashRemove(m, m.OptionSimple(mdb.HASH))
}}, }},
mdb.CREATE: {Name: "create path", Help: "删除", Hand: func(m *ice.Message, arg ...string) { mdb.CREATE: {Name: "create path", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
p := path.Join(m.Config(PATH), path.Base(m.Option(PATH))) p := path.Join(ice.VAR_TRASH, path.Base(m.Option(PATH)))
os.RemoveAll(p) RemoveAll(m, p)
if os.MkdirAll(path.Dir(p), ice.MOD_DIR); !m.Warn(os.Rename(m.Option(PATH), p)) { if MkdirAll(m, path.Dir(p)); !m.Warn(Rename(m, m.Option(PATH), p)) {
m.Echo(p) m.Echo(p)
} }
}}, }},
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) { mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
os.Remove(m.Option(FILE)) Remove(m, m.Option(FILE))
m.Cmd(mdb.DELETE, TRASH, "", mdb.HASH, m.OptionSimple(mdb.HASH)) mdb.HashRemove(m, m.OptionSimple(mdb.HASH))
}}, }},
mdb.PRUNES: {Name: "prunes before@date", Help: "清理", Hand: func(m *ice.Message, arg ...string) { mdb.PRUNES: {Name: "prunes before@date", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
mdb.HashPrunes(m, func(value ice.Maps) bool { mdb.HashPrunes(m, func(value ice.Maps) bool {
os.Remove(value[FILE]) Remove(m, value[FILE])
return false return false
}) })
}}, }},
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { }, 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 || !kit.FileExists(arg[0]) { if mdb.HashSelect(m, arg...); len(arg) == 0 || !ExistsFile(m, arg[0]) {
m.PushAction(mdb.REVERT, mdb.REMOVE) m.PushAction(mdb.REVERT, mdb.REMOVE)
return return
} }
_trash_create(m, arg[0]) _trash_create(m, arg[0])
}}, }},
}}) })
} }

View File

@ -13,21 +13,21 @@ import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/gdb"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
func Render(msg *ice.Message, cmd string, args ...ice.Any) (res string) { func Render(msg *ice.Message, cmd string, arg ...ice.Any) (res string) {
switch arg := kit.Simple(args...); cmd { switch args := kit.Simple(arg...); cmd {
case ice.RENDER_VOID: case ice.RENDER_VOID:
return res return res
case ice.RENDER_RESULT: case ice.RENDER_RESULT:
if len(arg) > 0 { if len(args) > 0 {
msg.Resultv(arg) msg.Resultv(args)
} }
res = msg.Result() res = msg.Result()
default: default:
if res = msg.Result(); res == "" { if res = msg.Result(); res == "" {
res = msg.Table().Result() res = msg.Table().Result()
@ -110,22 +110,18 @@ func (f *Frame) alias(m *ice.Message, ls []string) []string {
return ls return ls
} }
func (f *Frame) parse(m *ice.Message, line string) string { func (f *Frame) parse(m *ice.Message, line string) string {
// for _, one := range kit.Split(line, ";", ";", ";") { msg := m.Spawn(f.target)
for _, one := range kit.Simple(line) { ls := f.change(msg, f.alias(msg, kit.Split(strings.TrimSpace(line))))
msg := m.Spawn(f.target) if len(ls) == 0 {
ls := f.change(msg, f.alias(msg, kit.Split(strings.TrimSpace(one)))) return ""
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)...)
} }
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 "" return ""
} }
func (f *Frame) scan(m *ice.Message, h, line string) *Frame { 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 m.I, m.O = f.stdin, f.stdout
bio := bufio.NewScanner(f.stdin) bio := bufio.NewScanner(f.stdin)
for f.prompt(m, ps...); bio.Scan() && f.stdin != nil; f.prompt(m, ps...) { for f.prompt(m, ps...); f.stdin != nil && bio.Scan(); f.prompt(m, ps...) {
if h == STDIO { if len(bio.Text()) == 0 && h == STDIO {
if len(bio.Text()) == 0 { continue // 空行
continue // 空行
}
m.Cmdx(mdb.INSERT, SOURCE, kit.Keys(mdb.HASH, h), mdb.LIST, mdb.TEXT, bio.Text())
} }
f.count++ 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(), "\\") { if strings.HasSuffix(bio.Text(), "\\") {
line += bio.Text()[:len(bio.Text())-1] line += bio.Text()[:len(bio.Text())-1]
ps = f.ps2 ps = f.ps2
@ -170,11 +158,8 @@ func (f *Frame) scan(m *ice.Message, h, line string) *Frame {
} }
if strings.HasPrefix(strings.TrimSpace(line), "#") { if strings.HasPrefix(strings.TrimSpace(line), "#") {
line = "" line = ""
continue continue // 注释
} }
// if line = strings.Split(line, " # ")[0]; len(line) == 0 {
// continue // 注释
// }
if ps = f.ps1; f.stdout == os.Stdout { if ps = f.ps1; f.stdout == os.Stdout {
if ice.Info.Colors { if ice.Info.Colors {
f.printf(m, "\033[0m") // 清空格式 f.printf(m, "\033[0m") // 清空格式
@ -195,27 +180,28 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool {
m.Optionv(FRAME, f) m.Optionv(FRAME, f)
switch f.source = kit.Select(STDIO, arg, 0); f.source { switch f.source = kit.Select(STDIO, arg, 0); f.source {
case STDIO: // 终端交互 case STDIO: // 终端交互
m.Cap(ice.CTX_STREAM, f.source) if m.Cap(ice.CTX_STREAM, f.source); f.target == nil {
if f.target == nil {
f.target = m.Target() f.target = m.Target()
} }
r, w, _ := os.Pipe() r, w, _ := os.Pipe()
m.Go(func() { io.Copy(w, os.Stdin) }) go func() { io.Copy(w, os.Stdin) }()
f.stdin, f.stdout = r, os.Stdout f.pipe, f.stdin, f.stdout = w, r, os.Stdout
f.pipe = w
m.Option(ice.MSG_OPTS, ice.MSG_USERNAME) 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.NAME)), STDIO)
m.Conf(SOURCE, kit.Keys(mdb.HASH, STDIO, kit.Keym(mdb.TIME)), m.Time()) 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.count = kit.Int(m.Conf(SOURCE, kit.Keys(mdb.HASH, STDIO, kit.Keym(mdb.COUNT)))) + 1
f.scan(m, STDIO, "") f.scan(m, STDIO, "")
default: // 脚本文件 default: // 脚本文件
if strings.Contains(m.Option(ice.MSG_SCRIPT), ice.PS) { if m.Option(ice.MSG_SCRIPT) != "" {
f.source = path.Join(path.Dir(m.Option(ice.MSG_SCRIPT)), f.source) 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) m.Option(ice.MSG_SCRIPT, f.source)
f.target = m.Source() f.target = m.Source()
@ -224,13 +210,12 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool {
return true // 查找失败 return true // 查找失败
} else { } else {
buf := bytes.NewBuffer(make([]byte, 0, ice.MOD_BUFS)) buf := bytes.NewBuffer(make([]byte, 0, ice.MOD_BUFS))
f.stdin, f.stdout = bytes.NewBufferString(msg.Result()), buf
defer func() { m.Echo(buf.String()) }() defer func() { m.Echo(buf.String()) }()
f.stdin, f.stdout = bytes.NewBuffer([]byte(msg.Result())), buf
} }
f.count = 1 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 return true
} }
@ -266,16 +251,14 @@ func init() {
PS2, []ice.Any{mdb.COUNT, " ", TARGET, "> "}, PS2, []ice.Any{mdb.COUNT, " ", TARGET, "> "},
)}, )},
}, Commands: ice.Commands{ }, Commands: ice.Commands{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {}},
SOURCE: {Name: "source file", Help: "脚本解析", Actions: ice.MergeAction(ice.Actions{ 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.Cmdy(SCREEN, m.Option(mdb.TEXT))
m.ProcessInner() m.ProcessInner()
}}, }},
}, mdb.ZoneAction()), Hand: func(m *ice.Message, arg ...string) { }, mdb.ZoneAction()), Hand: func(m *ice.Message, arg ...string) {
if len(arg) > 0 && kit.Ext(arg[0]) == ice.SHY { if f, ok := m.Target().Server().(*Frame); ok {
(&Frame{}).Start(m, arg...) f.Spawn(m, m.Target()).Start(m, arg...)
return // 脚本解析
} }
}}, }},
TARGET: {Name: "target name run", Help: "当前模块", Hand: func(m *ice.Message, arg ...string) { TARGET: {Name: "target name run", Help: "当前模块", Hand: func(m *ice.Message, arg ...string) {
@ -284,26 +267,30 @@ func init() {
f.prompt(m) f.prompt(m)
}}, }},
PROMPT: {Name: "prompt arg run", Help: "命令提示", Hand: func(m *ice.Message, arg ...string) { PROMPT: {Name: "prompt arg run", Help: "命令提示", Hand: func(m *ice.Message, arg ...string) {
f := m.Optionv(FRAME).(*Frame) if f, ok := m.Optionv(FRAME).(*Frame); ok {
f.ps1 = arg f.ps1 = arg
f.prompt(m) f.prompt(m)
}
}}, }},
PRINTF: {Name: "printf run text", Help: "输出显示", Hand: func(m *ice.Message, arg ...string) { PRINTF: {Name: "printf run text", Help: "输出显示", Hand: func(m *ice.Message, arg ...string) {
f := m.Optionv(FRAME).(*Frame) if f, ok := m.Optionv(FRAME).(*Frame); ok {
f.printf(m, arg[0]) f.printf(m, arg[0])
}
}}, }},
SCREEN: {Name: "screen run text", Help: "输出命令", Hand: func(m *ice.Message, arg ...string) { SCREEN: {Name: "screen run text", Help: "输出命令", Hand: func(m *ice.Message, arg ...string) {
f := m.Optionv(FRAME).(*Frame) if f, ok := m.Optionv(FRAME).(*Frame); ok {
for _, line := range kit.Split(arg[0], ice.NL, ice.NL) { for _, line := range kit.Split(arg[0], ice.NL, ice.NL) {
fmt.Fprintf(f.pipe, line+ice.NL) fmt.Fprintf(f.pipe, line+ice.NL)
f.printf(m, line+ice.NL) f.printf(m, line+ice.NL)
m.Sleep300ms() m.Sleep300ms()
}
m.Echo(f.res)
} }
m.Echo(f.res)
}}, }},
RETURN: {Name: "return", Help: "结束脚本", Hand: func(m *ice.Message, arg ...string) { RETURN: {Name: "return", Help: "结束脚本", Hand: func(m *ice.Message, arg ...string) {
f := m.Optionv(FRAME).(*Frame) if f, ok := m.Optionv(FRAME).(*Frame); ok {
f.Close(m, arg...) f.Close(m, arg...)
}
}}, }},
}}) }})
} }

View File

@ -36,7 +36,6 @@ func (c *Conn) Close() error {
func _client_dial(m *ice.Message, arg ...string) { func _client_dial(m *ice.Message, arg ...string) {
c, e := net.Dial(TCP, m.Option(HOST)+ice.DF+m.Option(PORT)) c, e := net.Dial(TCP, m.Option(HOST)+ice.DF+m.Option(PORT))
c = &Conn{m: m, s: &Stat{}, Conn: c} c = &Conn{m: m, s: &Stat{}, Conn: c}
if e == nil { if e == nil {
defer c.Close() defer c.Close()
@ -57,8 +56,10 @@ func _client_dial(m *ice.Message, arg ...string) {
break break
} }
} }
default: case nil:
c.Write([]byte("hello world\n")) c.Write([]byte("hello world\n"))
default:
m.ErrorNotImplement(cb)
} }
} }
@ -77,25 +78,18 @@ const (
const CLIENT = "client" const CLIENT = "client"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
CLIENT: {Name: CLIENT, Help: "客户端", Value: kit.Data(
mdb.FIELD, "time,hash,status,type,name,host,port,error,nread,nwrite",
)},
}, Commands: ice.Commands{
CLIENT: {Name: "client hash auto prunes", Help: "客户端", Actions: ice.MergeAction(ice.Actions{ CLIENT: {Name: "client hash auto prunes", Help: "客户端", Actions: ice.MergeAction(ice.Actions{
ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) {
m.Richs(CLIENT, "", mdb.FOREACH, func(key string, value ice.Map) { m.Conf(m.PrefixKey(), "", "")
kit.Value(value, kit.Keym(STATUS), CLOSE)
})
m.Cmdy(SERVER, mdb.PRUNES)
}}, }},
DIAL: {Name: "dial type name port=9010 host=", Help: "连接", Hand: func(m *ice.Message, arg ...string) { DIAL: {Name: "dial type name port=9010 host=", Help: "连接", Hand: func(m *ice.Message, arg ...string) {
_client_dial(m, arg...) _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) { mdb.HashSelect(m, arg...).Tables(func(value ice.Maps) {
m.PushButton(kit.Select("", mdb.REMOVE, value[STATUS] == OPEN)) m.PushButton(kit.Select("", mdb.REMOVE, value[STATUS] == OPEN))
}) })
}}, }},
}}) })
} }

View File

@ -59,13 +59,6 @@ func _islocalhost(m *ice.Message, ip string) (ok bool) {
} }
return false 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 ( const (
LOCALHOST = "localhost" LOCALHOST = "localhost"
@ -73,16 +66,10 @@ const (
const HOST = "host" const HOST = "host"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
HOST: {Name: HOST, Help: "主机", Value: kit.Data( HOST: {Name: "host name auto", Help: "主机", Actions: ice.MergeAction(ice.Actions{
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{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
m.Cmd(HOST).Tables(func(value ice.Maps) { m.Cmd(HOST).Tables(func(value ice.Maps) { m.Cmd(HOST, aaa.WHITE, value[aaa.IP]) })
m.Cmd(HOST, aaa.WHITE, value[aaa.IP])
})
}}, }},
aaa.BLACK: {Name: "black", Help: "黑名单", Hand: func(m *ice.Message, arg ...string) { aaa.BLACK: {Name: "black", Help: "黑名单", Hand: func(m *ice.Message, arg ...string) {
m.Log_CREATE(aaa.BLACK, arg[0]) m.Log_CREATE(aaa.BLACK, arg[0])
@ -92,8 +79,16 @@ func init() {
m.Log_CREATE(aaa.WHITE, arg[0]) m.Log_CREATE(aaa.WHITE, arg[0])
m.Rich(HOST, kit.Keym(aaa.WHITE), kit.Dict(mdb.TEXT, 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)) _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
} }

View File

@ -6,7 +6,6 @@ import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
@ -25,12 +24,12 @@ func _port_right(m *ice.Message, arg ...string) string {
c.Close() c.Close()
continue continue
} }
p := path.Join(m.Conf(cli.DAEMON, kit.Keym(nfs.PATH)), kit.Format(i)) p := path.Join(ice.USR_LOCAL_DAEMON, kit.Format(i))
if kit.FileExists(p) { if nfs.ExistsFile(m, p) {
continue continue
} }
nfs.MkdirAll(m, p)
nfs.MkdirAll(m, p)
m.Log_SELECT(PORT, i) m.Log_SELECT(PORT, i)
return m.Config(CURRENT, i) return m.Config(CURRENT, i)
} }
@ -46,10 +45,8 @@ const (
const PORT = "port" const PORT = "port"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
PORT: {Name: PORT, Help: "端口", Value: kit.Data(BEGIN, 10000, CURRENT, 10000, END, 20000)}, PORT: {Name: "port port path auto", Help: "端口", Actions: ice.MergeAction(ice.Actions{
}, Commands: ice.Commands{
PORT: {Name: "port port path auto", Help: "端口", Actions: ice.Actions{
aaa.RIGHT: {Name: "right", Help: "分配", Hand: func(m *ice.Message, arg ...string) { aaa.RIGHT: {Name: "right", Help: "分配", Hand: func(m *ice.Message, arg ...string) {
m.Echo(_port_right(m, arg...)) 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))) m.Cmd(nfs.TRASH, path.Join(ice.USR_LOCAL_DAEMON, m.Option(PORT)))
} }
}}, }},
}, Hand: func(m *ice.Message, arg ...string) { }, mdb.HashAction(BEGIN, 10000, CURRENT, 10000, END, 20000)), Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 { if len(arg) > 0 {
current := kit.Int(m.Config(BEGIN)) m.Cmdy(nfs.DIR, arg[1:], kit.Dict(nfs.DIR_ROOT, path.Join(ice.USR_LOCAL_DAEMON, arg[0])))
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))
return 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))
}}, }},
}}) })
} }

View File

@ -19,7 +19,7 @@ type Listener struct {
func (l Listener) Accept() (net.Conn, error) { func (l Listener) Accept() (net.Conn, error) {
c, e := l.Listener.Accept() c, e := l.Listener.Accept()
l.s.nc += 1 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 { func (l Listener) Close() error {
l.m.Cmd(mdb.MODIFY, SERVER, "", mdb.HASH, mdb.HASH, l.h, STATUS, CLOSE) 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) { func _server_listen(m *ice.Message, arg ...string) {
l, e := net.Listen(TCP, m.Option(HOST)+":"+m.Option(PORT)) l, e := net.Listen(TCP, m.Option(HOST)+":"+m.Option(PORT))
h := m.Cmdx(mdb.INSERT, SERVER, "", mdb.HASH, arg, l = &Listener{m: m, h: m.Cmdx(mdb.INSERT, SERVER, "", mdb.HASH,
STATUS, kit.Select(ERROR, OPEN, e == nil), ERROR, kit.Format(e)) arg, STATUS, kit.Select(ERROR, OPEN, e == nil), ERROR, kit.Format(e), kit.Dict(mdb.TARGET, l)), s: &Stat{}, Listener: l}
l = &Listener{m: m, h: h, s: &Stat{}, Listener: l}
if e == nil { if e == nil {
defer l.Close() defer l.Close()
} }
@ -85,25 +83,28 @@ const (
const SERVER = "server" const SERVER = "server"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
SERVER: {Name: SERVER, Help: "服务器", Value: kit.Data(
mdb.FIELD, "time,hash,status,type,name,host,port,error,nconn",
)},
}, Commands: ice.Commands{
SERVER: {Name: "server hash auto prunes", Help: "服务器", Actions: ice.MergeAction(ice.Actions{ 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) { ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) {
m.Richs(SERVER, "", mdb.FOREACH, func(key string, value ice.Map) { mdb.HashSelectValue(m, func(target ice.Any) {
kit.Value(value, kit.Keym(STATUS), CLOSE) 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) { LISTEN: {Name: "LISTEN type name port=9030 host=", Help: "监听", Hand: func(m *ice.Message, arg ...string) {
_server_listen(m, arg...) _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) { mdb.HashSelect(m, arg...).Tables(func(value ice.Maps) {
m.PushButton(kit.Select("", mdb.REMOVE, value[STATUS] == CLOSE)) m.PushButton(kit.Select("", mdb.REMOVE, value[STATUS] == CLOSE))
}) })
}}, }},
}}) })
} }

View File

@ -426,5 +426,4 @@ func _story_commit(m *ice.Message, arg ...string) {
value["list"] = list value["list"] = list
} }
m.Echo(list) m.Echo(list)
} }

View File

@ -5,85 +5,86 @@ import (
"strings" "strings"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/tcp" "shylinux.com/x/icebergs/base/tcp"
kit "shylinux.com/x/toolkits" 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)) addr, err := net.ResolveUDPAddr("udp4", kit.Format("%s:%s", host, port))
m.Assert(err) m.Assert(err)
return addr return addr
} }
func _udp_broad(m *ice.Message, host, port string, remote_host, remote_port string) { func _broad_send(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) { if s, e := net.DialUDP("udp", nil, _broad_addr(m, remote_host, remote_port)); m.Assert(e) {
defer s.Close() defer s.Close()
msg := m.Spawn(kit.Dict(tcp.HOST, host, tcp.PORT, port)) 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())) s.Write([]byte(msg.FormatMeta()))
} }
} }
func _serve_udp(m *ice.Message, host, port string) { func _broad_serve(m *ice.Message, host, port string) {
m.Cmd(BROAD, mdb.CREATE, tcp.HOST, host, tcp.PORT, port) _broad_send(m, host, port, "255.255.255.255", "9020")
_udp_broad(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) {
if s, e := net.ListenUDP("udp", _udp_addr(m, "0.0.0.0", port)); m.Assert(e) {
defer s.Close() 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 { for {
n, addr, err := s.ReadFromUDP(buf[:]) n, addr, err := s.ReadFromUDP(buf[:])
if err != nil { if err != nil {
m.Debug("what %v", err) break
continue
} }
m.Debug("recv %v %v", string(buf[:n]), addr) m.Log_IMPORT(BROAD, string(buf[:n]), "from", addr)
msg := m.Spawn(buf[:n]) msg := m.Spawn(buf[:n])
if m.Cmd(BROAD, kit.Format("%s,%s", msg.Option(tcp.HOST), msg.Option(tcp.PORT))).Length() > 0 { if m.Cmd(BROAD, kit.Format("%s,%s", msg.Option(tcp.HOST), msg.Option(tcp.PORT))).Length() > 0 {
continue 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.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) s.WriteToUDP([]byte(m.Spawn(value).FormatMeta()), remote)
}) })
m.Cmd(BROAD, mdb.CREATE, msg.OptionSimple(tcp.HOST, tcp.PORT)) 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) { func _broad_search(m *ice.Message, kind, name, text string, arg ...string) {
m.Richs(BROAD, nil, mdb.FOREACH, func(key string, value ice.Map) { mdb.HashSelectValue(m, func(value ice.Map) {
if value = kit.GetMeta(value); !strings.Contains(kit.Format(value[tcp.HOST]), name) { if !strings.Contains(kit.Format(value[tcp.HOST]), name) {
return 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" const BROAD = "broad"
func init() { func init() {
Index.Merge(&ice.Context{Commands: ice.Commands{ Index.MergeCommands(ice.Commands{
BROAD: {Name: "broad hash auto", Help: "广播", Actions: ice.MergeAction(ice.Actions{ 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: {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) { SPACE: {Name: "space dev", Help: "连接", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(SPIDE, mdb.CREATE, mdb.NAME, m.Option(ice.DEV), ADDRESS, 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))) kit.Format("http://%s:%s", m.Option(tcp.HOST), m.Option(tcp.PORT)))
m.Cmd(SPACE, tcp.DIAL, m.OptionSimple(ice.DEV)) m.Cmd(SPACE, tcp.DIAL, m.OptionSimple(ice.DEV))
}}, }},
}, mdb.HashAction( }, mdb.HashAction(mdb.SHORT, "host,port", mdb.FIELD, "time,hash,host,port", mdb.ACTION, "space"))},
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)
}},
}})
} }

View File

@ -10,16 +10,17 @@ import (
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
"shylinux.com/x/toolkits/miss"
) )
func _cache_name(m *ice.Message, h string) string { 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 func _cache_save(m *ice.Message, kind, name, text string, arg ...string) { // file size
if name == "" { if name == "" {
return 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) p := m.Cmdx(nfs.SAVE, _cache_name(m, kit.Hashs(text)), text)
text, arg = p, kit.Simple(p, len(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)) size := kit.Int(kit.Select(kit.Format(len(text)), arg, 1))
file := kit.Select("", arg, 0) file := kit.Select("", arg, 0)
text = kit.Select(file, text) 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()) 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) { 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() 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 m.Cmdx(nfs.LINK, _cache_name(m, kit.Hashs(f)), name), kit.Format(s.Size())
} }
} }
return "", "0" return "", "0"
} }
func _cache_upload(m *ice.Message, r *http.Request) (kind, name, file, size string) { func _cache_upload(m *ice.Message, r *http.Request) (kind, name, file, size string) {
if buf, h, e := r.FormFile(UPLOAD); e == nil { if b, h, e := r.FormFile(UPLOAD); e == nil {
defer buf.Close() 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() defer f.Close()
// 导入数据 // 导入数据
buf.Seek(0, os.SEEK_SET) b.Seek(0, os.SEEK_SET)
if n, e := io.Copy(f, buf); m.Assert(e) { if n, e := io.Copy(f, b); m.Assert(e) {
m.Log_IMPORT(nfs.FILE, p, nfs.SIZE, kit.FmtSize(int64(n))) m.Log_IMPORT(nfs.FILE, p, nfs.SIZE, kit.FmtSize(int64(n)))
return h.Header.Get(ContentType), h.Filename, p, kit.Format(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) { func _cache_download(m *ice.Message, r *http.Response) (file, size string) {
defer r.Body.Close() defer r.Body.Close()
if f, p, e := kit.Create(path.Join(ice.VAR_TMP, kit.Hashs(mdb.UNIQ))); m.Assert(e) { if f, p, e := miss.CreateFile(path.Join(ice.VAR_TMP, kit.Hashs(mdb.UNIQ))); m.Assert(e) {
step, total := 0, kit.Int(kit.Select("1", r.Header.Get(ContentLength))) defer f.Close()
step, total := 0, kit.Int(kit.Select("100", r.Header.Get(ContentLength)))
size, buf := 0, make([]byte, ice.MOD_BUFS) size, buf := 0, make([]byte, ice.MOD_BUFS)
for { for {
if n, _ := r.Body.Read(buf); n > 0 { if n, e := r.Body.Read(buf); n > 0 && e == nil {
size += n size += n
f.Write(buf[0:n]) f.Write(buf[0:n])
s := size * 100 / total s := size * 100 / total
@ -95,31 +98,16 @@ func _cache_download(m *ice.Message, r *http.Response) (file, size string) {
cb(size, total, s) cb(size, total, s)
case func(int, int): case func(int, int):
cb(size, total) 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: default:
if s != step && s%10 == 0 { 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))) m.Log_IMPORT(nfs.FILE, p, mdb.VALUE, s, mdb.COUNT, kit.FmtSize(int64(size)), mdb.TOTAL, kit.FmtSize(int64(total)))
} }
} }
step = s step = s
continue continue
} }
return p, kit.Format(size)
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 "", "0" return "", "0"
@ -135,22 +123,7 @@ const (
const CACHE = "cache" const CACHE = "cache"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
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])
}
})
}},
CACHE: {Name: "cache hash auto", Help: "缓存池", Actions: ice.MergeAction(ice.Actions{ CACHE: {Name: "cache hash auto", Help: "缓存池", Actions: ice.MergeAction(ice.Actions{
WATCH: {Name: "watch key file", Help: "释放", Hand: func(m *ice.Message, arg ...string) { WATCH: {Name: "watch key file", Help: "释放", Hand: func(m *ice.Message, arg ...string) {
_cache_watch(m, arg[0], arg[1]) _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) { DOWNLOAD: {Name: "download type name", Help: "下载", Hand: func(m *ice.Message, arg ...string) {
if r, ok := m.Optionv(RESPONSE).(*http.Response); ok { if r, ok := m.Optionv(RESPONSE).(*http.Response); ok {
file, size := _cache_download(m, r) file, size := _cache_download(m, r)
file, size = _cache_catch(m, file)
_cache_save(m, arg[0], arg[1], "", file, size) _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 { if mdb.HashSelect(m, arg...); len(arg) == 0 {
return return
} }
if m.Append(nfs.FILE) == "" { if m.Append(nfs.FILE) == "" {
m.PushScript("inner", m.Append(mdb.TEXT)) m.PushScript("inner", m.Append(mdb.TEXT))
} else { } 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])
}
})
}},
})
} }

View File

@ -7,44 +7,65 @@ import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/gdb"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp" "shylinux.com/x/icebergs/base/tcp"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
"shylinux.com/x/toolkits/file"
) )
func _dream_list(m *ice.Message) *ice.Message { 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) { list := m.CmdMap(SPACE, mdb.NAME)
if m.Richs(SPACE, nil, value[mdb.NAME], func(key string, val ice.Map) { m.Cmdy(nfs.DIR, ice.USR_LOCAL_WORK, "time,size,name").Tables(func(value ice.Maps) {
m.Push(mdb.TYPE, val[mdb.TYPE]) if dream, ok := list[value[mdb.NAME]]; ok {
m.Push(mdb.TYPE, dream[mdb.TYPE])
m.Push(cli.STATUS, cli.START) m.Push(cli.STATUS, cli.START)
m.PushButton("vimer", "xterm", cli.OPEN, cli.STOP) m.PushButton("vimer", "xterm", cli.OPEN, cli.STOP)
m.PushAnchor(strings.Split(m.MergePod(value[mdb.NAME]), "?")[0]) 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(mdb.TYPE, WORKER)
m.Push(cli.STATUS, cli.STOP) m.Push(cli.STATUS, cli.STOP)
m.PushButton(cli.START, nfs.TRASH) m.PushButton(cli.START, nfs.TRASH)
m.PushAnchor("") 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) { func _dream_show(m *ice.Message, name string) {
if !strings.Contains(name, "-") || !strings.HasPrefix(name, "20") { if !strings.Contains(name, "-") || !strings.HasPrefix(name, "20") {
name = m.Time("20060102-") + kit.ReplaceAll(name, "-", "_") 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))) defer m.Echo(m.MergePod(m.Option(mdb.NAME, name)))
// 任务目录 p := path.Join(ice.USR_LOCAL_WORK, name)
p := path.Join(m.Config(nfs.PATH), 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) != "" { // 下载源码 if m.Option(nfs.REPOS) != "" { // 下载源码
m.Cmd("web.code.git.repos", mdb.CREATE, m.OptionSimple(nfs.REPOS), nfs.PATH, p) m.Cmd("web.code.git.repos", mdb.CREATE, m.OptionSimple(nfs.REPOS), nfs.PATH, p)
} else { // 创建目录 } else { // 创建目录
nfs.MkdirAll(m, p) file.MkdirAll(p, ice.MOD_DIR)
} }
// 任务模板 // 目录文件
if m.Option(nfs.TEMPLATE) != "" { if m.Option(nfs.TEMPLATE) != "" {
for _, file := range []string{ for _, file := range []string{
ice.ETC_MISS_SH, ice.SRC_MAIN_SHY, ice.SRC_MAIN_GO, 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)) { if kit.FileExists(path.Join(p, file)) {
continue 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: case ice.GO_MOD:
kit.Rewrite(path.Join(p, file), func(line string) string { kit.Rewrite(path.Join(p, file), func(line string) string {
return kit.Select(line, "module "+name, strings.HasPrefix(line, "module")) 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")) 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) m.Optionv(cli.CMD_DIR, kit.Path(p))
return // 已经启动
} else if m.Cmd(SPACE, name).Length() > 0 {
return // 已经启动
}
defer m.ToastProcess()()
m.Optionv(cli.CMD_DIR, p)
m.Optionv(cli.CMD_ENV, kit.Simple( m.Optionv(cli.CMD_ENV, kit.Simple(
cli.CTX_OPS, "http://:"+m.Cmd(SERVE, ice.OptionFields("")).Append(tcp.PORT), 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.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), cli.USER, ice.Info.UserName, m.Configv(cli.ENV),
)) ))
m.Optionv(cli.CMD_OUTPUT, path.Join(p, ice.BIN_BOOT_LOG)) 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))) 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.Cmd(cli.DAEMON, bin, SPACE, tcp.DIAL, ice.DEV, ice.OPS, m.OptionSimple(mdb.NAME, RIVER))
m.Sleep3s() m.Sleep3s()
m.Option(cli.CMD_ENV, "") m.Option(cli.CMD_ENV, "")
m.Option(cli.CMD_OUTPUT, "") 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 ( const (
@ -102,8 +112,8 @@ const (
const DREAM = "dream" const DREAM = "dream"
func init() { func init() {
Index.Merge(&ice.Context{Commands: ice.Commands{ Index.MergeCommands(ice.Commands{
DREAM: {Name: "dream name path auto start", Help: "梦想家", Actions: ice.Actions{ DREAM: {Name: "dream name path auto start", Help: "梦想家", Actions: ice.MergeAction(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
m.Config("miss", _dream_miss) m.Config("miss", _dream_miss)
}}, }},
@ -129,10 +139,10 @@ func init() {
cli.STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) { 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, mdb.MODIFY, m.OptionSimple(mdb.NAME), mdb.STATUS, cli.STOP)
m.Cmd(SPACE, m.Option(mdb.NAME), ice.EXIT) 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) { 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)) m.Cmd(mdb.DELETE, m.Prefix(SPACE), "", mdb.HASH, m.OptionSimple(mdb.NAME))
} else { } else {
m.Cmd(mdb.DELETE, m.Prefix(SPACE), "", mdb.HASH, m.OptionSimple(mdb.NAME)) 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) { 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() m.ProcessRefresh30ms()
}}, }},
}, Hand: func(m *ice.Message, arg ...string) { }, mdb.HashAction("miss", _dream_miss)), Hand: func(m *ice.Message, arg ...string) {
if start := 0; len(arg) == 0 { if len(arg) == 0 {
_dream_list(m).SetAppend(mdb.TEXT) if _dream_list(m); !m.IsMobileUA() {
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() {
m.Display("/plugin/table.js?style=card") m.Display("/plugin/table.js?style=card")
} }
return return
} }
m.Cmdy(nfs.CAT, arg[1:], kit.Dict(nfs.DIR_ROOT, path.Join(ice.USR_LOCAL_WORK, arg[0])))
m.Option(nfs.DIR_ROOT, path.Join(m.Config(nfs.PATH), arg[0]))
m.Cmdy(nfs.CAT, arg[1:])
}}, }},
}, Configs: ice.Configs{ })
DREAM: {Name: DREAM, Help: "梦想家", Value: kit.Data(nfs.PATH, ice.USR_LOCAL_WORK, "miss", _dream_miss)},
}})
} }
var _dream_miss = `#! /bin/sh var _dream_miss = `#! /bin/sh

View File

@ -2,6 +2,7 @@ package web
import ( import (
"fmt" "fmt"
"io"
"net/http" "net/http"
"path" "path"
"strings" "strings"
@ -9,13 +10,15 @@ import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp" "shylinux.com/x/icebergs/base/tcp"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
const ( const (
STATUS = "status"
COOKIE = "cookie" COOKIE = "cookie"
STATUS = "status"
) )
func Render(msg *ice.Message, cmd string, args ...ice.Any) { 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]]] case COOKIE: // value [name [path [expire]]]
RenderCookie(msg, arg[0], arg[1:]...) 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]] 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) http.Redirect(msg.W, msg.R, arg[0], http.StatusSeeOther)
break break
} }
msg.W.Header().Set("Content-Disposition", fmt.Sprintf("filename=%s", kit.Select(path.Base(kit.Select(arg[0], msg.Option("filename"))), arg, 2))) 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])) 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: case ice.RENDER_RESULT:
if len(arg) > 0 { // [str [arg...]] if len(arg) > 0 { // [str [arg...]]
msg.W.Write([]byte(kit.Format(arg[0], args[1:]...))) msg.W.Write([]byte(kit.Format(arg[0], args[1:]...)))
} else { } else {
args = append(args, "length:", len(msg.Result())) args = append(args, nfs.SIZE, len(msg.Result()))
msg.W.Write([]byte(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: case ice.RENDER_JSON:
msg.W.Header().Set("Content-Type", "application/json") msg.W.Header().Set("Content-Type", "application/json")
msg.W.Write([]byte(arg[0])) 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.Echo(kit.Format(cmd, args...))
} }
msg.W.Header().Set(ContentType, ContentJSON) 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) { func RenderHeader(msg *ice.Message, key, value string) {
msg.W.Header().Set(key, value) 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 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, 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}) 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) { func RenderStatus(msg *ice.Message, code int, text string) {
http.Redirect(msg.W, msg.R, kit.MergeURL(arg[0], arg[1:]), http.StatusTemporaryRedirect) msg.W.WriteHeader(code)
msg.W.Write([]byte(text))
} }
func RenderRefresh(msg *ice.Message, arg ...string) { // url text delay func RenderRefresh(msg *ice.Message, arg ...string) { // url text delay
msg.Render(ice.RENDER_VOID) msg.Render(ice.RENDER_VOID)
@ -107,27 +121,18 @@ func RenderRefresh(msg *ice.Message, arg ...string) { // url text delay
</html> </html>
`, kit.Select("3", arg, 2), kit.Select(msg.Option(ice.MSG_USERWEB), arg, 0), kit.Select("loading...", arg, 1))) `, 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) { func RenderRedirect(msg *ice.Message, arg ...string) {
if mime != "" { http.Redirect(msg.W, msg.R, kit.MergeURL(arg[0], arg[1:]), http.StatusTemporaryRedirect)
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 RenderDownload(msg *ice.Message, arg ...ice.Any) { func RenderDownload(msg *ice.Message, arg ...ice.Any) {
Render(msg, ice.RENDER_DOWNLOAD, arg...) 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 { func Format(tag string, arg ...ice.Any) string {
return kit.Format("<%s>%s</%s>", tag, strings.Join(kit.Simple(arg), ""), tag) return kit.Format("<%s>%s</%s>", tag, strings.Join(kit.Simple(arg), ""), tag)
} }

View File

@ -12,7 +12,7 @@ import (
) )
func _route_travel(m *ice.Message, route string) { 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] { switch val[mdb.TYPE] {
case SERVER: // 远程查询 case SERVER: // 远程查询
if val[mdb.NAME] == ice.Info.NodeName { 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.Tables(func(value ice.Maps) {
m.PushAnchor(value[ROUTE], m.MergePod(value[ROUTE])) m.PushAnchor(value[ROUTE], m.MergePod(value[ROUTE]))
switch value[mdb.TYPE] { switch value[mdb.TYPE] {
case SERVER: case SERVER:
m.PushButton(tcp.START) m.PushButton(tcp.START, aaa.INVITE)
case WORKER: case WORKER:
fallthrough fallthrough
default: default:
@ -59,22 +58,19 @@ func _route_list(m *ice.Message) {
m.Push(ROUTE, ice.Info.NodeName) m.Push(ROUTE, ice.Info.NodeName)
m.PushAnchor(tcp.LOCALHOST, kit.Format("%s://%s:%s", u.Scheme, tcp.LOCALHOST, u.Port())) m.PushAnchor(tcp.LOCALHOST, kit.Format("%s://%s:%s", u.Scheme, tcp.LOCALHOST, u.Port()))
m.PushButton(tcp.START) m.PushButton(tcp.START)
return m
} }
const ROUTE = "route" const ROUTE = "route"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
ROUTE: {Name: ROUTE, Help: "路由器", Value: kit.Data(mdb.SHORT, ROUTE)},
}, Commands: ice.Commands{
ROUTE: {Name: "route route ctx cmd auto invite spide", Help: "路由器", Actions: ice.Actions{ 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) { aaa.INVITE: {Name: "invite", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(SPACE, m.Option(ROUTE), SPACE, aaa.INVITE, arg) m.Cmdy(SPACE, m.Option(ROUTE), SPACE, aaa.INVITE, arg).ProcessInner()
m.ProcessInner()
}}, }},
cli.START: {Name: "start name repos template", Help: "启动", Hand: func(m *ice.Message, arg ...string) { 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.Cmdy(SPACE, m.Option(ROUTE), DREAM, tcp.START, arg).ProcessInner()
m.ProcessInner()
}}, }},
ctx.COMMAND: {Name: "command", Help: "命令", Hand: func(m *ice.Message, arg ...string) { 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) 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) { SPIDE: {Name: "spide", Help: "架构图", Hand: func(m *ice.Message, arg ...string) {
if m.Option(ROUTE) == "" { // 路由列表 route if m.Option(ROUTE) == "" { // 路由列表 route
m.Cmdy(ROUTE).Cut(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 } 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) 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) { }, Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 || arg[0] == "" { // 路由列表 if len(arg) == 0 || arg[0] == "" { // 路由列表
if _route_travel(m, kit.Select("", arg, 0)); m.W != nil { if _route_travel(m, kit.Select("", arg, 0)); m.W != nil {
_route_list(m) _route_list(m).Sort("type,route")
m.Sort("type,route")
} }
} else if len(arg) == 1 || arg[1] == "" { // 模块列表 } else if len(arg) == 1 || arg[1] == "" { // 模块列表
@ -122,5 +117,5 @@ func init() {
m.ProcessField(ctx.ACTION, ctx.COMMAND) m.ProcessField(ctx.ACTION, ctx.COMMAND)
} }
}}, }},
}}) })
} }

View File

@ -2,6 +2,7 @@ package web
import ( import (
"encoding/json" "encoding/json"
"io"
"net/http" "net/http"
"net/url" "net/url"
"os" "os"
@ -17,12 +18,48 @@ import (
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp" "shylinux.com/x/icebergs/base/tcp"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
"shylinux.com/x/toolkits/logs"
) )
var rewriteList = []ice.Any{} var rewriteList = []ice.Any{}
func AddRewrite(cb ice.Any) { rewriteList = append(rewriteList, cb) } 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 { func _serve_domain(m *ice.Message) string {
if p := m.Config(DOMAIN); p != "" { if p := m.Config(DOMAIN); p != "" {
return p return p
@ -41,6 +78,36 @@ func _serve_domain(m *ice.Message) string {
return kit.Format("https://%s", m.R.Host) 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 { func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool {
if r.Header.Get("Index-Module") == "" { if r.Header.Get("Index-Module") == "" {
r.Header.Set("Index-Module", m.Prefix()) 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 { } else {
r.Header.Set(ice.MSG_USERIP, strings.Split(r.RemoteAddr, ":")[0]) 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 { if m.Config(LOGHEADERS) == ice.TRUE {
for k, v := range r.Header { 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() { defer func() {
m.Info("") m.Info("", meta)
for k, v := range w.Header() { 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 { for _, h := range rewriteList {
if m.Config(LOGHEADERS) == ice.TRUE { 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) { switch h := h.(type) {
case func(w http.ResponseWriter, r *http.Request) func(): 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 return false
} }
default: default:
m.Error(true, ice.ErrNotImplement) m.ErrorNotImplement(h)
} }
} }
return true 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) _serve_params(msg, r.URL.Path)
// 请求参数 // 解析参数
switch r.Header.Get(ContentType) { switch r.Header.Get(ContentType) {
case ContentJSON: case ContentJSON:
defer r.Body.Close() defer r.Body.Close()
@ -145,11 +213,12 @@ func _serve_handle(key string, cmd *ice.Command, msg *ice.Message, w http.Respon
default: default:
r.ParseMultipartForm(kit.Int64(kit.Select("4096", r.Header.Get(ContentLength)))) r.ParseMultipartForm(kit.Int64(kit.Select("4096", r.Header.Get(ContentLength))))
if r.ParseForm(); len(r.PostForm) > 0 { if r.ParseForm(); len(r.PostForm) > 0 {
meta := logs.FileLineMeta("")
for k, v := range r.PostForm { for k, v := range r.PostForm {
if len(v) > 1 { 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 { } 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) v[i], _ = url.QueryUnescape(p)
} }
} }
if msg.Optionv(k, v); k == ice.MSG_SESSID { msg.Optionv(k, v)
msg.Option(ice.MSG_SESSID, v[0])
RenderCookie(msg, v[0])
}
} }
for k, v := range r.PostForm { for k, v := range r.PostForm {
msg.Optionv(k, v) msg.Optionv(k, v)
} }
// 会话参数
for _, v := range r.Cookies() { for _, v := range r.Cookies() {
msg.Option(v.Name, v.Value) 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_USERWEB, _serve_domain(msg))
msg.Option(ice.MSG_USERADDR, kit.Select(r.RemoteAddr, r.Header.Get(ice.MSG_USERADDR))) 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_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) != "" { if msg.Option(ice.POD) != "" {
msg.Option(ice.MSG_USERPOD, 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 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 { if msg.Right(key, cmds) {
return cmds, false // 黑名单 return cmds, true
} else if msg.Config(kit.Keys(aaa.WHITE, ls[1])) == ice.TRUE {
return cmds, true // 白名单
} }
if msg.Warn(msg.Option(ice.MSG_USERNAME) == "", ice.ErrNotLogin, r.URL.Path) { 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 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 ( const (
WEB_LOGIN = "_login" WEB_LOGIN = "_login"
@ -279,120 +331,58 @@ func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.Merge(&ice.Context{Configs: ice.Configs{
SERVE: {Name: SERVE, Help: "服务器", Value: kit.Data( SERVE: {Name: SERVE, Help: "服务器", Value: kit.Data(
mdb.SHORT, mdb.NAME, mdb.FIELD, "time,status,name,port,dev", mdb.SHORT, mdb.NAME, mdb.FIELD, "time,status,name,port,dev",
tcp.LOCALHOST, ice.TRUE, aaa.BLACK, kit.Dict(), aaa.WHITE, kit.Dict( DOMAIN, "", tcp.LOCALHOST, ice.TRUE, LOGHEADERS, ice.FALSE,
LOGIN, ice.TRUE, SHARE, ice.TRUE, SPACE, ice.TRUE, nfs.PATH, kit.Dict(ice.PS, ice.USR_VOLCANOS),
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),
ice.VOLCANOS, kit.Dict(nfs.PATH, ice.USR_VOLCANOS, INDEX, "page/index.html", ice.VOLCANOS, kit.Dict(nfs.PATH, ice.USR_VOLCANOS, INDEX, "page/index.html",
nfs.REPOS, "https://shylinux.com/x/volcanos", nfs.BRANCH, nfs.MASTER, 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, ice.INTSHELL, kit.Dict(nfs.PATH, ice.USR_INTSHELL, INDEX, ice.INDEX_SH,
nfs.REPOS, "https://shylinux.com/x/intshell", nfs.BRANCH, nfs.MASTER, nfs.REPOS, "https://shylinux.com/x/intshell", nfs.BRANCH, nfs.MASTER,
), ice.REQUIRE, ".ish/pluged", ),
)}, )},
}, Commands: ice.Commands{ }, Commands: ice.Commands{
SERVE: {Name: "serve name auto start spide", Help: "服务器", Actions: ice.MergeAction(ice.Actions{ SERVE: {Name: "serve name auto start spide", Help: "服务器", Actions: ice.MergeAction(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
cli.NodeInfo(m, WORKER, ice.Info.PathName) cli.NodeInfo(m, WORKER, ice.Info.PathName)
AddRewrite(func(w http.ResponseWriter, r *http.Request) bool { for _, p := range []string{LOGIN, SHARE, SPACE, ice.VOLCANOS, ice.INTSHELL, ice.PUBLISH, ice.REQUIRE, ice.HELP, ice.CMD} {
w.Header().Add("Access-Control-Allow-Origin", "*") m.Cmd(aaa.ROLE, aaa.WHITE, aaa.VOID, p)
if r.Method == SPIDE_GET { }
switch r.URL.Path { _serve_rewrite(m)
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)
})
}}, }},
DOMAIN: {Name: "domain", Help: "域名", Hand: func(m *ice.Message, arg ...string) { 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]))) 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) { 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) _serve_start(m)
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)
}
}}, }},
"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 { // 模块列表 if len(arg) == 0 { // 模块列表
m.Display("/plugin/story/spide.js", "root", ice.ICE, "prefix", "spide")
_serve_spide(m, ice.PS, m.Target()) _serve_spide(m, ice.PS, m.Target())
m.StatusTimeCount() m.DisplayStorySpide(lex.PREFIX, m.ActionKey(), nfs.ROOT, m.MergeLink(ice.PS))
return
} }
}}, }},
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { }, mdb.HashAction())},
mdb.HashSelect(m, arg...)
}},
"/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...) 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...) m.RenderIndex(SERVE, ice.VOLCANOS, arg...)
}}, }},
"/require/src/": {Name: "/require/src/", Help: "代码库", Hand: func(m *ice.Message, arg ...string) { PP(ice.PUBLISH): {Name: "/publish/", Help: "定制化", Hand: func(m *ice.Message, arg ...string) {
if p := path.Join(ice.SRC, path.Join(arg...)); m.Option(ice.POD) != "" { _share_local(aaa.UserRoot(m), ice.USR_PUBLISH, path.Join(arg...))
m.RenderResult(m.Cmdx(SPACE, m.Option(ice.POD), nfs.CAT, p))
} else {
m.RenderDownload(p)
}
}}, }},
"/require/usr/": {Name: "/require/usr/", Help: "代码库", Hand: func(m *ice.Message, arg ...string) { PP(ice.REQUIRE): {Name: "/require/shylinux.com/x/volcanos/proto.js", Help: "代码库", Hand: func(m *ice.Message, arg ...string) {
m.RenderDownload(path.Join(ice.USR, path.Join(arg...))) _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) { PP(ice.REQUIRE, ice.SRC): {Name: "/require/src/", Help: "源代码", Hand: func(m *ice.Message, arg ...string) {
p := path.Join(ice.USR_VOLCANOS, "node_modules", path.Join(arg...)) _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 { if b, ok := ice.Info.Pack[p]; ok && len(b) > 0 {
} else if _, e := os.Stat(p); e != nil { } else if _, e := os.Stat(p); e != nil {
@ -400,18 +390,7 @@ func init() {
} }
m.RenderDownload(p) m.RenderDownload(p)
}}, }},
"/require/": {Name: "/require/", Help: "代码库", Hand: func(m *ice.Message, arg ...string) { PP(ice.HELP): {Name: "/help/", 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) {
if len(arg) == 0 { if len(arg) == 0 {
arg = append(arg, "tutor.shy") arg = append(arg, "tutor.shy")
} }

View File

@ -3,7 +3,6 @@ package web
import ( import (
"fmt" "fmt"
"net/http" "net/http"
"os"
"path" "path"
"strings" "strings"
"time" "time"
@ -16,33 +15,27 @@ import (
"shylinux.com/x/icebergs/base/ssh" "shylinux.com/x/icebergs/base/ssh"
"shylinux.com/x/icebergs/base/tcp" "shylinux.com/x/icebergs/base/tcp"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
"shylinux.com/x/toolkits/file"
) )
func _share_link(m *ice.Message, p string, arg ...ice.Any) string { func _share_render(m *ice.Message, arg ...string) {
p = kit.Select("", "/share/local/", !strings.HasPrefix(p, ice.PS)) + p ice.AddRender(ice.RENDER_DOWNLOAD, func(msg *ice.Message, cmd string, args ...ice.Any) string {
return tcp.ReplaceLocalhost(m, m.MergeURL2(p, arg...)) list := []string{}
} if msg.Option(ice.MSG_USERPOD) != "" {
func _share_repos(m *ice.Message, repos string, arg ...string) { list = append(list, ice.POD, msg.Option(ice.MSG_USERPOD))
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)))
case http.MethodPost: // 上传文件 arg := kit.Simple(args...)
m.Cmdy(CACHE, UPLOAD) if len(arg) > 1 {
m.Cmdy(CACHE, WATCH, m.Option(mdb.DATA), p) list = append(list, "filename", arg[0])
m.RenderResult(m.Option(nfs.PATH)) }
} 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) { func _share_cache(m *ice.Message, arg ...string) {
if pod := m.Option(ice.POD); m.PodCmd(CACHE, arg[0]) { 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) m.Option(ice.POD, pod)
_share_local(m, m.Append(nfs.FILE)) _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) { func _share_local(m *ice.Message, arg ...string) {
p := path.Join(arg...) p := path.Join(arg...)
@ -72,36 +65,51 @@ func _share_local(m *ice.Message, arg ...string) {
} }
} }
if m.Option(ice.POD) != "" { // 远程文件 if m.Option(ice.POD) == "" {
pp := path.Join(ice.VAR_PROXY, m.Option(ice.POD), p) m.RenderDownload(p)
cache := time.Now().Add(-time.Hour * 240000) return // 本地文件
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 strings.HasSuffix(p, path.Join(ice.USR_PUBLISH, ice.ORDER_JS)) {
if !kit.FileExists(p) { pp := path.Join(ice.VAR_PROXY, m.Option(ice.POD), p)
m.RenderResult("") cache, size := time.Now().Add(-time.Hour*240000), int64(0)
return 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) 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 ( const (
TOPIC = "topic" TOPIC = "topic"
@ -112,9 +120,9 @@ const (
SHARE_TOAST = "/share/toast/" SHARE_TOAST = "/share/toast/"
SHARE_CACHE = "/share/cache/" SHARE_CACHE = "/share/cache/"
SHARE_REPOS = "/share/repos/"
SHARE_PROXY = "/share/proxy/"
SHARE_LOCAL = "/share/local/" SHARE_LOCAL = "/share/local/"
SHARE_PROXY = "/share/proxy/"
SHARE_REPOS = "/share/repos/"
SHARE_LOCAL_AVATAR = "/share/local/avatar/" SHARE_LOCAL_AVATAR = "/share/local/avatar/"
SHARE_LOCAL_BACKGROUND = "/share/local/background/" SHARE_LOCAL_BACKGROUND = "/share/local/background/"
@ -122,26 +130,10 @@ const (
const SHARE = "share" const SHARE = "share"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
SHARE: {Name: SHARE, Help: "共享链", Value: kit.Data(
mdb.EXPIRE, "72h", mdb.FIELD, "time,hash,userrole,username,river,storm,type,name,text",
)},
}, Commands: ice.Commands{
SHARE: {Name: "share hash auto prunes", Help: "共享链", Actions: ice.MergeAction(ice.Actions{ SHARE: {Name: "share hash auto prunes", Help: "共享链", Actions: ice.MergeAction(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { 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 { _share_render(m)
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])
})
}}, }},
mdb.CREATE: {Name: "create type name text", Help: "创建", Hand: func(m *ice.Message, arg ...string) { 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)), 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.EchoQRCode(msg.Option(mdb.LINK))
m.ProcessInner() 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 { if m.PodCmd(SHARE, arg) && m.Length() > 0 {
return return
} }
if mdb.HashSelect(m, arg...); len(arg) > 0 { 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.PushQRCode(cli.QRCODE, link)
m.PushScript(ssh.SCRIPT, link) m.PushScript(ssh.SCRIPT, link)
m.PushAnchor(link) m.PushAnchor(link)
} else { } else {
m.Action(LOGIN) m.Action(LOGIN)
} }
m.PushAction(mdb.REMOVE)
m.StatusTimeCount()
}}, }},
"/share/": {Name: "/share/", Help: "共享链", Hand: func(m *ice.Message, arg ...string) { PP(SHARE): {Name: "/share/", Help: "共享链", Hand: func(m *ice.Message, arg ...string) {
m.Option(SHARE, kit.Select(m.Option(SHARE), arg, 0)) msg := m.Cmd(SHARE, 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()) { if kit.Int(msg.Append(mdb.TIME)) < kit.Int(msg.FormatTime()) {
m.RenderResult("共享超时") m.RenderResult("共享超时")
return return
} else { }
switch msg.Append(mdb.TYPE) { switch msg.Append(mdb.TYPE) {
case LOGIN: case LOGIN:
if sessid := aaa.SessCreate(m, msg.Append(aaa.USERNAME)); m.Option(ice.MSG_USERWEB) == "" { sessid := aaa.SessCreate(m, msg.Append(aaa.USERNAME))
m.RenderRedirect(ice.PS, ice.MSG_SESSID, sessid) m.RenderRedirect(ice.PS, ice.MSG_SESSID, sessid)
} else { default:
RenderCookie(m, sessid) m.RenderIndex(SERVE, ice.VOLCANOS)
RenderRedirect(m, ice.PS)
}
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: {Name: "/share/cache/", Help: "缓存池", Hand: func(m *ice.Message, arg ...string) {
_share_cache(m, arg...) _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: {Name: "/share/local/", Help: "文件夹", Hand: func(m *ice.Message, arg ...string) {
_share_local(m, arg...) _share_local(m, arg...)
}}, }},
SHARE_LOCAL_AVATAR: {Name: "avatar", Help: "头像", Hand: func(m *ice.Message, arg ...string) { 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)) 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) { 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)) 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:]...)
}},
})
} }

View File

@ -41,109 +41,117 @@ func _space_domain(m *ice.Message) (link string) {
return tcp.ReplaceLocalhost(m, link) return tcp.ReplaceLocalhost(m, link)
} }
func _space_dial(m *ice.Message, dev, name string, arg ...string) { 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) m.Cmd(SPIDE, mdb.CREATE, ice.DEV, dev)
dev = ice.DEV dev = ice.DEV
} }
value := m.Richs(SPIDE, nil, dev, nil) msg := m.Cmd(SPIDE, dev)
client := kit.Value(value, tcp.CLIENT).(ice.Map) host := msg.Append(kit.Keys(tcp.CLIENT, tcp.HOSTNAME))
proto := strings.Replace(msg.Append(kit.Keys(tcp.CLIENT, tcp.PROTOCOL)), ice.HTTP, "ws", 1)
host := kit.Format(client[tcp.HOSTNAME]) uri := kit.MergeURL(proto+"://"+host+PP(SPACE), mdb.TYPE, ice.Info.NodeType, mdb.NAME, name, SHARE, ice.Info.CtxShare, RIVER, ice.Info.CtxRiver, arg)
proto := strings.Replace(kit.Format(client[tcp.PROTOCOL]), "http", "ws", 1) u := kit.ParseURL(uri)
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)
m.Go(func() { m.Go(func() {
u := kit.ParseURL(uri)
redial := m.Configm(REDIAL)
frame := m.Target().Server().(*Frame) frame := m.Target().Server().(*Frame)
for i := 0; i >= 0 && i < kit.Int(redial["c"]); i++ { ls := strings.Split(host, ":")
msg := m.Spawn() args := kit.SimpleKV("type,name,host,port", proto, dev, ls[0], kit.Select("443", ls, 1))
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), "")
// 连接成功 redial := m.Configm(REDIAL)
if i = 0; _space_handle(msg, true, frame.send, s, dev) { a, b, c := kit.Int(redial["a"]), kit.Int(redial["b"]), kit.Int(redial["c"])
i = -2 // 连接关闭 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) 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 { func _space_handle(m *ice.Message, safe bool, frame *Frame, c *websocket.Conn, name string) bool {
for running := true; running; { for {
if _, b, e := c.ReadMessage(); m.Warn(e, SPACE, name) { _, b, e := c.ReadMessage()
if m.Warn(e, SPACE, name) {
break 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 { socket, msg := c, m.Spawn(b)
if msg.Option(ice.MSG_HANDLE) == ice.TRUE { target := kit.Simple(msg.Optionv(ice.MSG_TARGET))
msg.Debug("what %v %v", msg.FormatMeta(), msg.FormatStack(1, 100)) source := kit.Simple(msg.Optionv(ice.MSG_SOURCE), name)
continue msg.Log("recv", "%v->%v %s %v", source, target, msg.Detailv(), msg.FormatMeta())
}
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)
}
} else if msg.Richs(SPACE, nil, target[0], func(key string, value ice.Map) { if len(target) == 0 { // 执行命令
if s, ok := value[SOCKET].(*websocket.Conn); ok { if msg.Option(ice.MSG_HANDLE) == ice.TRUE { // 异常请求
socket, source, target = s, source, target[1:] msg.Debug("what %v %v", msg.FormatMeta(), msg.FormatStack(1, 100))
_space_echo(msg, source, target, socket, kit.Select("", target)) continue
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 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 return false
} }
func _space_exec(msg *ice.Message, source, target []string, c *websocket.Conn, name string) { 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() 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) { func _space_echo(msg *ice.Message, source, target []string, c *websocket.Conn, name string) {
msg.Optionv(ice.MSG_SOURCE, source) msg.Optionv(ice.MSG_SOURCE, source)
msg.Optionv(ice.MSG_TARGET, target) msg.Optionv(ice.MSG_TARGET, target)
if e := c.WriteMessage(1, []byte(msg.FormatMeta())); msg.Warn(e) { if e := c.WriteMessage(1, []byte(msg.FormatMeta())); msg.Warn(e) { // 回复失败
msg.Cmd(mdb.DELETE, msg.PrefixKey(), "", mdb.HASH, mdb.NAME, name) mdb.HashRemove(msg, mdb.NAME, name)
c.Close() c.Close()
return return
} }
target = append([]string{name}, target...) target = append([]string{name}, target...)
msg.Log("send", "%v->%v %v %v", source, target, msg.Detailv(), msg.FormatMeta()) 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 return
} }
target := kit.Split(space, ice.PT, ice.PT) // 生成参数
m.Warn(m.Richs(SPACE, nil, target[0], func(key string, value ice.Map) { for _, k := range kit.Simple(m.Optionv(ice.MSG_OPTS)) {
if socket, ok := value[SOCKET].(*websocket.Conn); !m.Warn(!ok, ice.ErrNotFound, SOCKET) { switch k {
case ice.MSG_DETAIL, ice.MSG_CMDS, ice.MSG_SESSID:
// 复制选项
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)
default: 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 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) { 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)) 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)), ".", "_", ":", "_"))) name := strings.ToLower(m.Option(mdb.NAME, kit.ReplaceAll(kit.Select(text, m.Option(mdb.NAME)), ".", "_", ":", "_")))
kind := kit.Select(WORKER, m.Option(mdb.TYPE)) kind := kit.Select(WORKER, m.Option(mdb.TYPE))
args := append([]string{mdb.TYPE, kind, mdb.NAME, name}, m.OptionSimple(SHARE, RIVER)...) args := append([]string{mdb.TYPE, kind, mdb.NAME, name}, m.OptionSimple(SHARE, RIVER)...)
m.Go(func() { m.Go(func() {
h := m.Rich(SPACE, nil, kit.Dict(SOCKET, s, mdb.TEXT, kit.Select(text, m.Option(mdb.TEXT)), args)) m.Optionv(mdb.TARGET, s)
m.Log_CREATE(SPACE, name, mdb.TYPE, kind) mdb.HashCreate(m, mdb.TEXT, kit.Select(text, m.Option(mdb.TEXT)), args)
switch kind { switch kind {
case CHROME: // 交互节点 case CHROME: // 交互节点
defer m.Confv(SPACE, kit.Keys(mdb.HASH, h), "") defer mdb.HashRemove(m, mdb.NAME, name)
m.Go(func(msg *ice.Message) { m.Go(func(msg *ice.Message) {
switch m.Option(ice.CMD) { switch m.Option(ice.CMD) {
case cli.PWD: case cli.PWD:
@ -261,13 +245,36 @@ func _space_fork(m *ice.Message) {
default: // 服务节点 default: // 服务节点
m.Event(SPACE_START, args...) m.Event(SPACE_START, args...)
defer m.Event(SPACE_STOP, 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), s, name)
_space_handle(m, false, m.Target().Server().(*Frame).send, 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 ( const (
CHROME = "chrome" CHROME = "chrome"
@ -278,13 +285,12 @@ const (
WORKER = "worker" WORKER = "worker"
) )
const ( const (
SPACE_START = "space.start"
SPACE_STOP = "space.stop"
SOCKET = "socket"
BUFFER = "buffer" BUFFER = "buffer"
REDIAL = "redial" REDIAL = "redial"
TIMEOUT = "timeout" TIMEOUT = "timeout"
SPACE_START = "space.start"
SPACE_STOP = "space.stop"
) )
const SPACE = "space" const SPACE = "space"
@ -298,16 +304,23 @@ func init() {
}, Commands: ice.Commands{ }, Commands: ice.Commands{
SPACE: {Name: "space name cmd auto invite", Help: "空间站", Actions: ice.MergeAction(ice.Actions{ SPACE: {Name: "space name cmd auto invite", Help: "空间站", Actions: ice.MergeAction(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { 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) { 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) 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) { 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)) _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) { aaa.INVITE: {Name: "invite", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
for _, k := range []string{ice.MISC, ice.CORE, ice.BASE} { 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_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) _space_fork(m)
}}, }},
}}) }})

View File

@ -23,109 +23,100 @@ import (
) )
func _spide_create(m *ice.Message, name, address string) { func _spide_create(m *ice.Message, name, address string) {
if uri, e := url.Parse(address); e == nil && address != "" { if uri, e := url.Parse(address); !m.Warn(e != nil || address == "") {
if m.Richs(SPIDE, nil, name, func(key string, value ice.Map) { dir, file := path.Split(uri.EscapedPath())
kit.Value(value, "client.hostname", uri.Host) mdb.HashCreate(m, CLIENT_NAME, name)
kit.Value(value, "client.url", address) mdb.HashSelectUpdate(m, name, func(value ice.Map) {
}) == nil { value[SPIDE_COOKIE] = kit.Dict()
dir, file := path.Split(uri.EscapedPath()) value[SPIDE_HEADER] = kit.Dict()
m.Echo(m.Rich(SPIDE, nil, kit.Dict( value[SPIDE_CLIENT] = kit.Dict(
SPIDE_COOKIE, kit.Dict(), SPIDE_HEADER, kit.Dict(), SPIDE_CLIENT, kit.Dict( mdb.NAME, name, SPIDE_METHOD, SPIDE_POST, "url", address,
mdb.NAME, name, SPIDE_METHOD, SPIDE_POST, "url", address, tcp.PROTOCOL, uri.Scheme, tcp.HOSTNAME, uri.Host,
tcp.PROTOCOL, uri.Scheme, tcp.HOSTNAME, uri.Host, nfs.PATH, dir, nfs.FILE, file, "query", uri.RawQuery,
nfs.PATH, dir, nfs.FILE, file, "query", uri.RawQuery, cli.TIMEOUT, "600s", LOGHEADERS, ice.FALSE,
cli.TIMEOUT, "600s", LOGHEADERS, ice.FALSE, )
), })
)))
}
m.Log_CREATE(SPIDE, name, ADDRESS, address) m.Log_CREATE(SPIDE, name, ADDRESS, address)
} }
} }
func _spide_list(m *ice.Message, arg ...string) { func _spide_list(m *ice.Message, arg ...string) {
m.Richs(SPIDE, nil, arg[0], func(key string, value ice.Map) { // 缓存方法
// 缓存方式 cache, save := "", ""
cache, save := "", "" switch arg[1] {
switch arg[1] { case SPIDE_RAW:
case "url": cache, arg = arg[1], arg[1:]
m.Echo("%v", kit.Value(value, "client.url")) case SPIDE_MSG:
return cache, arg = arg[1], arg[1:]
case SPIDE_RAW: case SPIDE_SAVE:
cache, arg = arg[1], arg[1:] cache, save, arg = arg[1], arg[2], arg[2:]
case SPIDE_MSG: case SPIDE_CACHE:
cache, arg = arg[1], arg[1:] 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) msg := mdb.HashSelect(m.Spawn(), arg[0])
method := kit.Select(SPIDE_POST, client[SPIDE_METHOD]) method := kit.Select(SPIDE_POST, msg.Append(CLIENT_METHOD))
switch arg = arg[1:]; arg[0] { switch arg = arg[1:]; arg[0] {
case SPIDE_GET: case SPIDE_GET:
method, arg = SPIDE_GET, arg[1:] method, arg = SPIDE_GET, arg[1:]
case SPIDE_PUT: case SPIDE_PUT:
method, arg = SPIDE_PUT, arg[1:] method, arg = SPIDE_PUT, arg[1:]
case SPIDE_POST: case SPIDE_POST:
method, arg = SPIDE_POST, arg[1:] method, arg = SPIDE_POST, arg[1:]
case SPIDE_DELETE: case SPIDE_DELETE:
method, arg = SPIDE_DELETE, arg[1:] 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...) mdb.HashSelectDetail(m, msg.Append(CLIENT_NAME), func(value ice.Map) {
// 构造请求
req, e := http.NewRequest(method, kit.MergeURL2(kit.Format(client["url"]), uri, arg), body)
if m.Warn(e, ice.ErrNotFound, uri) {
return
}
// 请求配置
_spide_head(m, req, head, value) _spide_head(m, req, head, value)
})
// 发送请求 // 发送请求
res, e := _spide_send(m, req, kit.Format(client[cli.TIMEOUT])) res, e := _spide_send(m, req, kit.Format(msg.Append("client.timeout")))
if m.Warn(e, ice.ErrNotFound, uri) { if m.Warn(e, ice.ErrNotFound, uri) {
return 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 { mdb.HashSelectUpdate(m, msg.Append(CLIENT_NAME), func(value ice.Map) {
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))
// 缓存配置
for _, v := range res.Cookies() { for _, v := range res.Cookies() {
kit.Value(value, kit.Keys(SPIDE_COOKIE, v.Name), v.Value) kit.Value(value, kit.Keys(SPIDE_COOKIE, v.Name), v.Value)
m.Log_IMPORT(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) { func _spide_body(m *ice.Message, method string, arg ...string) (io.Reader, ice.Maps, []string) {
head := ice.Maps{} head := ice.Maps{}
@ -284,7 +275,7 @@ func _spide_save(m *ice.Message, cache, save, uri string, res *http.Response) {
case SPIDE_CACHE: case SPIDE_CACHE:
m.Optionv(RESPONSE, res) m.Optionv(RESPONSE, res)
m.Cmdy(CACHE, DOWNLOAD, res.Header.Get(ContentType), uri) m.Cmdy(CACHE, DOWNLOAD, res.Header.Get(ContentType), uri)
m.Echo(m.Append(DATA)) m.Echo(m.Append(mdb.DATA))
default: default:
b, _ := ioutil.ReadAll(res.Body) b, _ := ioutil.ReadAll(res.Body)
@ -302,25 +293,30 @@ func _spide_save(m *ice.Message, cache, save, uri string, res *http.Response) {
} }
const ( const (
// 缓存方法
SPIDE_RAW = "raw" SPIDE_RAW = "raw"
SPIDE_MSG = "msg" SPIDE_MSG = "msg"
SPIDE_SAVE = "save" SPIDE_SAVE = "save"
SPIDE_CACHE = "cache" SPIDE_CACHE = "cache"
// 请求方法
SPIDE_GET = "GET" SPIDE_GET = "GET"
SPIDE_PUT = "PUT" SPIDE_PUT = "PUT"
SPIDE_POST = "POST" SPIDE_POST = "POST"
SPIDE_DELETE = "DELETE" SPIDE_DELETE = "DELETE"
// 请求参数
SPIDE_BODY = "body" SPIDE_BODY = "body"
SPIDE_FORM = "form" SPIDE_FORM = "form"
SPIDE_PART = "part" SPIDE_PART = "part"
SPIDE_JSON = "json"
SPIDE_DATA = "data" SPIDE_DATA = "data"
SPIDE_FILE = "file" SPIDE_FILE = "file"
SPIDE_JSON = "json"
// 响应数据
SPIDE_RES = "content_data" SPIDE_RES = "content_data"
// 请求头
Bearer = "Bearer" Bearer = "Bearer"
Authorization = "Authorization" Authorization = "Authorization"
ContentType = "Content-Type" ContentType = "Content-Type"
@ -328,6 +324,7 @@ const (
UserAgent = "User-Agent" UserAgent = "User-Agent"
Accept = "Accept" Accept = "Accept"
// 数据格式
ContentFORM = "application/x-www-form-urlencoded" ContentFORM = "application/x-www-form-urlencoded"
ContentJSON = "application/json" ContentJSON = "application/json"
ContentHTML = "text/html" ContentHTML = "text/html"
@ -340,30 +337,30 @@ const (
SPIDE_HEADER = "header" SPIDE_HEADER = "header"
SPIDE_COOKIE = "cookie" SPIDE_COOKIE = "cookie"
CLIENT_NAME = "client.name"
CLIENT_METHOD = "client.method"
CLIENT_URL = "client.url"
LOGHEADERS = "logheaders"
FORM = "form" FORM = "form"
ADDRESS = "address" ADDRESS = "address"
REQUEST = "request" REQUEST = "request"
RESPONSE = "response" RESPONSE = "response"
CLIENT_NAME = "client.name" MERGE = "merge"
CLIENT_URL = "client.url" SUBMIT = "submit"
LOGHEADERS = "logheaders"
MERGE = "merge"
) )
const SPIDE = "spide" const SPIDE = "spide"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
SPIDE: {Name: SPIDE, Help: "蜘蛛侠", Value: kit.Data(mdb.SHORT, CLIENT_NAME, mdb.FIELD, "time,client.name,client.url", LOGHEADERS, ice.FALSE)},
}, Commands: 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{ 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) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
conf := m.Confm(cli.RUNTIME, "conf") conf := m.Confm(cli.RUNTIME, cli.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.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["ctx_dev"])) 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["ctx_shy"])) 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") m.Cmd(aaa.ROLE, aaa.WHITE, aaa.VOID, SPIDE, SUBMIT)
}}, }},
mdb.CREATE: {Name: "create name address", Help: "添加", Hand: func(m *ice.Message, arg ...string) { mdb.CREATE: {Name: "create name address", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
_spide_create(m, m.Option(mdb.NAME), m.Option(ADDRESS)) _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) { 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:])) 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) { 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") 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] == "") { if len(arg) < 2 || arg[0] == "" || (len(arg) > 3 && arg[3] == "") {
mdb.HashSelect(m, kit.Slice(arg, 0, 1)...) mdb.HashSelect(m, kit.Slice(arg, 0, 1)...).Sort(CLIENT_NAME)
m.Sort("client.name") } else {
return _spide_list(m, arg...)
} }
_spide_list(m, arg...)
}}, }},
SPIDE_GET: {Name: "GET url key value run", Help: "蜘蛛侠", Hand: func(m *ice.Message, arg ...string) {
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) {
m.Echo(kit.Formats(kit.UnMarshal(m.Cmdx(SPIDE, ice.DEV, SPIDE_RAW, SPIDE_GET, arg[0], arg[1:])))) 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{ SPIDE_POST: {Name: "POST url key value run", Help: "蜘蛛侠", Hand: func(m *ice.Message, arg ...string) {
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) {
m.Echo(kit.Formats(kit.UnMarshal(m.Cmdx(SPIDE, ice.DEV, SPIDE_RAW, SPIDE_POST, arg[0], arg[1:])))) 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{ SPIDE_DELETE: {Name: "DELETE url key value run", Help: "蜘蛛侠", Hand: func(m *ice.Message, arg ...string) {
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) {
m.Echo(kit.Formats(kit.UnMarshal(m.Cmdx(SPIDE, ice.DEV, SPIDE_RAW, SPIDE_DELETE, arg[0], arg[1:])))) m.Echo(kit.Formats(kit.UnMarshal(m.Cmdx(SPIDE, ice.DEV, SPIDE_RAW, SPIDE_DELETE, arg[0], arg[1:]))))
}}, }},
}}) })
} }

View File

@ -11,6 +11,8 @@ import (
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp" "shylinux.com/x/icebergs/base/tcp"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
"shylinux.com/x/toolkits/logs"
"shylinux.com/x/toolkits/task"
) )
type Frame struct { type Frame struct {
@ -20,21 +22,37 @@ type Frame struct {
*http.ServeMux *http.ServeMux
send map[string]*ice.Message send map[string]*ice.Message
lock task.Lock
} }
func (web *Frame) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (frame *Frame) getSend(key string) (*ice.Message, bool) {
if _serve_main(web.Message, w, r) { defer frame.lock.RLock()()
web.ServeMux.ServeHTTP(w, r) 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{} return &Frame{}
} }
func (web *Frame) Begin(m *ice.Message, arg ...string) ice.Server { func (frame *Frame) Begin(m *ice.Message, arg ...string) ice.Server {
web.send = map[string]*ice.Message{} frame.send = map[string]*ice.Message{}
return web 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{} list := map[*ice.Context]string{}
m.Travel(func(p *ice.Context, s *ice.Context) { m.Travel(func(p *ice.Context, s *ice.Context) {
if frame, ok := s.Server().(*Frame); ok { if frame, ok := s.Server().(*Frame); ok {
@ -42,19 +60,20 @@ func (web *Frame) Start(m *ice.Message, arg ...string) bool {
return return
} }
frame.ServeMux = http.NewServeMux() frame.ServeMux = http.NewServeMux()
meta := logs.FileLineMeta("")
// 级联路由 // 级联路由
msg := m.Spawn(s) msg := m.Spawn(s)
if pframe, ok := p.Server().(*Frame); ok && pframe.ServeMux != nil { if pframe, ok := p.Server().(*Frame); ok && pframe.ServeMux != nil {
route := ice.PS + s.Name + ice.PS 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)) pframe.Handle(route, http.StripPrefix(path.Dir(route), frame))
list[s] = path.Join(list[p], route) list[s] = path.Join(list[p], route)
} }
// 静态路由 // 静态路由
m.Confm(SERVE, kit.Keym(nfs.PATH), func(key string, value string) { 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)))) 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] != '/' { if s != sub || k[0] != '/' {
return 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)) 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) { frame.HandleFunc(k, func(frame http.ResponseWriter, r *http.Request) {
m.TryCatch(msg.Spawn(), true, func(msg *ice.Message) { 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) m.Event(SERVE_START)
defer m.Event(SERVE_STOP) 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) { switch cb := m.OptionCB(SERVE).(type) {
case func(http.Handler): case func(http.Handler):
cb(web) // 启动框架 cb(frame) // 启动框架
default: default:
m.Cmd(tcp.SERVER, tcp.LISTEN, mdb.TYPE, WEB, m.OptionSimple(mdb.NAME, tcp.HOST, tcp.PORT), func(l net.Listener) { 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) 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 return true
} }
func (web *Frame) Close(m *ice.Message, arg ...string) bool { func (frame *Frame) Close(m *ice.Message, arg ...string) bool {
return m.Done(true) 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 ( const (
SERVE_START = "serve.start" SERVE_START = "serve.start"
@ -106,8 +126,7 @@ var Index = &ice.Context{Name: WEB, Help: "网络模块"}
func init() { func init() {
ice.Index.Register(Index, &Frame{}, ice.Index.Register(Index, &Frame{},
SERVE, SPACE, DREAM, ROUTE, BROAD, SERVE, SPACE, DREAM,
SHARE, SPIDE, CACHE, STORY, SHARE, CACHE, SPIDE, ROUTE,
BROAD,
) )
} }

View File

@ -359,7 +359,7 @@ func init() {
case func(string, *Matrix): case func(string, *Matrix):
cb(h, mat) cb(h, mat)
default: default:
m.Error(true, ice.ErrNotImplement) m.ErrorNotImplement(cb)
} }
m.Echo(h) m.Echo(h)
}}, }},
@ -400,7 +400,7 @@ func init() {
case func(string, int, []string, int, *lex.Stream) (int, []string): case func(string, int, []string, int, *lex.Stream) (int, []string):
return cb(nhash, hash, word, begin, stream) return cb(nhash, hash, word, begin, stream)
default: default:
m.Error(true, ice.ErrNotImplement) m.ErrorNotImplement(cb)
} }
return hash, word return hash, word
}, mat.index(m, NPAGE, m.Option(NPAGE)), stream, 1) }, mat.index(m, NPAGE, m.Option(NPAGE)), stream, 1)

View File

@ -95,7 +95,7 @@ func _exp_true(m *ice.Message, arg string) bool {
const SCRIPT = "script" const SCRIPT = "script"
func init() { 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{ 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) { 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)) m.Cmd(MATRIX, mdb.CREATE, m.Option(mdb.NAME))
@ -214,5 +214,5 @@ func init() {
}) })
m.Resultv(stack.res) m.Resultv(stack.res)
}}, }},
}}) })
} }

57
conf.go
View File

@ -17,7 +17,6 @@ const (
SUCCESS = "success" SUCCESS = "success"
FAILURE = "failure" FAILURE = "failure"
PROCESS = "process" PROCESS = "process"
RESTART = "restart"
OF = " of " OF = " of "
INIT = "init" INIT = "init"
@ -107,14 +106,18 @@ const ( // DIR
PLUGIN_INPUT = "/plugin/input" PLUGIN_INPUT = "/plugin/input"
PLUGIN_STORY = "/plugin/story" PLUGIN_STORY = "/plugin/story"
PLUGIN_LOCAL = "/plugin/local" PLUGIN_LOCAL = "/plugin/local"
NODE_MODULES = "node_modules"
ISH_PLUGED = ".ish/pluged"
FAVICON = "favicon.ico" FAVICON = "favicon.ico"
PROTO_JS = "proto.js" PROTO_JS = "proto.js"
FRAME_JS = "frame.js" FRAME_JS = "frame.js"
INDEX_JS = "index.js" INDEX_JS = "index.js"
ORDER_JS = "order.js" ORDER_JS = "order.js"
ORDER_SH = "order.sh" ORDER_SH = "order.sh"
INDEX_SH = "index.sh" INDEX_SH = "index.sh"
INDEX_IML = "index.iml"
TUTOR_SHY = "tutor.shy"
USR_LOCAL = "usr/local" USR_LOCAL = "usr/local"
USR_LOCAL_GO = "usr/local/go" USR_LOCAL_GO = "usr/local/go"
@ -159,6 +162,8 @@ const ( // DIR
ICE_BIN = "ice.bin" ICE_BIN = "ice.bin"
GO_SUM = "go.sum" GO_SUM = "go.sum"
GO_MOD = "go.mod" GO_MOD = "go.mod"
CTX_DAEMON = "ctx_daemon"
) )
const ( // MSG const ( // MSG
MSG_DETAIL = "detail" MSG_DETAIL = "detail"
@ -206,23 +211,26 @@ const ( // MSG
MSG_STORM = "sess.storm" MSG_STORM = "sess.storm"
MSG_TOAST = "sess.toast" MSG_TOAST = "sess.toast"
MSG_LOCAL = "sess.local" MSG_LOCAL = "sess.local"
MSG_FILES = "file.system"
) )
const ( // RENDER const ( // RENDER
RENDER_RAW = "_raw"
RENDER_VOID = "_void"
RENDER_JSON = "_json"
RENDER_STATUS = "_status" 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_REDIRECT = "_redirect"
RENDER_DOWNLOAD = "_download" 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 const ( // PROCESS
PROCESS_LOCATION = "_location" PROCESS_LOCATION = "_location"
@ -369,4 +377,13 @@ const ( // gdb
LISTEN = "listen" LISTEN = "listen"
HAPPEN = "happen" HAPPEN = "happen"
FILELINE = "fileline" FILELINE = "fileline"
RESTART = "restart"
ERROR = "error"
OPEN = "open"
CLOSE = "close"
START = "start"
STOP = "stop"
BEGIN = "begin"
END = "end"
) )

View File

@ -146,7 +146,7 @@ const (
const ACTION = "action" const ACTION = "action"
func init() { 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{ 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) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
for _, cmd := range []string{ for _, cmd := range []string{
@ -193,5 +193,5 @@ func init() {
// 执行命令 // 执行命令
_action_exec(m, arg[0], arg[1], arg[2], arg[3:]...) _action_exec(m, arg[0], arg[1], arg[2], arg[3:]...)
}}, }},
}}) })
} }

View File

@ -51,9 +51,40 @@ func _cmd_file(m *ice.Message, arg ...string) bool {
const CMD = "cmd" const CMD = "cmd"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
CMD: {Name: CMD, Help: "命令", Value: kit.Data(mdb.SHORT, "type", nfs.PATH, nfs.PWD)}, CMD: {Name: "cmd path auto upload up home", Help: "命令", Actions: ice.MergeAction(ice.Actions{
}, Commands: ice.Commands{ 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{ "/cmd/": {Name: "/cmd/", Help: "命令", Actions: ice.MergeAction(ice.Actions{
ice.CTX_INIT: {Name: "_init", Help: "初始化", Hand: func(m *ice.Message, arg ...string) { 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") 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...))) // 文件 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)
}},
}})
} }

View File

@ -11,11 +11,7 @@ import (
const FILES = "files" const FILES = "files"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
FILES: {Name: FILES, Help: "文件夹", Value: kit.Data(
mdb.SHORT, mdb.DATA, mdb.FIELD, "time,hash,type,name,size,data",
)},
}, Commands: ice.Commands{
FILES: {Name: "files hash auto upload", Help: "文件夹", Actions: ice.MergeAction(ice.Actions{ FILES: {Name: "files hash auto upload", Help: "文件夹", Actions: ice.MergeAction(ice.Actions{
web.UPLOAD: {Name: "upload", Help: "上传", Hand: func(m *ice.Message, arg ...string) { web.UPLOAD: {Name: "upload", Help: "上传", Hand: func(m *ice.Message, arg ...string) {
up := kit.Simple(m.Optionv(ice.MSG_UPLOAD)) 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]) 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...) mdb.HashSelect(m, arg...)
m.Tables(func(value ice.Maps) { m.Tables(func(value ice.Maps) {
link := web.SHARE_CACHE + value[mdb.DATA] link := web.SHARE_CACHE + value[mdb.DATA]
@ -34,5 +30,5 @@ func init() {
} }
}) })
}}, }},
}}) })
} }

View File

@ -10,7 +10,7 @@ import (
const GRANT = "grant" const GRANT = "grant"
func init() { 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{ 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) { mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
switch arg[0] { switch arg[0] {
@ -26,5 +26,5 @@ func init() {
}}, }},
mdb.INSERT: {Name: "insert space grant userrole username", Help: "添加"}, mdb.INSERT: {Name: "insert space grant userrole username", Help: "添加"},
}, mdb.ZoneAction(mdb.SHORT, web.SPACE, mdb.FIELD, "time,grant,userrole,username"))}, }, mdb.ZoneAction(mdb.SHORT, web.SPACE, mdb.FIELD, "time,grant,userrole,username"))},
}}) })
} }

View File

@ -8,7 +8,7 @@ import (
const INFO = "info" const INFO = "info"
func init() { func init() {
Index.Merge(&ice.Context{Commands: ice.Commands{ Index.MergeCommands(ice.Commands{
INFO: {Name: "info auto", Help: "信息", Actions: ice.Actions{ INFO: {Name: "info auto", Help: "信息", Actions: ice.Actions{
mdb.MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) { 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) 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.OptionFields(mdb.DETAIL)
m.Cmdy(mdb.SELECT, RIVER, "", mdb.HASH, mdb.HASH, m.Option(ice.MSG_RIVER)) m.Cmdy(mdb.SELECT, RIVER, "", mdb.HASH, mdb.HASH, m.Option(ice.MSG_RIVER))
}}, }},
}}) })
} }

View File

@ -42,6 +42,9 @@ func init() {
m.Echo(get(m, "place/v1/explore", m.OptionSimple("boundary,page_index"))) m.Echo(get(m, "place/v1/explore", m.OptionSimple("boundary,page_index")))
}}, }},
"search": {Name: "search", Help: "搜索", Hand: func(m *ice.Message, arg ...string) { "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"))) m.Echo(get(m, "place/v1/search", m.OptionSimple("keyword,boundary,page_index")))
}}, }},
"direction": {Name: "direction", Help: "导航", Hand: func(m *ice.Message, arg ...string) { "direction": {Name: "direction", Help: "导航", Hand: func(m *ice.Message, arg ...string) {

View File

@ -12,7 +12,7 @@ import (
const NODE = "node" const NODE = "node"
func init() { 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{ NODE: {Name: "node pod ctx cmd auto insert invite", Help: "设备", Actions: ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
m.Watch(web.DREAM_START, m.PrefixKey()) m.Watch(web.DREAM_START, m.PrefixKey())
@ -60,5 +60,5 @@ func init() {
} }
m.Cmdy(web.ROUTE, arg) m.Cmdy(web.ROUTE, arg)
}}, }},
}}) })
} }

View File

@ -10,7 +10,7 @@ import (
const OCEAN = "ocean" const OCEAN = "ocean"
func init() { func init() {
Index.Merge(&ice.Context{Commands: ice.Commands{ Index.MergeCommands(ice.Commands{
OCEAN: {Name: "ocean username auto insert invite", Help: "用户", Actions: ice.Actions{ OCEAN: {Name: "ocean username auto insert invite", Help: "用户", Actions: ice.Actions{
mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) { mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(aaa.USER, ice.OptionFields(aaa.USERNAME, aaa.USERNICK, aaa.USERZONE)) m.Cmdy(aaa.USER, ice.OptionFields(aaa.USERNAME, aaa.USERNICK, aaa.USERZONE))
@ -31,5 +31,5 @@ func init() {
}) })
m.PushAction(mdb.DELETE) m.PushAction(mdb.DELETE)
}}, }},
}}) })
} }

View File

@ -5,27 +5,22 @@ import (
"shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/ssh" "shylinux.com/x/icebergs/base/ssh"
kit "shylinux.com/x/toolkits"
) )
const PASTE = "paste" const PASTE = "paste"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
PASTE: {Name: PASTE, Help: "粘贴", Value: kit.Data(
mdb.SHORT, mdb.TEXT, mdb.FIELD, "time,hash,type,name,text",
)},
}, Commands: ice.Commands{
PASTE: {Name: "paste hash auto getClipboardData", Help: "粘贴", Actions: ice.MergeAction(ice.Actions{ PASTE: {Name: "paste hash auto getClipboardData", Help: "粘贴", Actions: ice.MergeAction(ice.Actions{
"getClipboardData": {Name: "getClipboardData", Help: "粘贴", Hand: func(m *ice.Message, arg ...string) { "getClipboardData": {Name: "getClipboardData", Help: "粘贴", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(PASTE, mdb.CREATE, arg) m.Cmdy(PASTE, mdb.CREATE, arg)
}}, }},
mdb.CREATE: {Name: "create type=text name=hi text:textarea=hi", 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 mdb.HashSelect(m, arg...); len(arg) > 0 {
m.PushScript(ssh.SCRIPT, m.Append(mdb.TEXT)) m.PushScript(ssh.SCRIPT, m.Append(mdb.TEXT))
m.PushQRCode(cli.QRCODE, m.Append(mdb.TEXT)) m.PushQRCode(cli.QRCODE, m.Append(mdb.TEXT))
} }
}}, }},
}}) })
} }

View File

@ -16,13 +16,8 @@ import (
const POD = "pod" const POD = "pod"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
POD: {Name: POD, Help: "节点", Value: kit.Data()}, "/pod/": {Name: "/pod/", Help: "节点", Actions: ctx.CmdAction(), Hand: func(m *ice.Message, arg ...string) {
}, 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) {
if strings.HasPrefix(m.R.Header.Get("User-Agent"), "curl") || strings.HasPrefix(m.R.Header.Get("User-Agent"), "Wget") { 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_USERNAME, "root")
m.Option(ice.MSG_USERROLE, "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:]...)) // m.Cmdy(web.SPACE, m.Option(ice.MSG_USERPOD), "web.chat."+ice.PS+path.Join(arg[1:]...))
} }
}}, }},
}}) })
} }

View File

@ -53,7 +53,7 @@ func _river_list(m *ice.Message) {
const RIVER = "river" const RIVER = "river"
func init() { 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{ 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) }}, 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) { mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
@ -134,7 +134,7 @@ func init() {
m.Cmdy(RIVER, arg) m.Cmdy(RIVER, arg)
} }
}}, }},
}}) })
} }
var _river_template = kit.Dict( var _river_template = kit.Dict(

View File

@ -2,7 +2,6 @@ package chat
import ( import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/web" "shylinux.com/x/icebergs/base/web"
kit "shylinux.com/x/toolkits" 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(ROOM), "", mdb.HASH, m.OptionSimple(mdb.ZONE))
m.Cmdy(mdb.INSERT, m.Prefix(JOIN), "", 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) { // 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.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, // 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), // 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) { // 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)) // 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) { }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) {
m.Fields(len(arg), "time,space", "time,zone") m.Fields(len(arg), "time,space", "time,zone")
if len(arg) == 0 { if len(arg) == 0 {

View File

@ -11,18 +11,14 @@ import (
const SCAN = "scan" const SCAN = "scan"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
SCAN: {Name: SCAN, Help: "扫码", Value: kit.Data(
mdb.SHORT, mdb.TEXT, mdb.FIELD, "time,hash,type,name,text",
)},
}, Commands: ice.Commands{
SCAN: {Name: "scan hash auto scanQRCode scanQRCode0", Help: "扫码", Meta: kit.Dict( SCAN: {Name: "scan hash auto scanQRCode scanQRCode0", Help: "扫码", Meta: kit.Dict(
ice.Display("scan.js"), ice.Display("scan.js"),
), Actions: ice.MergeAction(ice.Actions{ ), Actions: ice.MergeAction(ice.Actions{
"scanQRCode0": {Name: "scan create", Help: "本机扫码"}, "scanQRCode0": {Name: "scan create", Help: "本机扫码"},
"scanQRCode": {Name: "scan create", Help: "扫码"}, "scanQRCode": {Name: "scan create", Help: "扫码"},
mdb.CREATE: {Name: "create type=text name=hi text:textarea=hi", 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 mdb.HashSelect(m, arg...); len(arg) > 0 {
if m.Append(mdb.TYPE) == "image" { if m.Append(mdb.TYPE) == "image" {
m.PushImages("image", m.Append(mdb.TEXT)) m.PushImages("image", m.Append(mdb.TEXT))
@ -31,5 +27,5 @@ func init() {
m.PushQRCode(cli.QRCODE, m.Append(mdb.TEXT)) m.PushQRCode(cli.QRCODE, m.Append(mdb.TEXT))
} }
}}, }},
}}) })
} }

View File

@ -10,9 +10,9 @@ import (
const SEARCH = "search" const SEARCH = "search"
func init() { 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) { 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() m.Cmdy(m.Space(m.Option(ice.POD)), mdb.SEARCH, arg).StatusTimeCount()
}}, }},
}}) })
} }

View File

@ -12,16 +12,15 @@ import (
const SSO = "sso" const SSO = "sso"
func init() { func init() {
Index.Merge(&ice.Context{Commands: ice.Commands{ Index.MergeCommands(ice.Commands{
"/sso": {Name: "/sso", Help: "登录", Hand: func(m *ice.Message, arg ...string) { "/sso": {Name: "/sso", Help: "登录", Hand: func(m *ice.Message, arg ...string) {
if m.Option(ice.MSG_USERNAME) == "" { if m.Option(ice.MSG_USERNAME) == "" {
m.RenderIndex(web.SERVE, ice.VOLCANOS) m.RenderIndex(web.SERVE, ice.VOLCANOS)
return return
} }
sessid := m.Cmdx(web.SPACE, m.Option(web.SPACE), aaa.SESS, mdb.CREATE, 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.USERNAME, m.Option(ice.MSG_USERNAME),
aaa.USERROLE, m.Option(ice.MSG_USERROLE),
aaa.USERNICK, m.Option(ice.MSG_USERNICK), aaa.USERNICK, m.Option(ice.MSG_USERNICK),
) )
m.RenderRedirect(kit.MergeURL(m.Option(cli.BACK), ice.MSG_SESSID, sessid)) 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"))) // web.RenderCookie(m, sessid, web.CookieName(m.Option("back")))
// m.RenderRedirect(kit.MergeURL(m.Option("back"))) // m.RenderRedirect(kit.MergeURL(m.Option("back")))
}}, }},
}}) })
} }

View File

@ -14,7 +14,7 @@ func _storm_key(m *ice.Message, key ...ice.Any) string {
const STORM = "storm" const STORM = "storm"
func init() { 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{ STORM: {Name: "storm hash id auto insert create", Help: "应用", Actions: ice.Actions{
mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) { mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
if ctx.Inputs(m, arg[0]) { if ctx.Inputs(m, arg[0]) {
@ -88,5 +88,5 @@ func init() {
m.PushAction(mdb.EXPORT, mdb.IMPORT) m.PushAction(mdb.EXPORT, mdb.IMPORT)
} }
}}, }},
}}) })
} }

View File

@ -22,7 +22,7 @@ func init() {
mdb.TYPE: "text", mdb.NAME: "height", mdb.VALUE: "31", 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{ 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) { mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
switch arg[0] { 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.W.Header()[web.ContentType] = kit.Simple(web.ContentCSS)
m.RenderResult() m.RenderResult()
}}, }},
}}) })
} }

View File

@ -18,7 +18,7 @@ const (
) )
func init() { 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{ TRANS: {Name: "trans from to auto", Help: "传输", Actions: ice.MergeAction(ice.Actions{
SEND: {Name: "send", Help: "发送", Hand: func(m *ice.Message, arg ...string) { 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")), 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("") m.DisplayLocal("")
}}, }},
}}) })
} }

View File

@ -173,7 +173,7 @@ func init() {
const AUTOGEN = "autogen" const AUTOGEN = "autogen"
func init() { 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{ 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) { mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
switch arg[0] { 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))) _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.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) { 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_module(m, p)
_autogen_import(m, path.Join(ice.SRC, m.Option(cli.MAIN)), m.Option(mdb.ZONE), _autogen_mod(m, ice.GO_MOD)) _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) { }, Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(nfs.CAT, kit.Select("version.go", arg, 0), kit.Dict(nfs.DIR_ROOT, ice.SRC)) m.Cmdy(nfs.CAT, kit.Select("version.go", arg, 0), kit.Dict(nfs.DIR_ROOT, ice.SRC))
}}, }},
}}) })
} }

View File

@ -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) { if s, e := bench.HTTP(nconn, nreqs, list, func(req *http.Request, res *http.Response) {
n, _ := io.Copy(ioutil.Discard, res.Body) n, _ := io.Copy(ioutil.Discard, res.Body)
atomic.AddInt64(&body, n) atomic.AddInt64(&ndata, n)
}); m.Assert(e) { }); m.Assert(e) {
m.Echo("body: %s\n", kit.FmtSize(body)) m.Echo("ndata: %s\n", kit.FmtSize(ndata))
m.Echo(s.Show()) m.Echo(s.Show())
m.ProcessInner() m.ProcessInner()
} }
@ -61,7 +61,7 @@ const (
const BENCH = "bench" const BENCH = "bench"
func init() { 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{ 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: "添加"}, 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) { 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.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)) mdb.ZoneSelect(m, arg...).PushAction(kit.Select(mdb.REMOVE, ice.RUN, len(arg) > 0))
}}, }},
}}) })
} }

View File

@ -3,9 +3,7 @@ package code
import ( import (
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"io"
"io/ioutil" "io/ioutil"
"net/http"
"os" "os"
"path" "path"
"strings" "strings"
@ -13,7 +11,6 @@ import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/web"
kit "shylinux.com/x/toolkits" 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) m.Option(nfs.DIR_TYPE, nfs.CAT)
for _, k := range []string{ice.FAVICON, ice.PROTO_JS, ice.FRAME_JS} { 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/"} { for _, k := range []string{LIB, PAGE, PANEL, PLUGIN, "publish/client/nodejs/"} {
m.Cmd(nfs.DIR, k).Sort(nfs.PATH).Tables(func(value ice.Maps) { 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) fmt.Fprintln(f)
@ -67,50 +66,13 @@ func _binpack_ctx(m *ice.Message, f *os.File) {
const BINPACK = "binpack" const BINPACK = "binpack"
func init() { 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{ BINPACK: {Name: "binpack path auto create remove export", Help: "打包", Actions: ice.MergeAction(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
if kit.FileExists(path.Join(ice.USR_VOLCANOS, ice.PROTO_JS)) { if kit.FileExists(path.Join(ice.USR_VOLCANOS, ice.PROTO_JS)) {
m.Cmd(BINPACK, mdb.REMOVE) m.Cmd(BINPACK, mdb.REMOVE)
return 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) { 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) { if f, p, e := kit.Create(ice.SRC_BINPACK_GO); m.Assert(e) {
@ -122,6 +84,7 @@ func init() {
import ( import (
"encoding/base64" "encoding/base64"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/nfs"
) )
func init() { func init() {
@ -130,7 +93,9 @@ func init() {
defer fmt.Fprintln(f, ` defer fmt.Fprintln(f, `
for k, v := range pack { 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]])) m.Echo(string(ice.Info.Pack[arg[0]]))
}}, }},
}}) })
} }

View File

@ -15,7 +15,7 @@ import (
const CASE = "case" const CASE = "case"
func init() { 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{ 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) { mdb.CREATE: {Name: "create name address", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(web.SPIDE, mdb.CREATE, arg) 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.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]) m.Cmdy(cli.SYSTEM, "go", "test", nfs.PWD, "-v", "-run="+arg[1])
}}, }},
}}) })
} }

View File

@ -3,20 +3,32 @@ package code
import ( import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
const FAVOR = "favor" const FAVOR = "favor"
func init() { func init() {
Index.Merge(&ice.Context{Commands: ice.Commands{ Index.MergeCommands(ice.Commands{
FAVOR: {Name: "favor zone id auto insert", Help: "收藏夹", Actions: ice.MergeAction(ice.Actions{ 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: "添加"}, 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) { INNER: {Name: "inner", Help: "源码", Hand: func(m *ice.Message, arg ...string) {
m.ProcessCommand(INNER, m.OptionSplit("path,file,line"), arg...) 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.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))
}}, }},
}}) })
} }

View File

@ -7,11 +7,13 @@ import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/gdb"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp" "shylinux.com/x/icebergs/base/tcp"
"shylinux.com/x/icebergs/base/web" "shylinux.com/x/icebergs/base/web"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
"shylinux.com/x/toolkits/file"
) )
func _install_path(m *ice.Message, link string) string { 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) { 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]) 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 "" return ""
} }
func _install_download(m *ice.Message) { 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)) target := path.Join(ice.USR_LOCAL_DAEMON, m.Option(tcp.PORT))
source := _install_path(m, "") source := _install_path(m, "")
nfs.MkdirAll(m, target) file.MkdirAll(target, ice.MOD_DIR)
defer m.Echo(target) defer m.Echo(target)
if m.Option(INSTALL) == "" && kit.FileExists(kit.Path(source, "_install")) { 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): case func(string):
cb(p) cb(p)
default: default:
m.Error(true, ice.ErrNotImplement) m.ErrorNotImplement(cb)
} }
if m.Cmdy(cli.DAEMON, arg[1:], args); cli.IsSuccess(m) { 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.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) { func _install_service(m *ice.Message, arg ...string) {
arg = kit.Split(path.Base(arg[0]), "-.")[:1] arg = kit.Split(path.Base(arg[0]), "-.")[:1]
@ -152,11 +154,7 @@ const (
const INSTALL = "install" const INSTALL = "install"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
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{
INSTALL: {Name: "install name port path auto download", Help: "安装", Meta: kit.Dict(), Actions: ice.MergeAction(ice.Actions{ 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) { web.DOWNLOAD: {Name: "download link path", Help: "下载", Hand: func(m *ice.Message, arg ...string) {
_install_download(m) _install_download(m)
@ -188,7 +186,7 @@ func init() {
cli.STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) { cli.STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) {
_install_stop(m, arg...) _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) { switch len(arg) {
case 0: // 源码列表 case 0: // 源码列表
mdb.HashSelect(m, arg...) mdb.HashSelect(m, arg...)
@ -201,7 +199,7 @@ func init() {
m.Cmdy(nfs.CAT, kit.Select(nfs.PWD, arg, 2)) m.Cmdy(nfs.CAT, kit.Select(nfs.PWD, arg, 2))
} }
}}, }},
}}) })
} }
func InstallAction(args ...ice.Any) ice.Actions { func InstallAction(args ...ice.Any) ice.Actions {

View File

@ -22,9 +22,7 @@ func init() {
LOGIN_OAUTH = "https://github.com/login/oauth/" LOGIN_OAUTH = "https://github.com/login/oauth/"
API_GITHUB = "https://api.github.com/" API_GITHUB = "https://api.github.com/"
) )
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
OAUTH: {Name: OAUTH, Help: "授权", Value: kit.Data(mdb.FIELD, "time,hash,code,access_token,scope,token_type")},
}, Commands: ice.Commands{
OAUTH: {Name: "oauth hash auto", Help: "授权", Actions: ice.MergeAction(ice.Actions{ 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) { 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) 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.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)) 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 { if mdb.HashSelect(m, arg...).PushAction("user", "public", ACCESS_TOKEN, mdb.REMOVE); len(arg) == 0 {
m.Action(mdb.CREATE) 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")) 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))) m.RenderCmd(m.PrefixKey(), m.Cmdx(m.PrefixKey(), mdb.CREATE, m.OptionSimple(CODE)))
} }
}}, }},
}}) })
} }

View File

@ -24,11 +24,7 @@ const (
const PPROF = "pprof" const PPROF = "pprof"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
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{
PPROF: {Name: "pprof zone id auto", Help: "性能分析", Actions: ice.MergeAction(ice.Actions{ PPROF: {Name: "pprof zone id auto", Help: "性能分析", Actions: ice.MergeAction(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
web.AddRewrite(func(w http.ResponseWriter, r *http.Request) bool { 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.Cmd(cli.DAEMON, m.Configv(PPROF), "-http="+p, m.Option(BINNARY), m.Option(nfs.FILE))
m.Echo("http://%s/ui/top", p).ProcessInner() 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)) m.Fields(len(arg), "time,zone,count,binnary,service,seconds", m.Config(mdb.FIELD))
if mdb.ZoneSelect(m, arg...); len(arg) == 0 { if mdb.ZoneSelect(m, arg...); len(arg) == 0 {
m.EchoAnchor(m.MergeLink("/code/pprof/"))
m.PushAction(ice.RUN, mdb.REMOVE) m.PushAction(ice.RUN, mdb.REMOVE)
m.Action(mdb.CREATE) m.Action(mdb.CREATE)
return return
@ -83,5 +80,5 @@ func init() {
m.R.URL.Path = "/debug" + m.R.URL.Path m.R.URL.Path = "/debug" + m.R.URL.Path
http.DefaultServeMux.ServeHTTP(m.W, m.R) http.DefaultServeMux.ServeHTTP(m.W, m.R)
}}, }},
}}) })
} }

View File

@ -13,7 +13,7 @@ import (
const TEMPLATE = "template" const TEMPLATE = "template"
func init() { func init() {
Index.Merge(&ice.Context{Commands: ice.Commands{ Index.MergeCommands(ice.Commands{
TEMPLATE: {Name: "template name auto", Help: "模板", Actions: ice.MergeAction(ice.Actions{ TEMPLATE: {Name: "template name auto", Help: "模板", Actions: ice.MergeAction(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
for _, _template := range _template_list { for _, _template := range _template_list {
@ -40,7 +40,7 @@ func init() {
m.Action(mdb.CREATE) m.Action(mdb.CREATE)
} }
m.PushAction(nfs.DEFS, mdb.REMOVE) m.PushAction(nfs.DEFS, mdb.REMOVE)
}}}, }},
}) })
} }

View File

@ -158,82 +158,78 @@ func _vimer_go_complete(m *ice.Message, name string, arg ...string) *ice.Message
const VIMER = "vimer" const VIMER = "vimer"
func init() { func init() {
Index.Merge(&ice.Context{ Index.MergeCommands(ice.Commands{
Configs: ice.Configs{ VIMER: {Name: "vimer path=src/ file=main.go line=1 list", Help: "编辑器", Meta: kit.Dict(ice.DisplayLocal("", INNER)), Actions: ice.Actions{
VIMER: {Name: VIMER, Help: "编辑器", Value: kit.Data()}, 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)))
Commands: ice.Commands{ m.Cmdy(nfs.SAVE, path.Join(m.Option(nfs.PATH), m.Option(nfs.FILE)))
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"))
}}, }},
}}) 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"))
}},
})
} }

View File

@ -46,7 +46,6 @@ func _webpack_cache(m *ice.Message, dir string, write bool) {
m.Option(nfs.DIR_ROOT, "") m.Option(nfs.DIR_ROOT, "")
m.Option(nfs.DIR_DEEP, true) m.Option(nfs.DIR_DEEP, true)
m.Option(nfs.DIR_PACK, true)
m.Option(nfs.DIR_TYPE, nfs.CAT) m.Option(nfs.DIR_TYPE, nfs.CAT)
// m.Cmd(nfs.DIR, ice.SRC).Tables(func(value ice.Maps) { // m.Cmd(nfs.DIR, ice.SRC).Tables(func(value ice.Maps) {

View File

@ -22,8 +22,7 @@ func _xterm_socket(m *ice.Message, h, t string) {
m.Option(mdb.TEXT, t) m.Option(mdb.TEXT, t)
} }
func _xterm_get(m *ice.Message, h string, must bool) (f *os.File) { func _xterm_get(m *ice.Message, h string, must bool) (f *os.File) {
f, _ = mdb.HashCache(m, h, func() ice.Any { f, _ = mdb.HashTarget(m, h, func() ice.Any {
m.Debug("what %v", must)
if !must { if !must {
return nil return nil
} }
@ -49,7 +48,6 @@ func _xterm_get(m *ice.Message, h string, must bool) (f *os.File) {
}) })
return tty return tty
}).(*os.File) }).(*os.File)
m.Debug("what %v", f)
return return
} }

View File

@ -14,14 +14,10 @@ const (
const SALARY = "salary" const SALARY = "salary"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
SALARY: {Name: SALARY, Help: "工资", Value: kit.Data(
mdb.SHORT, MONTH, mdb.FIELD, "month,company,amount,income,tax",
)},
}, Commands: ice.Commands{
SALARY: {Name: "salary month auto create", Help: "工资", Actions: ice.MergeAction(ice.Actions{ SALARY: {Name: "salary month auto create", Help: "工资", Actions: ice.MergeAction(ice.Actions{
mdb.CREATE: {Name: "create month company amount income tax 公积金 养老保险 医疗保险 生育保险 工伤保险 失业保险 企业公积金 企业养老保险 企业医疗保险 企业生育保险 企业工伤保险 企业失业保险", Help: "添加"}, 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...) mdb.HashSelect(m, arg...)
amount, income, tax := 0, 0, 0 amount, income, tax := 0, 0, 0
m.Tables(func(value ice.Maps) { m.Tables(func(value ice.Maps) {
@ -31,5 +27,5 @@ func init() {
}) })
m.StatusTime(AMOUNT, amount, INCOME, income, TAX, tax) m.StatusTime(AMOUNT, amount, INCOME, income, TAX, tax)
}}, }},
}}) })
} }

View File

@ -12,7 +12,7 @@ import (
const COUNT = "count" const COUNT = "count"
func init() { 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( COUNT: {Name: "count begin_time@date end_time@date auto insert", Help: "倒计时", Meta: kit.Dict(
ice.Display(""), ice.Display(""),
), Actions: ice.MergeAction(ice.Actions{ ), Actions: ice.MergeAction(ice.Actions{
@ -44,5 +44,5 @@ func init() {
) )
}) })
}}, }},
}}) })
} }

View File

@ -65,7 +65,7 @@ const (
const PLAN = "plan" const PLAN = "plan"
func init() { 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( 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"), ice.Display("/plugin/local/team/plan.js"),
), Actions: ice.MergeAction(ice.Actions{ ), Actions: ice.MergeAction(ice.Actions{
@ -95,5 +95,5 @@ func init() {
_plan_list(m, begin_time, end_time) _plan_list(m, begin_time, end_time)
m.PushPodCmd(m.CommandKey(), arg...) m.PushPodCmd(m.CommandKey(), arg...)
}}, }},
}}) })
} }

View File

@ -56,11 +56,7 @@ const (
const TASK = "task" const TASK = "task"
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.MergeCommands(ice.Commands{
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{
TASK: {Name: "task zone id auto insert export import", Help: "任务", Actions: ice.MergeAction(ice.Actions{ 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) { 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)) 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) { END: {Name: "end", Help: "完成", Hand: func(m *ice.Message, arg ...string) {
_task_modify(m, STATUS, FINISH) _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 { if mdb.ZoneSelect(m, arg...); len(arg) > 0 {
status := map[string]int{} status := map[string]int{}
m.Tables(func(value ice.Maps) { m.Tables(func(value ice.Maps) {
@ -103,5 +99,5 @@ func init() {
m.Status(status) m.Status(status)
} }
}}, }},
}}) })
} }

View File

@ -10,7 +10,6 @@ import (
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/ssh" "shylinux.com/x/icebergs/base/ssh"
"shylinux.com/x/icebergs/base/web"
kit "shylinux.com/x/toolkits" 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/", 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) 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:]) m.Cmdy(arg[0], ctx.ACTION, ice.RUN, arg[2:])
}}, }},
ice.PLAY: {Name: "play", Help: "演示"}, ice.PLAY: {Name: "play", Help: "演示"},

11
data.go
View File

@ -1,6 +1,7 @@
package ice package ice
import ( import (
"path"
"strings" "strings"
"sync" "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): case func(*sync.Mutex, string, Map):
wg, mu := &sync.WaitGroup{}, &sync.Mutex{} wg, mu := &sync.WaitGroup{}, &sync.Mutex{}
defer wg.Wait() 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) wg.Add(1)
m.Go(func() { m.Go(func() {
defer wg.Done() defer wg.Done()
@ -102,7 +103,7 @@ func (m *Message) Richs(prefix string, chain Any, raw Any, cb Any) (res Map) {
}) })
}) })
default: 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 return res
@ -113,7 +114,7 @@ func (m *Message) Rich(prefix string, chain Any, data Any) string {
cache = kit.Data() cache = kit.Data()
m.Confv(prefix, chain, cache) 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 { func (m *Message) Grow(prefix string, chain Any, data Any) int {
cache := m.Confm(prefix, chain) cache := m.Confm(prefix, chain)
@ -121,7 +122,7 @@ func (m *Message) Grow(prefix string, chain Any, data Any) int {
cache = kit.Data() cache = kit.Data()
m.Confv(prefix, chain, cache) 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 { func (m *Message) Grows(prefix string, chain Any, match string, value string, cb Any) Map {
cache := m.Confm(prefix, chain) 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("0", strings.TrimPrefix(m.Option(CACHE_OFFEND), "-"))),
kit.Int(kit.Select("10", m.Option(CACHE_LIMIT))), kit.Int(kit.Select("10", m.Option(CACHE_LIMIT))),
match, value, cb) match, value, cb)

34
exec.go
View File

@ -3,6 +3,7 @@ package ice
import ( import (
"errors" "errors"
"io" "io"
"path"
"strings" "strings"
"time" "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) Sleep30ms(arg ...Any) *Message { return m.Sleep("30ms", arg...) }
func (m *Message) Sleep3s(arg ...Any) *Message { return m.Sleep("3s", 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) 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 { func (m *Message) Call(sync bool, cb func(*Message) *Message) *Message {
wait := make(chan bool, 2) wait := make(chan bool, 2)
@ -117,8 +95,9 @@ func (m *Message) Back(res *Message) *Message {
} }
return m 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) { m.TryCatch(m, true, func(m *Message) {
switch cb := cb.(type) { switch cb := cb.(type) {
case func(*Message): case func(*Message):
@ -126,7 +105,7 @@ func (m *Message) Go(cb Any) *Message {
case func(): case func():
cb() cb()
default: default:
m.Error(true, ErrNotImplement) m.ErrorNotImplement(cb)
} }
}) })
return nil return nil
@ -146,7 +125,8 @@ func (m *Message) Event(key string, arg ...string) *Message {
return m return m
} }
func (m *Message) Right(arg ...Any) bool { 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, 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)) ErrNotRight, kit.Join(kit.Simple(arg), PT), USERROLE, m.Option(MSG_USERROLE), FILELINE, kit.FileLine(2, 3))
} }

View File

@ -1,7 +1,6 @@
package ice package ice
import ( import (
"io"
"os" "os"
"path" "path"
"strings" "strings"
@ -36,6 +35,7 @@ var Info = struct {
NodeName string NodeName string
CtxShare string CtxShare string
CtxRiver string CtxRiver string
PidPath string
Help string Help string
cans string cans string
@ -45,7 +45,6 @@ var Info = struct {
names Map names Map
render map[string]func(*Message, string, ...Any) string 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) Log func(m *Message, p, l, s string)
}{ }{
Help: ` Help: `
@ -73,7 +72,6 @@ source: https://shylinux.com/x/icebergs
names: Map{}, names: Map{},
render: map[string]func(*Message, string, ...Any) string{}, 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) {}, Log: func(m *Message, p, l, s string) {},
} }

57
init.go
View File

@ -3,11 +3,11 @@ package ice
import ( import (
"os" "os"
"strings" "strings"
"sync"
"time" "time"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
log "shylinux.com/x/toolkits/logs" "shylinux.com/x/toolkits/conf"
"shylinux.com/x/toolkits/logs"
) )
type Frame struct{} type Frame struct{}
@ -16,8 +16,6 @@ func (f *Frame) Spawn(m *Message, c *Context, arg ...string) Server {
return &Frame{} return &Frame{}
} }
func (f *Frame) Begin(m *Message, arg ...string) Server { func (f *Frame) Begin(m *Message, arg ...string) Server {
defer m.Cost(LOG_BEGIN, ICE)
list := map[*Context]*Message{m.target: m} list := map[*Context]*Message{m.target: m}
m.Travel(func(p *Context, s *Context) { m.Travel(func(p *Context, s *Context) {
s.root = m.target s.root = m.target
@ -29,20 +27,17 @@ func (f *Frame) Begin(m *Message, arg ...string) Server {
return f return f
} }
func (f *Frame) Start(m *Message, arg ...string) bool { 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.Cap(CTX_STREAM, strings.Split(m.Time(), SP)[1])
m.Cmdy("mdb._init")
m.Cmdy(INIT, arg) m.Cmdy(INIT, arg)
for _, k := range kit.Split(Getenv("ctx_daemon")) { for _, k := range kit.Split(Getenv(CTX_DAEMON)) {
m.Start(k) m.Start(k)
} }
m.Cmd(arg) m.Cmd(arg)
return true return true
} }
func (f *Frame) Close(m *Message, arg ...string) bool { func (f *Frame) Close(m *Message, arg ...string) bool {
defer m.Cost(LOG_CLOSE, ICE)
list := map[*Context]*Message{m.target: m} list := map[*Context]*Message{m.target: m}
m.Travel(func(p *Context, s *Context) { m.Travel(func(p *Context, s *Context) {
if msg, ok := list[p]; ok && msg != nil { 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...) s.Close(list[s], arg...)
} }
}) })
conf.Close()
return true return true
} }
@ -57,7 +53,6 @@ var Index = &Context{Name: ICE, Help: "冰山模块", Configs: map[string]*Confi
HELP: {Value: kit.Data(INDEX, Info.Help)}, HELP: {Value: kit.Data(INDEX, Info.Help)},
}, Commands: map[string]*Command{ }, Commands: map[string]*Command{
CTX_INIT: {Hand: func(m *Message, arg ...string) { CTX_INIT: {Hand: func(m *Message, arg ...string) {
defer m.Cost(CTX_INIT)
m.root.Travel(func(p *Context, c *Context) { m.root.Travel(func(p *Context, c *Context) {
if cmd, ok := c.Commands[CTX_INIT]; ok && p != nil { if cmd, ok := c.Commands[CTX_INIT]; ok && p != nil {
c._command(m.Spawn(c), cmd, CTX_INIT, arg...) 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)) m.Echo(m.Config(INDEX))
}}, }},
EXIT: {Name: "exit", Help: "结束", Hand: func(m *Message, arg ...string) { 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...) defer m.Target().Close(m.root.Spawn(), arg...)
m.root.Option(EXIT, kit.Select("0", arg, 0))
m.Cmd(SOURCE, ETC_EXIT_SHY) m.Cmd(SOURCE, ETC_EXIT_SHY)
m.root.Cmd(CTX_EXIT) m.root.Cmd(CTX_EXIT)
}}, }},
CTX_EXIT: {Hand: func(m *Message, arg ...string) { 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) { m.root.Travel(func(p *Context, c *Context) {
if cmd, ok := c.Commands[CTX_EXIT]; ok && p != nil { if cmd, ok := c.Commands[CTX_EXIT]; ok && p != nil {
m.TryCatch(m.Spawn(c), true, func(msg *Message) { 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, var Pulse = &Message{time: time.Now(), code: 0,
meta: map[string][]string{}, data: Map{}, meta: map[string][]string{}, data: Map{},
source: Index, target: Index, Hand: true, source: Index, target: Index, Hand: true,
} }
var _exit = make(chan int, 1)
func init() { Index.root, Pulse.root = Index, Pulse } func init() { Index.root, Pulse.root = Index, Pulse }
func Run(arg ...string) string { 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 len(arg) == 0 { // 进程参数
if arg = append(arg, os.Args[1:]...); kit.Env("ctx_arg") != "" { arg = kit.Simple(arg, os.Args[1:], kit.Split(kit.Env("ctx_arg")))
arg = append(arg, kit.Split(kit.Env("ctx_arg"))...)
}
} }
Pulse.meta[MSG_DETAIL] = arg Pulse.meta[MSG_DETAIL] = arg
switch Index.Merge(Index).Begin(Pulse.Spawn(), arg...); kit.Select("", arg, 0) { switch Index.Merge(Index).Begin(Pulse.Spawn(), arg...); kit.Select("", arg, 0) {
case SERVE, SPACE: // 启动服务 case SERVE, SPACE: // 启动服务
switch strings.Split(os.Getenv("TERM"), "-")[0] { if Index.Start(Pulse, arg...) {
case "xterm", "screen": conf.Wait()
Info.Colors = true os.Exit(kit.Int(Pulse.Option(EXIT)))
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)
} }
default: // 执行命令 default: // 执行命令
if len(arg) == 0 { if logs.Disable(true); len(arg) == 0 {
arg = append(arg, HELP) arg = append(arg, HELP)
} }
Pulse.Cmd(INIT) Pulse.Cmd(INIT)
if Pulse.Cmdy(arg); strings.TrimSpace(Pulse.Result()) == "" { if Pulse.Cmdy(arg); strings.TrimSpace(Pulse.Result()) == "" {
Pulse.Table() Pulse.Table()
} }
Pulse.Sleep30ms()
} }
if !strings.HasSuffix(Pulse.Result(), NL) { if !strings.HasSuffix(Pulse.Result(), NL) {

118
logs.go
View File

@ -7,15 +7,13 @@ import (
"time" "time"
kit "shylinux.com/x/toolkits" 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 { func (m *Message) log(level string, str string, arg ...Any) *Message {
if log.LogDisable { _source := logs.FileLineMeta(logs.FileLine(3, 3))
return m // 禁用日志 if Info.Log != nil {
} Info.Log(m, m.FormatPrefix(), level, logs.Format(str, append(arg, _source)...)) // 日志分流
if str = strings.TrimSpace(kit.Format(str, arg...)); Info.Log != nil {
Info.Log(m, m.FormatPrefix(), level, str) // 日志分流
} }
// 日志颜色 // 日志颜色
@ -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 { switch level {
case LOG_INFO, LOG_SEND, LOG_RECV: 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, 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)...)
kit.Format("%4s->%-4s", m.source.Name, m.target.Name), prefix, level, str, suffix))
return m return m
} }
func (m *Message) join(arg ...Any) string { func (m *Message) join(arg ...Any) (string, []Any) {
args := kit.Simple(arg...) list, meta := []string{}, []Any{}
list := []string{} for i := 0; i < len(arg); i += 2 {
for i := 0; i < len(args); i += 2 { switch v := arg[i].(type) {
if i == len(args)-1 { case logs.Meta:
list = append(list, args[i]) i--
meta = append(meta, v)
continue
}
if key := strings.TrimSpace(kit.Format(arg[i])); i == len(arg)-1 {
list = append(list, key)
} else { } 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 { 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 { func (m *Message) Info(str string, arg ...Any) *Message {
return m.log(LOG_INFO, str, arg...) 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 { func (m *Message) Warn(err Any, arg ...Any) bool {
switch err := err.(type) { switch err := err.(type) {
case error: case error:
@ -91,21 +87,30 @@ func (m *Message) Warn(err Any, arg ...Any) bool {
case nil: case nil:
return false 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 { if len(arg) == 0 {
arg = append(arg, "", "") arg = append(arg, "", "")
} else if len(arg) == 1 { } else if len(arg) == 1 {
arg = append(arg, "") arg = append(arg, "")
} }
m.meta[MSG_RESULT] = kit.Simple(ErrWarn, arg[0], arg[1], SP, m.join(kit.Simple(arg[2:]...))) str, meta := m.join(arg[2:]...)
return true 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 { if err {
m.Echo(ErrWarn).Echo(str, arg...) m.error(arg...)
m.log(LOG_ERROR, m.FormatStack(1, 100)) 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()) m.log(LOG_ERROR, m.FormatChain())
return true return true
} }
@ -117,43 +122,62 @@ func (m *Message) Debug(str string, arg ...Any) {
} }
m.log(LOG_DEBUG, str, arg...) 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { func (m *Message) FormatTime() string {
return m.Time() return m.Time()
@ -187,7 +211,7 @@ func (m *Message) FormatStack(s, n int) string {
case "reflect", "runtime", "http", "task", "icebergs": case "reflect", "runtime", "http", "task", "icebergs":
default: default:
switch kit.Select("", ls, 1) { switch kit.Select("", ls, 1) {
case "(*Frame)": // case "(*Frame)":
default: default:
list = append(list, kit.Format("%s:%d\t%s", file, frame.Line, name)) 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