diff --git a/base/aaa/aaa.go b/base/aaa/aaa.go index 10048e71..a6426960 100644 --- a/base/aaa/aaa.go +++ b/base/aaa/aaa.go @@ -1,12 +1,19 @@ package aaa -import ice "shylinux.com/x/icebergs" +import ( + ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/mdb" +) const ( RSA = "rsa" ) const AAA = "aaa" -var Index = &ice.Context{Name: AAA, Help: "认证模块"} +var Index = &ice.Context{Name: AAA, Help: "认证模块", Commands: ice.Commands{ + ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { + ice.Info.Load(m).Cmd(ROLE, mdb.CREATE, TECH, VOID) + }}, +}} -func init() { ice.Index.Register(Index, nil, ROLE, SESS, TOTP, USER, OFFER, EMAIL, RSA) } +func init() { ice.Index.Register(Index, nil, OFFER, EMAIL, USER, TOTP, SESS, ROLE, RSA) } diff --git a/base/aaa/email.go b/base/aaa/email.go index f40d87f9..3aff97de 100644 --- a/base/aaa/email.go +++ b/base/aaa/email.go @@ -9,7 +9,9 @@ import ( ) const ( - SEND = "send" + SEND = "send" + SUBJECT = "subject" + CONTENT = "content" ) const EMAIL = "email" @@ -17,8 +19,6 @@ func init() { const ( TO = "to" ADMIN = "admin" - SUBJECT = "subject" - CONTENT = "content" SERVICE = "service" NL = "\r\n" DF = ": " @@ -26,16 +26,14 @@ func init() { Index.MergeCommands(ice.Commands{ EMAIL: {Name: "email name auto create", Help: "邮件", Actions: ice.MergeActions(ice.Actions{ SEND: {Name: "send to*='shylinux@163.com' subject*=hi content*:textarea=hello", Help: "发送", Hand: func(m *ice.Message, arg ...string) { - if m.Option(SERVICE) == "" { - m.Options(m.Cmd("", ADMIN).AppendSimple(SERVICE, USERNAME, PASSWORD)) - } + kit.If(m.Option(SERVICE) == "", func() { m.Options(m.Cmd("", ADMIN).AppendSimple(SERVICE, USERNAME, PASSWORD)) }) if m.Warn(m.Option(SERVICE) == "", ice.ErrNotValid, SERVICE) { return } content := []byte(kit.JoinKV(DF, NL, "From", m.Option(USERNAME), "To", m.Option(TO), "Subject", m.Option(SUBJECT), "Content-Type", "text/html; charset=UTF-8") + NL + NL + m.Option(CONTENT)) auth := smtp.PlainAuth("", m.Option(USERNAME), m.Option(PASSWORD), kit.Split(m.Option(SERVICE), ice.DF)[0]) m.Warn(smtp.SendMail(m.Option(SERVICE), auth, m.Option(USERNAME), kit.Split(m.Option(TO)), content)) - m.Logs(mdb.EXPORT, EMAIL, string(content)) + m.Logs(EMAIL, SEND, string(content)) }}, }, mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,name,service,username,password", ice.ACTION, SEND))}, }) diff --git a/base/aaa/offer.go b/base/aaa/offer.go index 60c6e1c4..23fbbde2 100644 --- a/base/aaa/offer.go +++ b/base/aaa/offer.go @@ -2,6 +2,7 @@ package aaa import ( ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/gdb" "shylinux.com/x/icebergs/base/mdb" kit "shylinux.com/x/toolkits" ) @@ -15,30 +16,26 @@ const OFFER = "offer" func init() { Index.MergeCommands(ice.Commands{ OFFER: {Name: "offer hash auto", Help: "邀请", Actions: ice.MergeActions(ice.Actions{ - INVITE: {Name: "invite email*='shylinux@163.com' content", Help: "邀请", Hand: func(m *ice.Message, arg ...string) { - h := mdb.HashCreate(m.Spawn(), m.OptionSimple(EMAIL, "content"), "from", m.Option(ice.MSG_USERNAME), mdb.STATUS, INVITE) - msg := m.Cmd("web.share", mdb.CREATE, mdb.TYPE, "field", mdb.NAME, m.PrefixKey(), mdb.TEXT, kit.Format(kit.List(h)), - kit.Dict(ice.MSG_USERNAME, m.Option(EMAIL), ice.MSG_USERNICK, VOID, ice.MSG_USERROLE, VOID)) - m.Cmd(EMAIL, SEND, m.Option(EMAIL), "welcome to contents, please continue", ice.Render(m, ice.RENDER_ANCHOR, kit.MergeURL(msg.Option(mdb.LINK), "debug", "true"))) + INVITE: {Name: "invite email*='shylinux@163.com' subject content", Help: "邀请", Hand: func(m *ice.Message, arg ...string) { + h := mdb.HashCreate(m.Spawn(), m.OptionSimple(EMAIL, SUBJECT, CONTENT), "from", m.Option(ice.MSG_USERNAME), mdb.STATUS, INVITE) + m.Cmd(EMAIL, SEND, m.Option(EMAIL), m.OptionDefault(SUBJECT, "welcome to contents, please continue"), + m.OptionDefault(CONTENT, ice.Render(m, ice.RENDER_ANCHOR, m.Cmdx("host", "publish", m.MergePodCmd("", "", mdb.HASH, h, gdb.DEBUG, ice.TRUE)))), + ) }}, ACCEPT: {Help: "接受", Hand: func(m *ice.Message, arg ...string) { if m.Warn(m.Option(mdb.HASH) == "", ice.ErrNotValid, mdb.HASH) { return } msg := m.Cmd("", m.Option(mdb.HASH)) - ls := kit.Split(msg.Option(EMAIL), ice.AT) - m.Cmd(USER, mdb.CREATE, USERNAME, msg.Option(EMAIL), USERNICK, ls[0], USERZONE, ls[1]) - m.ProcessOpen(kit.MergeURL2(m.Option(ice.MSG_USERWEB), ice.PS, ice.MSG_SESSID, SessCreate(m, msg.Option(EMAIL)))) - mdb.HashModify(m, m.OptionSimple(mdb.HASH), mdb.STATUS, ACCEPT) + if ls := kit.Split(msg.Append(EMAIL), ice.AT); !m.Warn(msg.Length() == 0 || len(ls) < 2, ice.ErrNotValid, m.Option(mdb.HASH)) { + m.Cmd(USER, mdb.CREATE, USERNICK, ls[0], USERNAME, msg.Append(EMAIL), USERZONE, ls[1]) + m.ProcessOpen(kit.MergeURL2(m.Option(ice.MSG_USERWEB), ice.PS, ice.MSG_SESSID, SessCreate(m, msg.Append(EMAIL)), mdb.HASH, "", gdb.DEBUG, ice.TRUE)) + mdb.HashModify(m, m.OptionSimple(mdb.HASH), mdb.STATUS, ACCEPT) + } }}, - }, mdb.HashAction(mdb.SHORT, mdb.UNIQ, mdb.FIELD, "time,hash,status,from,email,content"), RoleAction(ACCEPT)), Hand: func(m *ice.Message, arg ...string) { - if len(arg) == 0 && m.Option(ice.MSG_USERROLE) == VOID { - return - } - if mdb.HashSelect(m, arg...); len(arg) == 0 { - m.Action(INVITE) - } else { - m.PushAction(ACCEPT) + }, mdb.HashAction(mdb.SHORT, mdb.UNIQ, mdb.FIELD, "time,hash,status,from,email,title,content"), RoleAction(ACCEPT)), Hand: func(m *ice.Message, arg ...string) { + if !m.Warn(len(arg) == 0 && m.Option(ice.MSG_USERROLE) == VOID, ice.ErrNotRight) { + kit.If(mdb.HashSelect(m, arg...).FieldsIsDetail(), func() { m.PushAction(ACCEPT) }, func() { m.Action(INVITE) }) } }}, }) diff --git a/base/aaa/role.go b/base/aaa/role.go index 5b7147aa..6e5755b1 100644 --- a/base/aaa/role.go +++ b/base/aaa/role.go @@ -11,7 +11,12 @@ import ( ) func _role_keys(key ...string) string { - return strings.TrimPrefix(strings.TrimSuffix(strings.Replace(path.Join(strings.Replace(kit.Keys(key), ice.PT, ice.PS, -1)), ice.PS, ice.PT, -1), ice.PT), ice.PT) + if _key := kit.Slice(strings.Split(key[0], ice.PT), -1)[0]; _key != "" { + if c, ok := ice.Info.Index[_key].(*ice.Context); ok && kit.Keys(c.Prefix(), _key) == key[0] { + key[0] = _key + } + } + return strings.TrimPrefix(strings.TrimPrefix(strings.TrimSuffix(strings.Replace(path.Join(strings.Replace(kit.Keys(key), ice.PT, ice.PS, -1)), ice.PS, ice.PT, -1), ice.PT), ice.PT), "web.") } func _role_set(m *ice.Message, role, zone, key string, status bool) { m.Logs(mdb.INSERT, mdb.KEY, ROLE, ROLE, role, zone, key) @@ -22,33 +27,21 @@ func _role_black(m *ice.Message, role, key string) { _role_set(m, role, BLACK, k func _role_check(value ice.Map, key []string, ok bool) bool { white, black := value[WHITE].(ice.Map), value[BLACK].(ice.Map) for i := 0; i < len(key); i++ { - if v, o := white[kit.Join(key[:i+1], ice.PT)]; o && v == true { - ok = true - } - if v, o := black[kit.Join(key[:i+1], ice.PT)]; o && v == true { - ok = false - } + kit.If(white[kit.Join(key[:i+1], ice.PT)], func() { ok = true }) + kit.If(black[kit.Join(key[:i+1], ice.PT)], func() { ok = false }) } return ok } func _role_right(m *ice.Message, role string, key ...string) (ok bool) { - if role == ROOT { - return true - } - mdb.HashSelectDetail(m, kit.Select(VOID, role), func(value ice.Map) { - ok = _role_check(value, key, role == TECH) - }) - return + return role == ROOT || len(mdb.HashSelectDetails(m, kit.Select(VOID, role), func(value ice.Map) bool { return _role_check(value, key, role == TECH) })) > 0 } func _role_list(m *ice.Message, role string) *ice.Message { mdb.HashSelectDetail(m, kit.Select(VOID, role), func(value ice.Map) { kit.For(value[WHITE], func(k string, v ice.Any) { - m.Push(ROLE, kit.Value(value, mdb.NAME)) - m.Push(mdb.ZONE, WHITE).Push(mdb.KEY, k).Push(mdb.STATUS, v) + m.Push(ROLE, kit.Value(value, mdb.NAME)).Push(mdb.ZONE, WHITE).Push(mdb.KEY, k).Push(mdb.STATUS, v) }) kit.For(value[BLACK], func(k string, v ice.Any) { - m.Push(ROLE, kit.Value(value, mdb.NAME)) - m.Push(mdb.ZONE, BLACK).Push(mdb.KEY, k).Push(mdb.STATUS, v) + m.Push(ROLE, kit.Value(value, mdb.NAME)).Push(mdb.ZONE, BLACK).Push(mdb.KEY, k).Push(mdb.STATUS, v) }) }) return m.Sort(mdb.KEY).StatusTimeCount() @@ -69,7 +62,6 @@ const ROLE = "role" func init() { Index.MergeCommands(ice.Commands{ ROLE: {Name: "role role auto insert", Help: "角色", Actions: ice.MergeActions(ice.Actions{ - ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { m.Cmd("", mdb.CREATE, TECH, VOID) }}, mdb.CREATE: {Hand: func(m *ice.Message, arg ...string) { kit.For(arg, func(role string) { mdb.Rich(m, ROLE, nil, kit.Dict(mdb.NAME, role, BLACK, kit.Dict(), WHITE, kit.Dict())) @@ -91,18 +83,15 @@ func init() { }}, }) } - func RoleAction(key ...string) ice.Actions { return ice.Actions{ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { + cmd := m.PrefixKey() if c, ok := ice.Info.Index[m.CommandKey()].(*ice.Context); ok && c == m.Target() { - m.Cmd(ROLE, WHITE, VOID, m.CommandKey()) - m.Cmd(ROLE, BLACK, VOID, m.CommandKey(), ice.ACTION) + cmd = m.CommandKey() } - m.Cmd(ROLE, WHITE, VOID, m.PrefixKey()) - m.Cmd(ROLE, BLACK, VOID, m.PrefixKey(), ice.ACTION) - m.Cmd(ROLE, WHITE, VOID, strings.TrimPrefix(m.PrefixKey(), "web.")) - m.Cmd(ROLE, BLACK, VOID, strings.TrimPrefix(m.PrefixKey(), "web."), ice.ACTION) - kit.For(key, func(key string) { m.Cmd(ROLE, WHITE, VOID, m.PrefixKey(), ice.ACTION, key) }) + m.Cmd(ROLE, WHITE, VOID, cmd) + m.Cmd(ROLE, BLACK, VOID, cmd, ice.ACTION) + kit.For(key, func(key string) { m.Cmd(ROLE, WHITE, VOID, cmd, ice.ACTION, key) }) }}} } func WhiteAction(key ...string) ice.Actions { @@ -112,15 +101,6 @@ func WhiteAction(key ...string) ice.Actions { kit.For(key, func(key string) { m.Cmd(ROLE, WHITE, VOID, m.CommandKey(), ice.ACTION, key) }) }}} } -func BlackAction(key ...string) ice.Actions { - return ice.Actions{ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { - m.Cmd(ROLE, WHITE, VOID, m.CommandKey()) - kit.For(key, func(key string) { m.Cmd(ROLE, BLACK, VOID, m.CommandKey(), ice.ACTION, key) }) - }}} -} -func RoleRight(m *ice.Message, role string, key ...string) bool { - return m.Cmdx(ROLE, RIGHT, role, key) == ice.OK -} func Right(m *ice.Message, key ...ice.Any) bool { return m.Option(ice.MSG_USERROLE) == ROOT || !m.Warn(m.Cmdx(ROLE, RIGHT, m.Option(ice.MSG_USERROLE), key, logs.FileLineMeta(-1)) != ice.OK, ice.ErrNotRight, kit.Keys(key...), USERROLE, m.Option(ice.MSG_USERROLE), logs.FileLineMeta(-1)) diff --git a/base/aaa/sess.go b/base/aaa/sess.go index 1de7a572..837969ca 100644 --- a/base/aaa/sess.go +++ b/base/aaa/sess.go @@ -2,20 +2,17 @@ package aaa import ( ice "shylinux.com/x/icebergs" - "shylinux.com/x/icebergs/base/gdb" "shylinux.com/x/icebergs/base/mdb" kit "shylinux.com/x/toolkits" "shylinux.com/x/toolkits/logs" ) -func _sess_create(m *ice.Message, username string, arg ...string) (h string) { +func _sess_create(m *ice.Message, username string, arg ...string) { if msg := m.Cmd(USER, username); msg.Length() > 0 { - h = mdb.HashCreate(m, msg.AppendSimple(USERNICK, USERNAME, USERROLE), arg) + mdb.HashCreate(m, msg.AppendSimple(USERNICK, USERNAME, USERROLE), arg) } else { - h = mdb.HashCreate(m, m.OptionSimple(USERNICK, USERNAME, USERROLE), arg) + mdb.HashCreate(m, m.OptionSimple(USERNICK, USERNAME, USERROLE), arg) } - gdb.Event(m, SESS_CREATE, SESS, h, USERNAME, username) - return } func _sess_check(m *ice.Message, sessid string) { if val := mdb.HashSelectDetails(m, sessid, func(value ice.Map) bool { return !m.WarnTimeNotValid(value[mdb.TIME], sessid) }); len(val) > 0 { @@ -29,13 +26,8 @@ const ( ) const ( CHECK = "check" - GRANT = "grant" LOGIN = "login" LOGOUT = "logout" - SESSID = "sessid" -) -const ( - SESS_CREATE = "sess.create" ) const SESS = "sess" @@ -45,10 +37,8 @@ func init() { mdb.CREATE: {Name: "create username*", Hand: func(m *ice.Message, arg ...string) { _sess_create(m, m.Option(USERNAME), UA, m.Option(ice.MSG_USERUA), IP, m.Option(ice.MSG_USERIP)) }}, - CHECK: {Name: "check sessid*", Hand: func(m *ice.Message, arg ...string) { - _sess_check(m, m.Option(SESSID)) - }}, - }, mdb.HashAction(mdb.SHORT, mdb.UNIQ, mdb.FIELD, "time,hash,username,usernick,userrole,ua,ip", mdb.EXPIRE, mdb.MONTH, mdb.ImportantDataAction()))}, + CHECK: {Name: "check sessid*", Hand: func(m *ice.Message, arg ...string) { _sess_check(m, m.Option(ice.MSG_SESSID)) }}, + }, mdb.HashAction(mdb.EXPIRE, mdb.MONTH, mdb.SHORT, mdb.UNIQ, mdb.FIELD, "time,hash,usernick,username,userrole,ua,ip"), mdb.ImportantDataAction())}, }) } @@ -68,8 +58,5 @@ func SessAuth(m *ice.Message, value ice.Any, arg ...string) *ice.Message { ) } func SessLogout(m *ice.Message, arg ...string) { - if m.Option(ice.MSG_SESSID) == "" { - return - } - m.Cmd(SESS, mdb.REMOVE, kit.Dict(mdb.HASH, m.Option(ice.MSG_SESSID))) + kit.If(m.Option(ice.MSG_SESSID) != "", func() { m.Cmd(SESS, mdb.REMOVE, mdb.HASH, m.Option(ice.MSG_SESSID)) }) } diff --git a/base/aaa/totp.go b/base/aaa/totp.go index 327aef45..1e6ecfcb 100644 --- a/base/aaa/totp.go +++ b/base/aaa/totp.go @@ -23,12 +23,8 @@ func _totp_gen(per int64) string { } func _totp_get(key string, per int64, num int) string { buf, now := []byte{}, kit.Int64(time.Now().Unix()/per) - for i := 0; i < 8; i++ { - buf = append(buf, byte((uint64(now) >> uint64(((7 - i) * 8))))) - } - if l := len(key) % 8; l != 0 { - key += strings.Repeat(ice.EQ, 8-l) - } + kit.For(8, func(i int) { buf = append(buf, byte((uint64(now) >> uint64(((7 - i) * 8))))) }) + kit.If(len(key)%8, func(l int) { key += strings.Repeat(ice.EQ, 8-l) }) s, _ := base32.StdEncoding.DecodeString(strings.ToUpper(key)) hm := hmac.New(sha1.New, s) hm.Write(buf) diff --git a/base/gdb/gdb.go b/base/gdb/gdb.go index e7650e82..8b9c23b8 100644 --- a/base/gdb/gdb.go +++ b/base/gdb/gdb.go @@ -1,21 +1,35 @@ package gdb import ( + "fmt" "os" + "os/signal" + "syscall" "time" ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/mdb" kit "shylinux.com/x/toolkits" + "shylinux.com/x/toolkits/logs" ) type Frame struct{ s chan os.Signal } -func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server { - f.s = make(chan os.Signal, 3) - return f +func (f *Frame) listen(m *ice.Message, s int, arg ...string) { + signal.Notify(f.s, syscall.Signal(s)) + mdb.HashCreate(m, SIGNAL, s, arg) } -func (f *Frame) Start(m *ice.Message, arg ...string) bool { +func (f *Frame) Begin(m *ice.Message, arg ...string) { + f.s = make(chan os.Signal, 10) +} +func (f *Frame) Start(m *ice.Message, arg ...string) { + kit.If(ice.Info.PidPath, func(p string) { + if f, p, e := logs.CreateFile(p); e == nil { + defer f.Close() + fmt.Fprint(f, os.Getpid()) + m.Logs("save", PID, p) + } + }) t := kit.Duration(mdb.Conf(m, TIMER, kit.Keym(TICK))) enable := mdb.Conf(m, TIMER, kit.Keym("enable")) == ice.TRUE for { @@ -26,20 +40,13 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool { } case s, ok := <-f.s: if !ok { - return true + return } m.Cmd(SIGNAL, HAPPEN, SIGNAL, s) } } - return true -} -func (f *Frame) Close(m *ice.Message, arg ...string) bool { - close(f.s) - return true -} -func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server { - return &Frame{} } +func (f *Frame) Close(m *ice.Message, arg ...string) { close(f.s) } const GDB = "gdb" diff --git a/base/gdb/signal.go b/base/gdb/signal.go index c41736da..186379b0 100644 --- a/base/gdb/signal.go +++ b/base/gdb/signal.go @@ -1,7 +1,6 @@ package gdb import ( - "fmt" "os" "os/signal" "runtime" @@ -11,13 +10,11 @@ import ( "shylinux.com/x/icebergs/base/mdb" kit "shylinux.com/x/toolkits" "shylinux.com/x/toolkits/file" - "shylinux.com/x/toolkits/logs" ) func _signal_listen(m *ice.Message, s int, arg ...string) { if f, ok := m.Target().Server().(*Frame); ok { - signal.Notify(f.s, syscall.Signal(s)) - mdb.HashCreate(m, SIGNAL, s, arg) + f.listen(m, s, arg...) } } func _signal_action(m *ice.Message, arg ...string) { @@ -58,14 +55,6 @@ func init() { } _signal_listen(m, 2, mdb.NAME, "重启", ice.CMD, "exit 1") _signal_listen(m, 3, mdb.NAME, "退出", ice.CMD, "exit 0") - if ice.Info.PidPath == "" { - return - } - if f, p, e := logs.CreateFile(ice.Info.PidPath); e == nil { - defer f.Close() - fmt.Fprint(f, os.Getpid()) - m.Logs("save", PID, p) - } }}, LISTEN: {Name: "listen signal name cmd", Help: "监听", Hand: func(m *ice.Message, arg ...string) { _signal_listen(m, kit.Int(m.Option(SIGNAL)), arg...) diff --git a/base/log/log.go b/base/log/log.go index cdab1321..84decdbc 100644 --- a/base/log/log.go +++ b/base/log/log.go @@ -2,6 +2,7 @@ package log import ( "bufio" + "fmt" "path" ice "shylinux.com/x/icebergs" @@ -12,7 +13,6 @@ import ( ) type Log struct { - m *ice.Message p string l string s string @@ -20,56 +20,47 @@ type Log struct { type Frame struct{ p chan *Log } -func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server { +func (f *Frame) Begin(m *ice.Message, arg ...string) { f.p = make(chan *Log, ice.MOD_BUFS) - ice.Info.Log = func(m *ice.Message, p, l, s string) { f.p <- &Log{m: m, p: p, l: l, s: s} } - return f + ice.Info.Log = func(m *ice.Message, p, l, s string) { f.p <- &Log{p: p, l: l, s: s} } } -func (f *Frame) Start(m *ice.Message, arg ...string) bool { +func (f *Frame) Start(m *ice.Message, arg ...string) { m.Option("_lock", m.PrefixKey()) + mdb.Confm(m, FILE, nil, func(key string, value ice.Map) { + if f, p, e := logs.CreateFile(kit.Format(value[nfs.PATH])); e == nil { + value[FILE] = bufio.NewWriter(f) + m.Logs(nfs.SAVE, nfs.FILE, p) + } + }) for { select { case l, ok := <-f.p: if !ok { - return true + return } - for _, file := range []string{m.Conf(SHOW, kit.Keys(l.l, FILE)), BENCH} { + kit.For([]string{m.Conf(SHOW, kit.Keys(l.l, FILE)), BENCH}, func(file string) { if file == "" { - continue + return } - view := mdb.Confm(m, VIEW, m.Conf(SHOW, kit.Keys(l.l, VIEW))) bio := m.Confv(FILE, kit.Keys(file, FILE)).(*bufio.Writer) if bio == nil { - continue + return } - bio.WriteString(l.p) - bio.WriteString(ice.SP) - if ice.Info.Colors == true { - if p, ok := view[PREFIX].(string); ok { - bio.WriteString(p) - } - } - bio.WriteString(l.l) - bio.WriteString(ice.SP) - bio.WriteString(l.s) - if ice.Info.Colors == true { - if p, ok := view[SUFFIX].(string); ok { - bio.WriteString(p) - } - } - bio.WriteString(ice.NL) - bio.Flush() - } + defer bio.Flush() + defer fmt.Fprintln(bio) + fmt.Fprint(bio, l.p, ice.SP) + view := mdb.Confm(m, VIEW, m.Conf(SHOW, kit.Keys(l.l, VIEW))) + kit.If(ice.Info.Colors, func() { bio.WriteString(kit.Format(view[PREFIX])) }) + defer kit.If(ice.Info.Colors, func() { bio.WriteString(kit.Format(view[SUFFIX])) }) + fmt.Fprint(bio, l.l, ice.SP, l.s) + }) } } - return true } -func (f *Frame) Close(m *ice.Message, arg ...string) bool { +func (f *Frame) Close(m *ice.Message, arg ...string) { ice.Info.Log = nil close(f.p) - return true } -func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server { return &Frame{} } const ( PREFIX = "prefix" @@ -107,11 +98,6 @@ var Index = &ice.Context{Name: LOG, Help: "日志模块", Configs: ice.Configs{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { mdb.Confm(m, FILE, nil, func(key string, value ice.Map) { kit.For(value[mdb.LIST], func(index int, k string) { m.Conf(SHOW, kit.Keys(k, FILE), key) }) - if f, p, e := logs.CreateFile(kit.Format(value[nfs.PATH])); e == nil { - m.Cap(ice.CTX_STREAM, path.Base(p)) - value[FILE] = bufio.NewWriter(f) - m.Logs(nfs.SAVE, nfs.FILE, p) - } }) mdb.Confm(m, VIEW, nil, func(key string, value ice.Map) { kit.For(value[mdb.LIST], func(index int, k string) { m.Conf(SHOW, kit.Keys(k, VIEW), key) }) diff --git a/base/mdb/hash.go b/base/mdb/hash.go index e3053fb9..a4024b74 100644 --- a/base/mdb/hash.go +++ b/base/mdb/hash.go @@ -125,8 +125,9 @@ const HASH = "hash" func HashAction(arg ...Any) ice.Actions { return ice.Actions{ice.CTX_INIT: AutoConfig(append(kit.List(FIELD, HASH_FIELD), arg...)...), - ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) { HashSelectClose(m) }}, - + ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) { + HashSelectClose(m) + }}, INPUTS: {Hand: func(m *ice.Message, arg ...string) { HashInputs(m, arg) }}, CREATE: {Hand: func(m *ice.Message, arg ...string) { HashCreate(m, arg) }}, REMOVE: {Hand: func(m *ice.Message, arg ...string) { HashRemove(m, arg) }}, @@ -269,7 +270,7 @@ func HashSelectTarget(m *ice.Message, key string, create Any) (target Any) { func HashSelectClose(m *ice.Message) *ice.Message { HashSelectValue(m, func(value Map) { if c, ok := value[TARGET].(io.Closer); ok { - c.Close() + m.Warn(c.Close()) } delete(value, TARGET) }) diff --git a/base/ssh/script.go b/base/ssh/script.go index 6895f80e..f0f09060 100644 --- a/base/ssh/script.go +++ b/base/ssh/script.go @@ -33,21 +33,11 @@ type Frame struct { } func (f *Frame) prompt(m *ice.Message, list ...string) *Frame { - if f.source != STDIO { + if f.source != STDIO || m.Target().Cap(ice.CTX_STATUS) == ice.CTX_CLOSE { return f } - if m.Target().Cap(ice.CTX_STATUS) == ice.CTX_CLOSE { - return f - } - if len(list) == 0 { - list = append(list, f.ps1...) - } - if ice.Info.Colors { - fmt.Fprintf(f.stdout, "\r\033[2K") - } else { - fmt.Fprintf(f.stdout, "\r") - } - + kit.If(len(list) == 0, func() { list = append(list, f.ps1...) }) + fmt.Fprintf(f.stdout, kit.Select("\r", "\r\033[2K", ice.Info.Colors)) for _, v := range list { switch v { case mdb.COUNT: @@ -59,9 +49,7 @@ func (f *Frame) prompt(m *ice.Message, list ...string) *Frame { case TARGET: fmt.Fprintf(f.stdout, f.target.Name) default: - if ice.Info.Colors || v[0] != '\033' { - fmt.Fprintf(f.stdout, v) - } + kit.If(ice.Info.Colors || v[0] != '\033', func() { fmt.Fprintf(f.stdout, v) }) } } return f @@ -122,6 +110,9 @@ func (f *Frame) scan(m *ice.Message, h, line string) *Frame { f.ps2 = kit.Simple(mdb.Confv(m, PROMPT, kit.Keym(PS2))) // m.Options(MESSAGE, m, ice.LOG_DISABLE, ice.TRUE) m.I, m.O = f.stdin, f.stdout + if msg := m.Cmd("serve"); msg.Append("status") == "start" { + m.Cmd(PRINTF, kit.Dict(nfs.CONTENT, ice.NL+ice.Render(m, ice.RENDER_QRCODE, tcp.PublishLocalhost(m, kit.Format("http://localhost:%s", msg.Append(tcp.PORT)))))) + } ps, bio := f.ps1, bufio.NewScanner(f.stdin) for f.prompt(m, ps...); f.stdin != nil && bio.Scan(); f.prompt(m, ps...) { if len(bio.Text()) == 0 && h == STDIO { @@ -152,16 +143,15 @@ func (f *Frame) scan(m *ice.Message, h, line string) *Frame { return f } -func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server { +func (f *Frame) Begin(m *ice.Message, arg ...string) { switch strings.Split(os.Getenv(cli.TERM), "-")[0] { case "xterm", "screen": ice.Info.Colors = true default: ice.Info.Colors = false } - return f } -func (f *Frame) Start(m *ice.Message, arg ...string) bool { +func (f *Frame) Start(m *ice.Message, arg ...string) { m.Optionv(FRAME, f) switch f.source = kit.Select(STDIO, arg, 0); f.source { case STDIO: @@ -185,7 +175,7 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool { m.Option(ice.MSG_SCRIPT, f.source) f.target = m.Source() if msg := m.Cmd(nfs.CAT, f.source); msg.IsErr() { - return true + return } else { buf := bytes.NewBuffer(make([]byte, 0, ice.MOD_BUFS)) f.stdin, f.stdout = bytes.NewBufferString(msg.Result()), buf @@ -193,14 +183,12 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool { } f.scan(m, "", "") } - return true } -func (f *Frame) Close(m *ice.Message, arg ...string) bool { +func (f *Frame) Close(m *ice.Message, arg ...string) { if stdin, ok := f.stdin.(io.Closer); ok { stdin.Close() } f.stdin = nil - return true } func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server { return &Frame{} diff --git a/base/tcp/server.go b/base/tcp/server.go index 57b51b8b..c9455f5e 100644 --- a/base/tcp/server.go +++ b/base/tcp/server.go @@ -6,8 +6,16 @@ import ( ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/mdb" kit "shylinux.com/x/toolkits" + "shylinux.com/x/toolkits/logs" ) +func _broad_addr(m *ice.Message, host, port string) *net.UDPAddr { + if addr, e := net.ResolveUDPAddr("udp4", kit.Format("%s:%s", host, port)); !m.Warn(e, ice.ErrNotValid, host, port, logs.FileLineMeta(2)) { + return addr + } + return nil +} + type Listener struct { m *ice.Message h string @@ -26,7 +34,21 @@ func (l Listener) Close() error { return l.Listener.Close() } +func _server_udp(m *ice.Message, arg ...string) { + l, e := net.ListenUDP("udp4", _broad_addr(m, "0.0.0.0", m.Option(PORT))) + defer l.Close() + mdb.HashCreate(m, arg, kit.Dict(mdb.TARGET, l), STATUS, kit.Select(ERROR, OPEN, e == nil), ERROR, kit.Format(e)) + switch cb := m.OptionCB("").(type) { + case func(*net.UDPConn): + m.Assert(e) + cb(l) + } +} func _server_listen(m *ice.Message, arg ...string) { + if m.Option("type") == "udp4" { + _server_udp(m, arg...) + return + } l, e := net.Listen(TCP, m.Option(HOST)+":"+m.Option(PORT)) l = &Listener{m: m, h: mdb.HashCreate(m, arg, kit.Dict(mdb.TARGET, l), STATUS, kit.Select(ERROR, OPEN, e == nil), ERROR, kit.Format(e)), s: &Stat{}, Listener: l} if e == nil { @@ -63,9 +85,7 @@ const SERVER = "server" func init() { Index.MergeCommands(ice.Commands{ SERVER: {Name: "server hash auto prunes", Help: "服务器", Actions: ice.MergeActions(ice.Actions{ - LISTEN: {Name: "listen type name port=9030 host=", Hand: func(m *ice.Message, arg ...string) { - _server_listen(m, arg...) - }}, + LISTEN: {Name: "listen type name port=9030 host=", Hand: func(m *ice.Message, arg ...string) { _server_listen(m, arg...) }}, }, mdb.StatusHashAction(mdb.FIELD, "time,hash,status,type,name,host,port,error,nconn"), mdb.ClearOnExitHashAction())}, }) } diff --git a/base/web/broad.go b/base/web/broad.go index 0dc82ecc..7409c97c 100644 --- a/base/web/broad.go +++ b/base/web/broad.go @@ -29,16 +29,13 @@ func _broad_send(m *ice.Message, host, port string, remote_host, remote_port str } } func _broad_serve(m *ice.Message, port string) { - if s, e := net.ListenUDP("udp4", _broad_addr(m, "0.0.0.0", port)); m.Assert(e) { - defer s.Close() - m.Go(func() { - m.Sleep("10ms").Cmd(tcp.HOST, func(values ice.Maps) { - _broad_send(m, values[aaa.IP], port, "255.255.255.255", "9020", mdb.TYPE, ice.Info.NodeType, mdb.NAME, ice.Info.NodeName) - }) - }) + m.Cmd(tcp.HOST, func(values ice.Maps) { + _broad_send(m, values[aaa.IP], port, "255.255.255.255", "9020", mdb.TYPE, ice.Info.NodeType, mdb.NAME, ice.Info.NodeName) + }) + m.Cmd(tcp.SERVER, tcp.LISTEN, mdb.TYPE, "udp4", m.OptionSimple(mdb.NAME, tcp.HOST, tcp.PORT), func(l *net.UDPConn) { buf := make([]byte, ice.MOD_BUFS) for { - n, from, e := s.ReadFromUDP(buf[:]) + n, from, e := l.ReadFromUDP(buf[:]) if e != nil { break } @@ -51,12 +48,12 @@ func _broad_serve(m *ice.Message, port string) { if remote := _broad_addr(m, msg.Option(tcp.HOST), msg.Option(tcp.PORT)); remote != nil { m.Cmd(BROAD, func(value ice.Maps) { m.Logs(tcp.SEND, BROAD, kit.Format(value), nfs.TO, kit.Format(remote)) - s.WriteToUDP([]byte(m.Spawn(value, kit.Dict(mdb.ZONE, "echo")).FormatMeta()), remote) + l.WriteToUDP([]byte(m.Spawn(value, kit.Dict(mdb.ZONE, "echo")).FormatMeta()), remote) }) _broad_save(m, msg) } } - } + }) } func _broad_save(m, msg *ice.Message) { save := false @@ -101,6 +98,9 @@ func init() { tcp.SEND: {Hand: func(m *ice.Message, arg ...string) { _broad_send(m, "", "", "255.255.255.255", "9020", arg...) }}, + SERVE_START: {Hand: func(m *ice.Message, arg ...string) { + m.Go(func() { m.Cmd(BROAD, SERVE, m.OptionSimple(tcp.PORT)) }) + }}, }, mdb.HashAction(mdb.SHORT, "host,port", mdb.FIELD, "time,hash,type,name,host,port", mdb.ACTION, OPEN), mdb.ClearOnExitHashAction())}, }) } diff --git a/base/web/dream.go b/base/web/dream.go index 37d2033d..0064bd87 100644 --- a/base/web/dream.go +++ b/base/web/dream.go @@ -137,7 +137,7 @@ func init() { cli.STOP: {Hand: func(m *ice.Message, arg ...string) { m.Cmd(SPACE, mdb.MODIFY, m.OptionSimple(mdb.NAME), mdb.STATUS, cli.STOP) m.Go(func() { m.Cmd(SPACE, m.Option(mdb.NAME), ice.EXIT) }) - m.Sleep("1s") + m.Sleep300ms() }}, nfs.TRASH: {Hand: func(m *ice.Message, arg ...string) { nfs.Trash(m, path.Join(ice.USR_LOCAL_WORK, m.Option(mdb.NAME))) diff --git a/base/web/serve.go b/base/web/serve.go index 569da2ae..ebf3b4fa 100644 --- a/base/web/serve.go +++ b/base/web/serve.go @@ -17,7 +17,6 @@ import ( "shylinux.com/x/icebergs/base/gdb" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" - "shylinux.com/x/icebergs/base/ssh" "shylinux.com/x/icebergs/base/tcp" kit "shylinux.com/x/toolkits" ) @@ -26,13 +25,12 @@ func _serve_address(m *ice.Message) string { return kit.Format("http://localhost:%s", m.Option(tcp.PORT)) } func _serve_start(m *ice.Message) { - defer kit.For(kit.Split(m.Option(ice.DEV)), func(v string) { m.Cmd(SPACE, tcp.DIAL, ice.DEV, v, mdb.NAME, ice.Info.NodeName) }) + defer kit.For(kit.Split(m.Option(ice.DEV)), func(v string) { m.Sleep("10ms").Cmd(SPACE, tcp.DIAL, ice.DEV, v, mdb.NAME, ice.Info.NodeName) }) kit.If(m.Option(aaa.USERNAME), func() { aaa.UserRoot(m, m.Option(aaa.USERNICK), m.Option(aaa.USERNAME)) }) kit.If(m.Option(tcp.PORT) == tcp.RANDOM, func() { m.Option(tcp.PORT, m.Cmdx(tcp.PORT, aaa.RIGHT)) }) - kit.If(runtime.GOOS == cli.WINDOWS, func() { m.Cmd(SPIDE, ice.OPS, _serve_address(m)+"/exit").Sleep("300ms") }) + kit.If(runtime.GOOS == cli.WINDOWS, func() { m.Cmd(SPIDE, ice.OPS, _serve_address(m)+"/exit").Sleep300ms() }) cli.NodeInfo(m, kit.Select(ice.Info.Hostname, m.Option(tcp.NODENAME)), SERVER) m.Target().Start(m, m.OptionSimple(tcp.HOST, tcp.PORT)...) - m.Sleep("300ms") } func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool { const ( @@ -192,27 +190,21 @@ func init() { _serve_start(m) }}, SERVE_START: {Hand: func(m *ice.Message, arg ...string) { - if m.Go(func() { m.Cmd(BROAD, SERVE, m.OptionSimple(tcp.PORT)) }); m.Option(ice.DEV) == "" { - m.Cmd(ssh.PRINTF, kit.Dict(nfs.CONTENT, ice.NL+ice.Render(m, ice.RENDER_QRCODE, tcp.PublishLocalhost(m, _serve_address(m))))).Cmd(ssh.PROMPT, kit.Dict(ice.LOG_DISABLE, ice.TRUE)) - } - go func() { + m.Go(func() { opened := false for i := 0; i < 3 && !opened; i++ { m.Sleep("1s").Cmd(SPACE, kit.Dict(ice.LOG_DISABLE, ice.TRUE), func(values ice.Maps) { kit.If(values[mdb.TYPE] == CHROME, func() { opened = true }) }) } - if opened { - return - } - cli.Opens(m, _serve_address(m)) - }() + kit.If(!opened, func() { cli.Opens(m, _serve_address(m)) }) + }) }}, DOMAIN: {Hand: func(m *ice.Message, arg ...string) { kit.If(len(arg) > 0, func() { ice.Info.Domain, ice.Info.Localhost = arg[0], false }) m.Echo(ice.Info.Domain) }}, - }, mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,status,name,proto,host,port", tcp.LOCALHOST, ice.TRUE), mdb.ClearOnExitHashAction(), ServeAction())}, + }, mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,status,name,proto,host,port", tcp.LOCALHOST, ice.TRUE), mdb.ClearOnExitHashAction())}, PP(ice.INTSHELL): {Name: "/intshell/", Help: "命令行", Actions: aaa.WhiteAction(), Hand: func(m *ice.Message, arg ...string) { RenderIndex(m, arg...) }}, @@ -256,15 +248,6 @@ func init() { } m.RenderDownload(p) }}, - PP(ice.HELP): {Name: "/help/", Help: "帮助", Actions: ice.MergeActions(ctx.CmdAction(), aaa.WhiteAction()), Hand: func(m *ice.Message, arg ...string) { - if len(arg) == 0 { - arg = append(arg, "tutor.shy") - } - if len(arg) > 0 && arg[0] != ctx.ACTION { - arg[0] = path.Join(ice.SRC_HELP, arg[0]) - } - m.Cmdy("web.chat./cmd/", arg) - }}, }) ice.AddMerges(func(c *ice.Context, key string, cmd *ice.Command, sub string, action *ice.Action) (ice.Handler, ice.Handler) { if strings.HasPrefix(sub, ice.PS) { diff --git a/base/web/space.go b/base/web/space.go index e19b4b99..77a5976c 100644 --- a/base/web/space.go +++ b/base/web/space.go @@ -33,9 +33,9 @@ func _space_dial(m *ice.Message, dev, name string, arg ...string) { if conn, _, e := websocket.NewClient(c, uri, nil, kit.Int(redial["r"]), kit.Int(redial["w"])); !m.Warn(e, tcp.DIAL, dev, SPACE, uri.String()) { defer mdb.HashCreateDeferRemove(m, kit.SimpleKV("", MASTER, dev, msg.Append(tcp.HOSTNAME)), kit.Dict(mdb.TARGET, conn))() if !prints && ice.Info.Colors { - go func() { - m.Sleep("300ms").Cmd(ssh.PRINTF, kit.Dict(nfs.CONTENT, "\r"+ice.Render(m, ice.RENDER_QRCODE, m.CmdAppend(SPACE, dev, cli.PWD, mdb.LINK)))).Cmd(ssh.PROMPT, kit.Dict(ice.LOG_DISABLE, ice.TRUE)) - }() + m.Go(func() { + m.Sleep300ms().Cmd(ssh.PRINTF, kit.Dict(nfs.CONTENT, "\r"+ice.Render(m, ice.RENDER_QRCODE, m.CmdAppend(SPACE, dev, cli.PWD, mdb.LINK)))).Cmd(ssh.PROMPT, kit.Dict(ice.LOG_DISABLE, ice.TRUE)) + }) prints = true } _space_handle(m.Spawn(), true, dev, conn) @@ -57,8 +57,8 @@ func _space_fork(m *ice.Message) { case WORKER: defer gdb.EventDeferEvent(m, DREAM_OPEN, args)(DREAM_CLOSE, args) case CHROME: - m.Go(func() { m.Sleep30ms().Cmd(SPACE, name, cli.PWD, name) }) - case aaa.LOGIN: + m.Cmd(SPACE, name, cli.PWD, name) + case LOGIN: gdb.EventDeferEvent(m, SPACE_LOGIN, args) } _space_handle(m, false, name, conn) @@ -66,10 +66,10 @@ func _space_fork(m *ice.Message) { } } func _space_handle(m *ice.Message, safe bool, name string, conn *websocket.Conn) { + defer m.Cost(SPACE, name) for { _, b, e := conn.ReadMessage() if e != nil { - m.Cost(SPACE, name, e) break } msg := m.Spawn(b) @@ -89,7 +89,7 @@ func _space_handle(m *ice.Message, safe bool, name string, conn *websocket.Conn) }) { } else if res := getSend(m, next); !m.Warn(res == nil || len(target) != 1, ice.ErrNotFound, next) { res.Cost(kit.Format("[%v]->%v %v %v", next, res.Optionv(ice.MSG_TARGET), res.Detailv(), msg.FormatSize())) - back(res, msg.Sleep("10ms")) // 接收响应 + back(res, msg.Sleep30ms()) // 接收响应 } } } @@ -189,7 +189,6 @@ func init() { m.PushSearch(mdb.TEXT, m.Cmd(SPIDE, values[mdb.NAME], ice.Maps{ice.MSG_FIELDS: ""}).Append(CLIENT_ORIGIN), values) case SERVER: m.PushSearch(mdb.TEXT, kit.Format(tcp.PublishLocalhost(m, strings.Split(MergePod(m, values[mdb.NAME]), ice.QS)[0])), values) - case aaa.LOGIN: } }) } else if arg[0] == mdb.FOREACH && arg[1] == ssh.SHELL { @@ -208,7 +207,7 @@ func init() { } aaa.SessAuth(m, kit.Dict(aaa.USERNAME, m.Option(ice.MSG_USERNAME), aaa.USERNICK, m.Option(ice.MSG_USERNICK), aaa.USERROLE, m.Option(ice.MSG_USERROLE))) }}, - aaa.LOGIN: {Hand: func(m *ice.Message, arg ...string) { + LOGIN: {Hand: func(m *ice.Message, arg ...string) { m.Cmd(SPACE, kit.Select(m.Option(mdb.NAME), arg, 0), ice.MSG_SESSID, aaa.SessCreate(m, m.Option(ice.MSG_USERNAME))) }}, DOMAIN: {Hand: func(m *ice.Message, arg ...string) { m.Echo(_space_domain(m)) }}, @@ -228,8 +227,8 @@ func init() { mdb.HashSelect(m, arg...).Sort("type,name,text") m.Tables(func(values ice.Maps) { switch values[mdb.TYPE] { - case aaa.LOGIN: - m.PushButton(aaa.LOGIN, mdb.REMOVE) + case LOGIN: + m.PushButton(LOGIN, mdb.REMOVE) default: m.PushButton(cli.OPEN, mdb.REMOVE) } diff --git a/base/web/web.go b/base/web/web.go index 98491d49..4ba5571c 100644 --- a/base/web/web.go +++ b/base/web/web.go @@ -23,11 +23,10 @@ type Frame struct { send ice.Messages } -func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server { +func (f *Frame) Begin(m *ice.Message, arg ...string) { f.send = ice.Messages{} - return f } -func (f *Frame) Start(m *ice.Message, arg ...string) bool { +func (f *Frame) Start(m *ice.Message, arg ...string) { f.Message, f.Server = m, &http.Server{Handler: f} list := map[*ice.Context]string{} m.Travel(func(p *ice.Context, c *ice.Context) { @@ -56,24 +55,18 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool { }(key, cmd) } }) - gdb.EventDeferEvent(m, SERVE_START, arg) switch cb := m.OptionCB("").(type) { case func(http.Handler): cb(f) default: m.Cmd(tcp.SERVER, tcp.LISTEN, mdb.TYPE, WEB, m.OptionSimple(mdb.NAME, tcp.HOST, tcp.PORT), func(l net.Listener) { defer mdb.HashCreateDeferRemove(m, m.OptionSimple(mdb.NAME, tcp.PROTO), arg, cli.STATUS, tcp.START)() + gdb.EventDeferEvent(m, SERVE_START, arg) m.Warn(f.Server.Serve(l)) }) } - return true -} -func (f *Frame) Close(m *ice.Message, arg ...string) bool { - return true -} -func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server { - return &Frame{} } +func (f *Frame) Close(m *ice.Message, arg ...string) {} func (f *Frame) ServeHTTP(w http.ResponseWriter, r *http.Request) { if _serve_main(f.Message, w, r) { f.ServeMux.ServeHTTP(w, r) diff --git a/core/chat/footer.go b/core/chat/footer.go index 55272365..f13c282b 100644 --- a/core/chat/footer.go +++ b/core/chat/footer.go @@ -23,9 +23,6 @@ func init() { } } }}, - ice.HELP: {Hand: func(m *ice.Message, arg ...string) { - ctx.ProcessField(m, web.WIKI_WORD, func() string { return kit.ExtChange(ctx.GetCmdFile(m, arg[0]), nfs.SHY) }, arg...) - }}, nfs.SCRIPT: {Hand: func(m *ice.Message, arg ...string) { ctx.ProcessField(m, web.CODE_VIMER, func() []string { return nfs.SplitPath(m, kit.ExtChange(nfs.Relative(m, ctx.GetCmdFile(m, arg[0])), nfs.JS)) diff --git a/core/chat/header.go b/core/chat/header.go index b4ecec71..9bea8a37 100644 --- a/core/chat/header.go +++ b/core/chat/header.go @@ -34,7 +34,11 @@ func _header_share(m *ice.Message, arg ...string) { m.Push(mdb.NAME, m.Option(mdb.LINK)).PushQRCode(mdb.TEXT, m.Option(mdb.LINK)) } func _header_check(m *ice.Message, arg ...string) bool { - if m.Option(web.SHARE) != "" { + if m.Option(ice.CMD) == aaa.OFFER && m.Option(mdb.HASH) != "" { + m.Cmd(aaa.OFFER, m.Option(mdb.HASH), func(value ice.Maps) { + aaa.SessAuth(m, kit.Dict(aaa.USERNAME, value[aaa.EMAIL], aaa.USERROLE, aaa.VOID)) + }) + } else if m.Option(web.SHARE) != "" { m.Cmd(web.SHARE, m.Option(web.SHARE), ice.OptionFields(""), func(value ice.Maps) { if web.IsNotValidShare(m, value[mdb.TIME]) { return @@ -65,6 +69,7 @@ const HEADER = "header" func init() { Index.MergeCommands(ice.Commands{ web.P(HEADER): {Name: "/header", Help: "标题栏", Actions: ice.MergeActions(ice.Actions{ + ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { aaa.White(m, HEADER) }}, mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {}}, aaa.LOGOUT: {Hand: aaa.SessLogout}, aaa.PASSWORD: {Hand: _header_users}, @@ -74,14 +79,12 @@ func init() { aaa.AVATAR: {Hand: _header_users}, web.SHARE: {Hand: _header_share}, "webpack": {Hand: ctx.CmdHandler("webpack", "build")}, - }, ctx.ConfAction(SSO, ""), aaa.BlackAction("webpack")), Hand: func(m *ice.Message, arg ...string) { + }, ctx.ConfAction(SSO, "")), Hand: func(m *ice.Message, arg ...string) { if gdb.Event(m, HEADER_AGENT); !_header_check(m, arg...) { return } msg := m.Cmd(aaa.USER, m.Option(ice.MSG_USERNAME)) - for _, k := range []string{aaa.USERNICK, aaa.LANGUAGE} { - m.Option(k, msg.Append(k)) - } + kit.For([]string{aaa.USERNICK, aaa.LANGUAGE}, func(k string) { m.Option(k, msg.Append(k)) }) for _, k := range []string{aaa.BACKGROUND, aaa.AVATAR} { if strings.HasPrefix(msg.Append(k), ice.PS) || strings.HasPrefix(msg.Append(k), ice.HTTP) { m.Option(k, msg.Append(k)) diff --git a/core/chat/template.go b/core/chat/template.go index 65b4b949..c83e402b 100644 --- a/core/chat/template.go +++ b/core/chat/template.go @@ -14,6 +14,7 @@ func init() { Index.MergeCommands(ice.Commands{ TEMPLATE: {Name: "template river storm index auto 删除配置 查看配置", Help: "模板", Actions: ice.MergeActions(ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { + return if gdb.Watch(m, RIVER_CREATE); m.Cmd("").Length() == 0 { kit.For(_river_template, func(river string, value ice.Any) { m.Cmd("", mdb.CREATE, RIVER, river) diff --git a/core/code/pprof.go b/core/code/pprof.go index 8584633b..94ae3e17 100644 --- a/core/code/pprof.go +++ b/core/code/pprof.go @@ -52,7 +52,7 @@ func init() { u := web.OptionUserWeb(m) p := u.Hostname() + ice.DF + m.Cmdx(tcp.PORT, aaa.RIGHT) m.Cmd(cli.DAEMON, mdb.Configv(m, PPROF), "-http="+p, m.Option(BINNARY), m.Option(nfs.FILE)) - m.Sleep("3s").ProcessOpen(kit.Format("http://%s/ui/top", p)) + m.Sleep3s().ProcessOpen(kit.Format("http://%s/ui/top", p)) }}, }, mdb.ZoneAction(mdb.FIELDS, "time,zone,count,binnary,service,seconds", mdb.FIELD, "time,id,text,file", PPROF, kit.List(GO, "tool", PPROF))), Hand: func(m *ice.Message, arg ...string) { if mdb.ZoneSelect(m, arg...); len(arg) == 0 { diff --git a/core/code/vimer.go b/core/code/vimer.go index 6ee03cc6..9260068f 100644 --- a/core/code/vimer.go +++ b/core/code/vimer.go @@ -154,7 +154,7 @@ func init() { if isWebview() { m.Go(func() { m.Cmd(cli.SYSTEM, "./bin/ice.bin", cli.FOREVER, cli.DELAY, "300ms", cli.SYSTEM, cli.OPEN, app) }) } - m.Go(func() { m.Sleep("10ms").Cmd(UPGRADE, cli.RESTART) }) + m.Go(func() { m.Sleep30ms().Cmd(UPGRADE, cli.RESTART) }) } else { _vimer_make(m, nfs.PWD, msg) } diff --git a/core/code/xterm.go b/core/code/xterm.go index baa4e8e5..4a27d1f8 100644 --- a/core/code/xterm.go +++ b/core/code/xterm.go @@ -59,7 +59,7 @@ func _xterm_get(m *ice.Message, h string) _xterm { if _xterm_echo(m, h, string(buf[:n])); len(text) > 0 { if cmd := text[0]; text[0] != "" { m.Go(func() { - m.Sleep("10ms") + m.Sleep30ms() tty.Write([]byte(cmd + ice.NL)) }) } diff --git a/exec.go b/exec.go index 8f7b4457..2025e6d4 100644 --- a/exec.go +++ b/exec.go @@ -76,8 +76,9 @@ func (m *Message) TableGo(cb Any) *Message { }) return m } -func (m *Message) Go(cb Any) *Message { - task.Put(logs.FileLine(cb), func(task *task.Task) error { +func (m *Message) Go(cb Any, arg ...Any) *Message { + kit.If(len(arg) == 0, func() { arg = append(arg, logs.FileLine(cb)) }) + task.Put(arg[0], func(task *task.Task) error { m.TryCatch(m, true, func(m *Message) { switch cb := cb.(type) { case func(*Message): diff --git a/init.go b/init.go index 28d99b56..2156611e 100644 --- a/init.go +++ b/init.go @@ -13,7 +13,7 @@ import ( type Frame struct{} -func (s *Frame) Begin(m *Message, arg ...string) Server { +func (s *Frame) Begin(m *Message, arg ...string) { list := map[*Context]*Message{m.target: m} m.Travel(func(p *Context, s *Context) { s.root = m.target @@ -22,19 +22,14 @@ func (s *Frame) Begin(m *Message, arg ...string) Server { s.Begin(list[s], arg...) } }) - return s } -func (s *Frame) Start(m *Message, arg ...string) bool { - m.Cap(CTX_STREAM, strings.Split(m.Time(), SP)[1]) +func (s *Frame) Start(m *Message, arg ...string) { m.Cmd(kit.Keys(MDB, CTX_INIT)) m.Cmd(INIT, arg) - for _, k := range kit.Split(kit.Select("ctx,log,gdb,ssh", os.Getenv(CTX_DAEMON))) { - m.Start(k) - } m.Cmd(arg) - return true + kit.For(kit.Split(kit.Select("log,gdb,ssh", os.Getenv(CTX_DAEMON))), func(k string) { m.Sleep("10ms").Start(k) }) } -func (s *Frame) Close(m *Message, arg ...string) bool { +func (s *Frame) Close(m *Message, arg ...string) { list := map[*Context]*Message{m.target: m} m.Travel(func(p *Context, s *Context) { if msg, ok := list[p]; ok && msg != nil { @@ -43,26 +38,25 @@ func (s *Frame) Close(m *Message, arg ...string) bool { } }) conf.Close() - go func() { os.Exit(kit.Int(Pulse.Sleep("30ms").Option(EXIT))) }() - return true + go func() { os.Exit(kit.Int(Pulse.Sleep30ms().Option(EXIT))) }() } -func (s *Frame) Spawn(m *Message, c *Context, arg ...string) Server { return &Frame{} } const ( INIT = "init" - HELP = "help" - EXIT = "exit" QUIT = "quit" + EXIT = "exit" ) -var Index = &Context{Name: ICE, Help: "冰山模块", Configs: Configs{HELP: {Value: kit.Data(INDEX, Info.Help)}}, Commands: Commands{ +var Index = &Context{Name: ICE, Help: "冰山模块", Commands: Commands{ CTX_INIT: {Hand: func(m *Message, arg ...string) { m.Travel(func(p *Context, c *Context) { - if p != nil { - c._command(m.Spawn(c), c.Commands[CTX_INIT], CTX_INIT, arg...) - } + kit.If(p != nil, func() { m.Go(func() { c._command(m.Spawn(c), c.Commands[CTX_INIT], CTX_INIT, arg...) }) }) }) loadImportant(m) + loadImportant(m) + loadImportant(m) + loadImportant(m) + loadImportant(m) }}, INIT: {Hand: func(m *Message, arg ...string) { m.Cmd(CTX_INIT) @@ -77,26 +71,23 @@ var Index = &Context{Name: ICE, Help: "冰山模块", Configs: Configs{HELP: {Va CTX_EXIT: {Hand: func(m *Message, arg ...string) { defer m.Target().Close(m.Spawn(), arg...) m.Travel(func(p *Context, c *Context) { - if p != nil { - c._command(m.Spawn(c), c.Commands[CTX_EXIT], CTX_EXIT, arg...) - } + kit.If(p != nil, func() { c._command(m.Spawn(c), c.Commands[CTX_EXIT], CTX_EXIT, arg...) }) }) removeImportant(m) }}, }, server: &Frame{}} -var Pulse = &Message{time: time.Now(), code: 0, meta: map[string][]string{}, data: Map{}, source: Index, target: Index, Hand: true} +var Pulse = &Message{time: time.Now(), code: 0, Hand: true, meta: map[string][]string{}, data: Map{}, source: Index, target: Index} func init() { Index.root, Pulse.root = Index, Pulse } func Run(arg ...string) string { - if len(arg) == 0 && len(os.Args) > 1 { - arg = kit.Simple(os.Args[1:], kit.Split(kit.Env(CTX_ARG))) - } + kit.If(len(arg) == 0 && len(os.Args) > 1, func() { arg = kit.Simple(os.Args[1:], kit.Split(kit.Env(CTX_ARG))) }) if len(arg) == 0 { if runtime.GOOS == "windows" { arg = append(arg, SERVE, START, DEV, DEV) } else { - // arg = append(arg, "forever", START, DEV, DEV) + arg = append(arg, "pwd") + // arg = append(arg, "forever", START, DEV, DEV) } } Pulse.meta[MSG_DETAIL] = arg @@ -105,32 +96,20 @@ func Run(arg ...string) string { Pulse.Option(ls[0], ls[1]) } }) + kit.If(Pulse._cmd == nil, func() { Pulse._cmd = &Command{RawHand: logs.FileLines(3)} }) time.Local = time.FixedZone("Beijing", 28800) - if Pulse.time = time.Now(); Pulse._cmd == nil { - Pulse._cmd = &Command{RawHand: logs.FileLines(3)} - } + Pulse.time = time.Now() switch Index.Merge(Index).Begin(Pulse, arg...); kit.Select("", arg, 0) { case SERVE, SPACE: - if os.Getenv("ctx_log") == "" { - // os.Stderr.Close() - } - if Index.Start(Pulse, arg...) { - conf.Wait() - os.Exit(kit.Int(Pulse.Option(EXIT))) - } + Index.Start(Pulse, arg...) + conf.Wait() + os.Exit(kit.Int(Pulse.Option(EXIT))) default: - if logs.Disable(true); len(arg) == 0 { - arg = append(arg, HELP) - } - if Pulse.Cmdy(INIT).Cmdy(arg); Pulse.IsErrNotFound() { - Pulse.SetAppend().SetResult().Cmdy(SYSTEM, arg) - } - if strings.TrimSpace(Pulse.Result()) == "" && Pulse.Length() > 0 { - Pulse.Table() - } - if Pulse.Result() != "" && !strings.HasSuffix(Pulse.Result(), NL) { - Pulse.Echo(NL) - } + logs.Disable(true) + Pulse.Cmdy(INIT).Cmdy(arg) + kit.If(Pulse.IsErrNotFound(), func() { Pulse.SetAppend().SetResult().Cmdy(SYSTEM, arg) }) + kit.If(strings.TrimSpace(Pulse.Result()) == "" && Pulse.Length() > 0, func() { Pulse.Table() }) + kit.If(Pulse.Result() != "" && !strings.HasSuffix(Pulse.Result(), NL), func() { Pulse.Echo(NL) }) } return Pulse.Result() } diff --git a/logs.go b/logs.go index 52a93c88..34a9cab9 100644 --- a/logs.go +++ b/logs.go @@ -272,3 +272,22 @@ func (m *Message) FormatStack(s, n int) string { } return kit.Join(list, NL) } +func (c *Command) GetFileLine() string { + return kit.Join(kit.Slice(kit.Split(c.GetFileLines(), PS), -3), PS) +} +func (c *Command) GetFileLines() string { + if c == nil { + return "" + } else if c.RawHand != nil { + switch h := c.RawHand.(type) { + case string: + return h + default: + return logs.FileLines(c.RawHand) + } + } else if c.Hand != nil { + return logs.FileLines(c.Hand) + } else { + return "" + } +} diff --git a/misc.go b/misc.go index 0f231d07..9d44468d 100644 --- a/misc.go +++ b/misc.go @@ -351,8 +351,8 @@ func MergeActions(arg ...Any) Actions { last := h.Hand hand := v.Hand h.Hand = func(m *Message, arg ...string) { - hand(m, arg...) last(m, arg...) + hand(m, arg...) } } else if h.Name = kit.Select(v.Name, h.Name); h.Hand == nil { h.Hand = v.Hand @@ -474,3 +474,13 @@ func MergeHand(hand ...Handler) Handler { } } } +func (m *Message) CmdMap(arg ...string) map[string]map[string]string { + field, list := kit.Slice(arg, -1)[0], map[string]map[string]string{} + m._command(kit.Slice(arg, 0, -1)).Tables(func(value Maps) { list[value[field]] = value }) + return list +} +func (m *Message) CmdAppend(arg ...Any) string { + args := kit.Simple(arg...) + field := kit.Slice(args, -1)[0] + return m._command(kit.Slice(args, 0, -1), OptionFields(field)).Append(field) +} diff --git a/misc/git/status.go b/misc/git/status.go index 84409bbe..49853777 100644 --- a/misc/git/status.go +++ b/misc/git/status.go @@ -216,13 +216,13 @@ func init() { PULL: {Help: "下载", Hand: func(m *ice.Message, arg ...string) { _status_each(m, "", cli.SYSTEM, GIT, PULL) _status_each(m, "", cli.SYSTEM, GIT, PULL, "--tags") - m.Sleep("3s") + m.Sleep3s() }}, PUSH: {Help: "上传", Hand: func(m *ice.Message, arg ...string) { if m.Option(REPOS) == "" { _status_each(m, "", cli.SYSTEM, GIT, PUSH) _status_each(m, "", cli.SYSTEM, GIT, PUSH, "--tags") - m.Sleep("3s") + m.Sleep3s() return } m.Option(cli.CMD_DIR, _repos_path(m.Option(REPOS))) diff --git a/misc/tmux/session.go b/misc/tmux/session.go index c9a2a92b..714df7d4 100644 --- a/misc/tmux/session.go +++ b/misc/tmux/session.go @@ -117,7 +117,7 @@ func init() { return } m.Go(func() { - m.Sleep("1s") + m.Sleep300ms() _tmux_cmd(m, SEND_KEYS, "-t", kit.Keys(name, "2"), "ish_miss_log", ENTER) _tmux_cmd(m, SEND_KEYS, "-t", kit.Keys(name, "1"), "vi etc/miss.sh", ENTER) }) diff --git a/render.go b/render.go index 1a1cb9d4..7454e242 100644 --- a/render.go +++ b/render.go @@ -126,6 +126,19 @@ func (m *Message) IsCliUA() bool { func (m *Message) IsMobileUA() bool { return strings.Contains(m.Option(MSG_USERUA), "Mobile") } +func (m *Message) MergePodCmd(pod, cmd string, arg ...Any) string { + ls := []string{"chat"} + kit.If(kit.Keys(m.Option(MSG_USERPOD), pod), func(p string) { ls = append(ls, POD, p) }) + if cmd == "" { + if _, ok := Info.Index[m.CommandKey()]; ok { + cmd = m.CommandKey() + } else { + cmd = m.PrefixKey() + } + } + ls = append(ls, CMD, cmd) + return kit.MergeURL2(strings.Split(kit.Select(Info.Domain, m.Option(MSG_USERWEB)), QS)[0], PS+kit.Join(ls, PS), arg...) +} func (m *Message) PushSearch(arg ...Any) { data := kit.Dict(arg...) for i := 0; i < len(arg); i += 2 { diff --git a/type.go b/type.go index 7b8d6da2..9d3a2267 100644 --- a/type.go +++ b/type.go @@ -66,65 +66,31 @@ type Context struct { id int32 } type Server interface { - Begin(m *Message, arg ...string) Server - Start(m *Message, arg ...string) bool - Close(m *Message, arg ...string) bool - Spawn(m *Message, c *Context, arg ...string) Server + Begin(m *Message, arg ...string) + Start(m *Message, arg ...string) + Close(m *Message, arg ...string) } -func (c *Context) ID() int32 { - return atomic.AddInt32(&c.id, 1) -} func (c *Context) Cap(key string, arg ...Any) string { - if len(arg) > 0 { - c.Caches[key].Value = kit.Format(arg[0]) - } + kit.If(len(arg) > 0, func() { c.Caches[key].Value = kit.Format(arg[0]) }) return c.Caches[key].Value } func (c *Context) Cmd(m *Message, key string, arg ...string) *Message { return c._command(m, c.Commands[key], key, arg...) } -func (c *Context) Server() Server { - return c.server -} func (c *Context) Prefix(arg ...string) string { return kit.Keys(c.Cap(CTX_FOLLOW), arg) } -func (c *Command) GetFileLine() string { - return kit.Join(kit.Slice(kit.Split(c.GetFileLines(), PS), -3), PS) -} -func (c *Command) GetFileLines() string { - if c == nil { - return "" - } else if c.RawHand != nil { - switch h := c.RawHand.(type) { - case string: - return h - default: - return logs.FileLines(c.RawHand) +func (c *Context) Server() Server { return c.server } +func (c *Context) ID() int32 { return atomic.AddInt32(&c.id, 1) } +func (c *Context) Register(s *Context, x Server, cmd ...string) *Context { + kit.For(cmd, func(cmd string) { + if s, ok := Info.Index[cmd].(*Context); ok { + panic(kit.Format("%s %s registed by %v", ErrWarn, cmd, s.Name)) } - } else if c.Hand != nil { - return logs.FileLines(c.Hand) - } else { - return "" - } -} - -func (c *Context) Register(s *Context, x Server, n ...string) *Context { - for _, n := range n { - if s, ok := Info.Index[n]; ok { - last := "" - switch s := s.(type) { - case *Context: - last = s.Name - } - panic(kit.Format("%s %s %v", ErrWarn, n, last)) - } - Info.Index[n] = s - } - if c.Contexts == nil { - c.Contexts = Contexts{} - } + Info.Index[cmd] = s + }) + kit.If(c.Contexts == nil, func() { c.Contexts = Contexts{} }) c.Contexts[s.Name] = s s.root = c.root s.context = c @@ -134,8 +100,7 @@ func (c *Context) Register(s *Context, x Server, n ...string) *Context { func (c *Context) MergeCommands(Commands Commands) *Context { for key, cmd := range Commands { if cmd.Hand == nil && cmd.RawHand == nil { - cmd.RawHand = logs.FileLines(2) - if cmd.Actions != nil { + if cmd.RawHand = logs.FileLines(2); cmd.Actions != nil { if action, ok := cmd.Actions[SELECT]; ok { cmd.Name = kit.Select(strings.Replace(action.Name, SELECT, key, 1), cmd.Name) cmd.Help = kit.Select(action.Help, cmd.Help) @@ -144,65 +109,49 @@ func (c *Context) MergeCommands(Commands Commands) *Context { } } configs := Configs{} - for k, _ := range Commands { + for k := range Commands { configs[k] = &Config{Value: kit.Data()} } return c.Merge(&Context{Commands: Commands, Configs: configs}) } func (c *Context) Merge(s *Context) *Context { - if c.Commands == nil { - c.Commands = Commands{} - } - if c.Commands[CTX_INIT] == nil { - c.Commands[CTX_INIT] = &Command{Hand: func(m *Message, arg ...string) { Info.Load(m) }} - } - if c.Commands[CTX_EXIT] == nil { - c.Commands[CTX_EXIT] = &Command{Hand: func(m *Message, arg ...string) { Info.Save(m) }} - } - merge := func(pre *Command, init bool, key string, cmd *Command, cb ...Handler) { + kit.If(c.Commands == nil, func() { c.Commands = Commands{} }) + kit.If(c.Commands[CTX_INIT] == nil, func() { c.Commands[CTX_INIT] = &Command{Hand: func(m *Message, arg ...string) { Info.Load(m) }} }) + kit.If(c.Commands[CTX_EXIT] == nil, func() { c.Commands[CTX_EXIT] = &Command{Hand: func(m *Message, arg ...string) { Info.Save(m) }} }) + merge := func(pre *Command, init bool, key string, cmd *Command, cb Handler) { + if cb == nil { + return + } last := pre.Hand pre.Hand = func(m *Message, arg ...string) { - if init { - last(m, arg...) - } + kit.If(init, func() { last(m, arg...) }) + defer kit.If(!init, func() { last(m, arg...) }) _key, _cmd := m._key, m._cmd + defer func() { m._key, m._cmd = _key, _cmd }() m._key, m._cmd = key, cmd - for _, cb := range cb { - if cb != nil { - cb(m, arg...) - } - } - m._key, m._cmd = _key, _cmd - if !init { - last(m, arg...) - } + cb(m, arg...) } } for key, cmd := range s.Commands { if pre, ok := c.Commands[key]; ok && s != c { - switch hand := cmd.Hand; key { + switch key { case CTX_INIT: - merge(pre, true, key, cmd, hand) + merge(pre, true, key, cmd, cmd.Hand) continue case CTX_EXIT: - merge(pre, false, key, cmd, hand) + merge(pre, false, key, cmd, cmd.Hand) continue } } - if c.Commands[key] = cmd; cmd.List == nil { - cmd.List = SplitCmd(cmd.Name, cmd.Actions) - } - if cmd.Meta == nil { - cmd.Meta = kit.Dict() - } + c.Commands[key] = cmd + kit.If(cmd.Meta == nil, func() { cmd.Meta = kit.Dict() }) + kit.If(cmd.List == nil, func() { cmd.List = SplitCmd(cmd.Name, cmd.Actions) }) for sub, action := range cmd.Actions { if pre, ok := c.Commands[sub]; ok && s == c { - switch h := action.Hand; sub { - case CTX_INIT: - merge(pre, true, key, cmd, h) - case CTX_EXIT: - merge(pre, false, key, cmd, h) - } + kit.Switch(sub, + CTX_INIT, func() { merge(pre, true, key, cmd, action.Hand) }, + CTX_EXIT, func() { merge(pre, false, key, cmd, action.Hand) }, + ) } if s == c { for _, h := range Info.merges { @@ -219,70 +168,37 @@ func (c *Context) Merge(s *Context) *Context { if action.Hand == nil { continue } - if action.List == nil { - action.List = SplitCmd(action.Name, nil) - } - if len(action.List) > 0 { - cmd.Meta[sub] = action.List - } + kit.If(action.List == nil, func() { action.List = SplitCmd(action.Name, nil) }) + kit.If(len(action.List) > 0, func() { cmd.Meta[sub] = action.List }) } } - if c.Configs == nil { - c.Configs = Configs{} - } + kit.If(c.Configs == nil, func() { c.Configs = Configs{} }) for k, v := range s.Configs { c.Configs[k] = v } return c } func (c *Context) Begin(m *Message, arg ...string) *Context { - follow := c.Name - if c.context != nil && c.context != Index { - follow = kit.Keys(c.context.Cap(CTX_FOLLOW), c.Name) - } - if c.Caches == nil { - c.Caches = Caches{} - } - c.Caches[CTX_FOLLOW] = &Cache{Name: CTX_FOLLOW, Value: follow} - c.Caches[CTX_STATUS] = &Cache{Name: CTX_STATUS, Value: CTX_BEGIN} + kit.If(c.Caches == nil, func() { c.Caches = Caches{} }) c.Caches[CTX_STREAM] = &Cache{Name: CTX_STREAM, Value: ""} - if c.Merge(c); c.server != nil { - c.server.Begin(m, arg...) - } - return c + c.Caches[CTX_STATUS] = &Cache{Name: CTX_STATUS, Value: CTX_BEGIN} + c.Caches[CTX_FOLLOW] = &Cache{Name: CTX_FOLLOW, Value: c.Name} + kit.If(c.context != nil && c.context != Index, func() { c.Cap(CTX_FOLLOW, kit.Keys(c.context.Cap(CTX_FOLLOW), c.Name)) }) + kit.If(c.server != nil, func() { c.server.Begin(m, arg...) }) + return c.Merge(c) } func (c *Context) Start(m *Message, arg ...string) bool { - wait := make(chan bool, 1) - defer func() { <-wait }() - m.Go(func() { - wait <- true - - m.Log(CTX_START, c.Cap(CTX_FOLLOW)) - c.Cap(CTX_STATUS, CTX_START) - if c.server != nil { - c.server.Start(m, arg...) - } + m.Log(c.Cap(CTX_STATUS, CTX_START), c.Cap(CTX_FOLLOW)) + kit.If(c.server != nil, func() { + m.Go(func() { c.server.Start(m, arg...) }, m.Prefix()) }) return true } func (c *Context) Close(m *Message, arg ...string) bool { - m.Log(CTX_CLOSE, c.Cap(CTX_FOLLOW)) - c.Cap(CTX_STATUS, CTX_CLOSE) - if c.server != nil { - return c.server.Close(m, arg...) - } + m.Log(c.Cap(CTX_STATUS, CTX_CLOSE), c.Cap(CTX_FOLLOW)) + kit.If(c.server != nil, func() { c.server.Close(m, arg...) }) return true } -func (c *Context) Spawn(m *Message, name string, help string, arg ...string) *Context { - s := &Context{Name: name, Help: help} - if c.server != nil { - c.Register(s, c.server.Spawn(m, s, arg...)) - } else { - c.Register(s, nil) - } - m.target = s - return s -} type Message struct { time time.Time @@ -309,42 +225,42 @@ type Message struct { I io.Reader } -func (m *Message) Time(args ...Any) string { +func (m *Message) Time(arg ...Any) string { t := m.time - if len(args) > 0 { - switch arg := args[0].(type) { + if len(arg) > 0 { + switch arg := arg[0].(type) { case string: if d, e := time.ParseDuration(arg); e == nil { - t, args = t.Add(d), args[1:] + t, arg = t.Add(d), arg[1:] } } } f := MOD_TIME - if len(args) > 0 { - switch arg := args[0].(type) { + if len(arg) > 0 { + switch p := arg[0].(type) { case string: - if f = arg; len(args) > 1 { - f = fmt.Sprintf(f, args[1:]...) + if f = p; len(arg) > 1 { + f = fmt.Sprintf(f, arg[1:]...) } } } return t.Format(f) } -func (m *Message) Target() *Context { - return m.target +func (m *Message) Target() *Context { return m.target } +func (m *Message) Source() *Context { return m.source } +func (m *Message) Message() *Message { return m.message } +func (m *Message) Commands(key string) *Command { + return m.Target().Commands[key] } -func (m *Message) Source() *Context { - return m.source -} -func (m *Message) Message() *Message { - return m.message +func (m *Message) Actions(key string) *Action { + return m._cmd.Actions[key] } func (m *Message) Spawn(arg ...Any) *Message { msg := &Message{ time: time.Now(), code: int(m.target.root.ID()), meta: map[string][]string{}, data: Map{}, - message: m, root: m.root, - source: m.target, target: m.target, _cmd: m._cmd, _key: m._key, _sub: m._sub, _target: logs.FileLine(2), + message: m, root: m.root, _target: logs.FileLine(2), + source: m.target, target: m.target, _cmd: m._cmd, _key: m._key, _sub: m._sub, W: m.W, R: m.R, O: m.O, I: m.I, } for _, val := range arg { @@ -354,23 +270,19 @@ func (m *Message) Spawn(arg ...Any) *Message { case Option: msg.Option(val.Name, val.Value) case Maps: - for k, v := range val { - msg.Option(k, v) - } + kit.For(val, func(k, v string) { msg.Option(k, v) }) case Map: - for k, v := range val { - msg.Option(k, v) - } - case http.ResponseWriter: - msg.W = val - case *http.Request: - msg.R = val + kit.For(val, func(k string, v Any) { msg.Option(k, v) }) case *Context: msg.target = val case *Command: msg._cmd = val case string: msg._key = val + case http.ResponseWriter: + msg.W = val + case *http.Request: + msg.R = val } } return msg @@ -379,31 +291,23 @@ func (m *Message) Start(key string, arg ...string) *Message { return m.Search(key+PT, func(p *Context, s *Context) { s.Start(m.Spawn(s), arg...) }) } func (m *Message) Travel(cb Any) *Message { + target := m.target + defer func() { m.target = target }() list := []*Context{m.root.target} for i := 0; i < len(list); i++ { switch cb := cb.(type) { case func(*Context, *Context): cb(list[i].context, list[i]) case func(*Context, *Context, string, *Command): - target := m.target - for _, k := range kit.SortedKey(list[i].Commands) { - m.target = list[i] - cb(list[i].context, list[i], k, list[i].Commands[k]) - } - m.target = target + m.target = list[i] + kit.For(kit.SortedKey(list[i].Commands), func(k string) { cb(list[i].context, list[i], k, list[i].Commands[k]) }) case func(*Context, *Context, string, *Config): - target := m.target - for _, k := range kit.SortedKey(list[i].Configs) { - m.target = list[i] - cb(list[i].context, list[i], k, list[i].Configs[k]) - } - m.target = target + m.target = list[i] + kit.For(kit.SortedKey(list[i].Configs), func(k string) { cb(list[i].context, list[i], k, list[i].Configs[k]) }) default: m.ErrorNotImplement(cb) } - for _, k := range kit.SortedKey(list[i].Contexts) { - list = append(list, list[i].Contexts[k]) - } + kit.For(kit.SortedKey(list[i].Contexts), func(k string) { list = append(list, list[i].Contexts[k]) }) } return m } @@ -493,35 +397,13 @@ func (m *Message) Search(key string, cb Any) *Message { return m } -func (m *Message) Commands(key string) *Command { - return m.Target().Commands[key] -} -func (m *Message) Actions(key string) *Action { - return m._cmd.Actions[key] -} -func (m *Message) CmdAppend(arg ...Any) string { - args := kit.Simple(arg...) - field := kit.Slice(args, -1)[0] - return m._command(kit.Slice(args, 0, -1), OptionFields(field)).Append(field) -} -func (m *Message) CmdMap(arg ...string) map[string]map[string]string { - field, list := kit.Slice(arg, -1)[0], map[string]map[string]string{} - m._command(kit.Slice(arg, 0, -1)).Tables(func(value Maps) { list[value[field]] = value }) - return list -} -func (m *Message) Cmd(arg ...Any) *Message { - return m._command(arg...) -} -func (m *Message) Cmds(arg ...Any) *Message { - return m.Go(func() { m._command(arg...) }) -} +func (m *Message) Cmd(arg ...Any) *Message { return m._command(arg...) } +func (m *Message) Cmds(arg ...Any) *Message { return m.Go(func() { m._command(arg...) }) } func (m *Message) Cmdx(arg ...Any) string { res := kit.Select("", m._command(arg...).meta[MSG_RESULT], 0) return kit.Select("", res, res != ErrWarn) } -func (m *Message) Cmdy(arg ...Any) *Message { - return m.Copy(m._command(arg...)) -} +func (m *Message) Cmdy(arg ...Any) *Message { return m.Copy(m._command(arg...)) } func (m *Message) Confv(arg ...Any) (val Any) { if m.Spawn().Warn(Info.Important && m.Option("_lock") == "") { m.Warn(true, "what unsafe lock", m.PrefixKey(), m.FormatStack(1, 100)) @@ -530,8 +412,7 @@ func (m *Message) Confv(arg ...Any) (val Any) { if len(arg) == 1 { val = conf.Value return - } - if len(arg) > 2 { + } else if len(arg) > 2 { if arg[1] == nil || arg[1] == "" { conf.Value = arg[2] } else { @@ -541,9 +422,7 @@ func (m *Message) Confv(arg ...Any) (val Any) { val = kit.Value(conf.Value, arg[1]) } key := kit.Format(arg[0]) - if key == "" { - key = m._key - } + kit.If(key == "", func() { key = m._key }) if conf, ok := m.target.Configs[key]; ok { run(conf) } else if conf, ok := m.source.Configs[key]; ok { @@ -553,13 +432,9 @@ func (m *Message) Confv(arg ...Any) (val Any) { } return } -func (m *Message) Conf(arg ...Any) string { - return kit.Format(m.Confv(arg...)) -} +func (m *Message) Conf(arg ...Any) string { return kit.Format(m.Confv(arg...)) } func (m *Message) Capi(key string, val ...Any) int { - if len(val) > 0 { - m.Cap(key, kit.Int(m.Cap(key))+kit.Int(val[0])) - } + kit.If(len(val) > 0, func() { m.Cap(key, kit.Int(m.Cap(key))+kit.Int(val[0])) }) return kit.Int(m.Cap(key)) } func (m *Message) Capv(arg ...Any) Any { @@ -571,15 +446,11 @@ func (m *Message) Capv(arg ...Any) Any { for _, s := range []*Context{m.target} { for c := s; c != nil; c = c.context { if caps, ok := c.Caches[key]; ok { - if len(arg) > 0 { - caps.Value = kit.Format(arg[0]) - } + kit.If(len(arg) > 0, func() { caps.Value = kit.Format(arg[0]) }) return caps.Value } } } return nil } -func (m *Message) Cap(arg ...Any) string { - return kit.Format(m.Capv(arg...)) -} +func (m *Message) Cap(arg ...Any) string { return kit.Format(m.Capv(arg...)) }