diff --git a/base/aaa/role.go b/base/aaa/role.go
index 7f2ee93c..96a5d425 100644
--- a/base/aaa/role.go
+++ b/base/aaa/role.go
@@ -29,6 +29,9 @@ func _role_list(m *ice.Message, userrole string) {
}
})
}
+func _role_chain(arg ...string) string {
+ return strings.ReplaceAll(kit.Keys(arg), "/", ice.PT)
+}
func _role_black(m *ice.Message, userrole, chain string, status bool) {
m.Richs(ROLE, nil, userrole, func(key string, value map[string]interface{}) {
m.Log_MODIFY(ROLE, userrole, BLACK, chain)
@@ -57,7 +60,7 @@ func _role_right(m *ice.Message, userrole string, keys ...string) (ok bool) {
}
}
- if m.Warn(!ok, ice.ErrNotRight, userrole, " of ", keys) {
+ if m.Warn(!ok, ice.ErrNotRight, userrole, ice.OF, keys) {
return
}
if userrole == TECH {
@@ -72,7 +75,7 @@ func _role_right(m *ice.Message, userrole string, keys ...string) (ok bool) {
}
}
- if m.Warn(!ok, ice.ErrNotRight, userrole, " of ", keys) {
+ if m.Warn(!ok, ice.ErrNotRight, userrole, ice.OF, keys) {
return
}
// 普通用户
@@ -117,13 +120,13 @@ func init() {
}},
BLACK: {Name: "black role chain...", Help: "黑名单", Hand: func(m *ice.Message, arg ...string) {
- _role_black(m, arg[0], strings.ReplaceAll(kit.Keys(arg[1:]), "/", ice.PT), true)
+ _role_black(m, arg[0], _role_chain(arg[1:]...), true)
}},
WHITE: {Name: "white role chain...", Help: "白名单", Hand: func(m *ice.Message, arg ...string) {
- _role_white(m, arg[0], strings.ReplaceAll(kit.Keys(arg[1:]), "/", ice.PT), true)
+ _role_white(m, arg[0], _role_chain(arg[1:]...), true)
}},
RIGHT: {Name: "right role chain...", Help: "查看权限", Hand: func(m *ice.Message, arg ...string) {
- if _role_right(m, arg[0], kit.Split(strings.ReplaceAll(kit.Keys(arg[1:]), "/", ice.PT), ice.PT)...) {
+ if _role_right(m, arg[0], kit.Split(_role_chain(arg[1:]...), ice.PT)...) {
m.Echo(ice.OK)
}
}},
diff --git a/conf.go b/conf.go
index 1d120630..97dde5d7 100644
--- a/conf.go
+++ b/conf.go
@@ -5,6 +5,7 @@ const (
SP = " "
PT = "."
NL = "\n"
+ OF = " of "
OK = "ok"
TRUE = "true"
diff --git a/misc/mp/login.go b/misc/mp/login.go
index 2f909115..307a9b51 100644
--- a/misc/mp/login.go
+++ b/misc/mp/login.go
@@ -4,6 +4,7 @@ import (
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/mdb"
+ "shylinux.com/x/icebergs/base/tcp"
"shylinux.com/x/icebergs/base/web"
"shylinux.com/x/icebergs/core/chat"
kit "shylinux.com/x/toolkits"
@@ -14,50 +15,48 @@ const (
APPMM = "appmm"
ACCESS = "access"
OPENID = "openid"
- WEIXIN = "weixin"
)
const LOGIN = "login"
func init() {
- Index.Merge(&ice.Context{
- Configs: map[string]*ice.Config{
- LOGIN: {Name: LOGIN, Help: "认证", Value: kit.Data(
- WEIXIN, "https://api.weixin.qq.com", APPID, "", APPMM, "",
- )},
- },
- Commands: map[string]*ice.Command{
- ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
- m.Cmd(web.SPIDE, mdb.CREATE, WEIXIN, m.Conf(LOGIN, kit.Keym(WEIXIN)))
- }},
- "/login/": {Name: "/login/", Help: "认证", Action: map[string]*ice.Action{
- aaa.SESS: {Name: "sess code", Help: "会话", Hand: func(m *ice.Message, arg ...string) {
- msg := m.Cmd(web.SPIDE, WEIXIN, web.SPIDE_GET, "/sns/jscode2session?grant_type=authorization_code",
- "js_code", m.Option(kit.MDB_CODE), APPID, m.Conf(LOGIN, kit.Keym(APPID)), "secret", m.Conf(LOGIN, kit.Keym(APPMM)))
+ Index.Merge(&ice.Context{Configs: map[string]*ice.Config{
+ LOGIN: {Name: LOGIN, Help: "认证", Value: kit.Data(
+ tcp.SERVER, "https://api.weixin.qq.com",
+ APPID, "", APPMM, "", "tokens", "",
+ )},
+ }, Commands: map[string]*ice.Command{
+ ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
+ m.Cmd(web.SPIDE, mdb.CREATE, MP, m.Conf(LOGIN, kit.Keym(tcp.SERVER)))
+ }},
+ "/login/": {Name: "/login/", Help: "认证", Action: map[string]*ice.Action{
+ aaa.SESS: {Name: "sess code", Help: "会话", Hand: func(m *ice.Message, arg ...string) {
+ msg := m.Cmd(web.SPIDE, MP, web.SPIDE_GET, "/sns/jscode2session?grant_type=authorization_code",
+ "js_code", m.Option(kit.MDB_CODE), APPID, m.Config(APPID), "secret", m.Config(APPMM))
- // 用户登录
- m.Option(ice.MSG_USERZONE, MP)
- m.Echo(aaa.SessCreate(msg, msg.Append(OPENID)))
- }},
- aaa.USER: {Name: "user", Help: "用户", Hand: func(m *ice.Message, arg ...string) {
- m.Option(aaa.USERNAME, m.Option(ice.MSG_USERNAME))
- m.Cmd(aaa.USER, mdb.MODIFY, aaa.USERZONE, MP, aaa.USERNICK, m.Option("nickName"),
- aaa.AVATAR, m.Option("avatarUrl"), aaa.GENDER, kit.Select("女", "男", m.Option(aaa.GENDER) == "1"),
- aaa.COUNTRY, m.Option(aaa.COUNTRY), aaa.LANGUAGE, m.Option(aaa.LANGUAGE),
- aaa.CITY, m.Option(aaa.CITY), aaa.PROVINCE, m.Option(aaa.PROVINCE),
- )
- }},
- chat.SCAN: {Name: "scan", Help: "扫码", Hand: func(m *ice.Message, arg ...string) {
- m.Cmdy(chat.SCAN, arg)
- }},
+ // 用户登录
+ m.Option(ice.MSG_USERZONE, MP)
+ m.Echo(aaa.SessCreate(msg, msg.Append(OPENID)))
}},
- LOGIN: {Name: "login appid auto login", Help: "认证", Action: map[string]*ice.Action{
- mdb.CREATE: {Name: "create appid appmm", Help: "登录", Hand: func(m *ice.Message, arg ...string) {
- m.Conf(LOGIN, kit.Keym(APPID), m.Option(APPID))
- m.Conf(LOGIN, kit.Keym(APPMM), m.Option(APPMM))
- }},
- }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
- m.Echo(m.Conf(LOGIN, kit.Keym(APPID)))
+ aaa.USER: {Name: "user", Help: "用户", Hand: func(m *ice.Message, arg ...string) {
+ m.Option(aaa.USERNAME, m.Option(ice.MSG_USERNAME))
+ m.Cmd(aaa.USER, mdb.MODIFY, aaa.USERZONE, MP, aaa.USERNICK, m.Option("nickName"),
+ aaa.AVATAR, m.Option("avatarUrl"), aaa.GENDER, kit.Select("女", "男", m.Option(aaa.GENDER) == "1"),
+ aaa.COUNTRY, m.Option(aaa.COUNTRY), aaa.LANGUAGE, m.Option(aaa.LANGUAGE),
+ aaa.CITY, m.Option(aaa.CITY), aaa.PROVINCE, m.Option(aaa.PROVINCE),
+ )
}},
- },
+ chat.SCAN: {Name: "scan", Help: "扫码", Hand: func(m *ice.Message, arg ...string) {
+ m.Cmdy(chat.SCAN, arg)
+ }},
+ }},
+ LOGIN: {Name: "login appid auto login", Help: "认证", Action: map[string]*ice.Action{
+ mdb.CREATE: {Name: "create appid appmm", Help: "登录", Hand: func(m *ice.Message, arg ...string) {
+ m.Config(APPID, m.Option(APPID))
+ m.Config(APPMM, m.Option(APPMM))
+ }},
+ }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
+ m.Echo(m.Config(APPID))
+ }},
+ },
})
}
diff --git a/misc/mp/mp.go b/misc/mp/mp.go
index 931c6a94..d7a3a1fe 100644
--- a/misc/mp/mp.go
+++ b/misc/mp/mp.go
@@ -8,15 +8,6 @@ import (
const MP = "mp"
-var Index = &ice.Context{Name: MP, Help: "小程序",
- Commands: map[string]*ice.Command{
- ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
- m.Load()
- }},
- ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
- m.Save()
- }},
- },
-}
+var Index = &ice.Context{Name: MP, Help: "小程序"}
func init() { chat.Index.Register(Index, &web.Frame{}) }
diff --git a/misc/mp/mp.shy b/misc/mp/mp.shy
index 4745af60..d4297507 100644
--- a/misc/mp/mp.shy
+++ b/misc/mp/mp.shy
@@ -1,5 +1,5 @@
title "微信小程序"
-refer "" `
+refer `
官网 https://weixin.qq.com/
后台 https://mp.weixin.qq.com/
文档 https://developers.weixin.qq.com/miniprogram/dev/api/
diff --git a/misc/wework/bot.go b/misc/wework/bot.go
index 52e9f8b3..2a231516 100644
--- a/misc/wework/bot.go
+++ b/misc/wework/bot.go
@@ -5,8 +5,6 @@ import (
"crypto/cipher"
"crypto/sha1"
"encoding/base64"
- "encoding/hex"
- "sort"
"strings"
ice "shylinux.com/x/icebergs"
@@ -20,35 +18,40 @@ const BOT = "bot"
func init() {
Index.Merge(&ice.Context{Configs: map[string]*ice.Config{
BOT: {Name: "bot", Help: "机器人", Value: kit.Data(
- kit.MDB_SHORT, "name", kit.MDB_FIELD, "time,name,token,ekey,hook",
+ kit.MDB_SHORT, kit.MDB_NAME, kit.MDB_FIELD, "time,name,token,ekey,hook",
)},
}, Commands: map[string]*ice.Command{
- ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Load() }},
- ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Save() }},
web.WEB_LOGIN: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
- "/bot/": {Name: "/bot", Help: "机器人", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
+ "/bot/": {Name: "/bot/", Help: "机器人", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
msg := m.Cmd(BOT, arg[0])
- list := []string{msg.Append("token"), m.Option("nonce"), m.Option("timestamp"), m.Option("echostr")}
- sort.Strings(list)
- res := sha1.Sum([]byte(strings.Join(list, "")))
- m.Debug(hex.EncodeToString(res[:]))
+ check := kit.Sort([]string{msg.Append("token"), m.Option("nonce"), m.Option("timestamp"), m.Option("echostr")})
+ sig := kit.Format(sha1.Sum([]byte(strings.Join(check, ""))))
+ m.Debug("what %v", sig)
+ m.Debug("what %v", check)
+ if m.Warn(sig != m.Option("msg_signature"), ice.ErrNotRight) {
+ // return
+ }
- aeskey, err := base64.StdEncoding.DecodeString(msg.Append("ekey"))
+ m.Debug("what %v", msg.Append("ekey"))
+ aeskey, err := base64.RawURLEncoding.DecodeString(msg.Append("ekey"))
m.Assert(err)
- en_msg, err := base64.StdEncoding.DecodeString(m.Option("echostr"))
+
+ en_msg, err := base64.RawURLEncoding.DecodeString(m.Option("echostr"))
m.Assert(err)
+
block, err := aes.NewCipher(aeskey)
m.Assert(err)
+
mode := cipher.NewCBCDecrypter(block, aeskey[:aes.BlockSize])
mode.CryptBlocks(en_msg, en_msg)
-
}},
BOT: {Name: "bot name chat text:textarea auto create", Help: "机器人", Action: ice.MergeAction(map[string]*ice.Action{
- mdb.CREATE: {Name: "create name token ekey hook", Help: "创建"},
+ mdb.CREATE: {Name: "create name token ekey hook", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
+ m.Cmd(web.SPIDE, mdb.CREATE, m.Option("name"), m.Option("hook"))
+ m.Cmdy(mdb.INSERT, m.PrefixKey(), "", mdb.HASH, arg)
+ }},
}, mdb.HashAction()), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if mdb.HashSelect(m, arg...); len(arg) > 2 {
- m.SetAppend()
- m.Cmd(web.SPIDE, mdb.CREATE, arg[0], m.Append("hook"))
m.Cmdy(web.SPIDE, arg[0], "", kit.Format(kit.Dict(
"chatid", arg[1], "msgtype", "text", "text.content", arg[2],
)))
diff --git a/misc/wework/wework.go b/misc/wework/wework.go
index 67a978a8..f9ef8304 100644
--- a/misc/wework/wework.go
+++ b/misc/wework/wework.go
@@ -6,6 +6,8 @@ import (
"shylinux.com/x/icebergs/core/chat"
)
-var Index = &ice.Context{Name: "wework", Help: "企业微信"}
+const WEWORK = "wework"
+
+var Index = &ice.Context{Name: WEWORK, Help: "企业微信"}
func init() { chat.Index.Register(Index, &web.Frame{}) }
diff --git a/misc/wx/access.go b/misc/wx/access.go
index 4244e72e..73cf11be 100644
--- a/misc/wx/access.go
+++ b/misc/wx/access.go
@@ -21,6 +21,7 @@ func _wx_sign(m *ice.Message, nonce, stamp string) string {
kit.Format("noncestr=%s", nonce),
}), "&"))))
}
+
func _wx_config(m *ice.Message, nonce string) {
m.Option(APPID, m.Config(APPID))
m.Option(ssh.SCRIPT, m.Config(ssh.SCRIPT))
@@ -36,7 +37,6 @@ const (
EXPIRES = "expires"
)
const (
- WEIXIN = "weixin"
ERRCODE = "errcode"
ERRMSG = "errmsg"
)
@@ -51,7 +51,7 @@ func init() {
)},
}, Commands: map[string]*ice.Command{
ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
- m.Cmd(web.SPIDE, mdb.CREATE, WEIXIN, m.Config(tcp.SERVER))
+ m.Cmd(web.SPIDE, mdb.CREATE, WX, m.Conf(ACCESS, kit.Keym(tcp.SERVER)))
}},
ACCESS: {Name: "access appid auto ticket token login", Help: "认证", Action: map[string]*ice.Action{
LOGIN: {Name: "login appid appmm token", Help: "登录", Hand: func(m *ice.Message, arg ...string) {
@@ -61,7 +61,7 @@ func init() {
}},
TOKEN: {Name: "token", Help: "令牌", Hand: func(m *ice.Message, arg ...string) {
if now := time.Now().Unix(); m.Config(TOKEN) == "" || now > kit.Int64(m.Config(EXPIRE)) {
- msg := m.Cmd(web.SPIDE, WEIXIN, web.SPIDE_GET, "/cgi-bin/token?grant_type=client_credential",
+ msg := m.Cmd(web.SPIDE, WX, web.SPIDE_GET, "/cgi-bin/token?grant_type=client_credential",
APPID, m.Config(APPID), "secret", m.Config(APPMM))
if m.Warn(msg.Append(ERRCODE) != "", msg.Append(ERRCODE), msg.Append(ERRMSG)) {
return
@@ -74,7 +74,7 @@ func init() {
}},
TICKET: {Name: "ticket", Help: "票据", Hand: func(m *ice.Message, arg ...string) {
if now := time.Now().Unix(); m.Conf(TICKET) == "" || now > kit.Int64(m.Config(EXPIRES)) {
- msg := m.Cmd(web.SPIDE, WEIXIN, web.SPIDE_GET, "/cgi-bin/ticket/getticket?type=jsapi", "access_token", m.Cmdx(ACCESS, TOKEN))
+ msg := m.Cmd(web.SPIDE, WX, web.SPIDE_GET, "/cgi-bin/ticket/getticket?type=jsapi", "access_token", m.Cmdx(ACCESS, TOKEN))
if m.Warn(msg.Append(ERRCODE) != "0", msg.Append(ERRCODE), msg.Append(ERRMSG)) {
return
}
@@ -88,7 +88,7 @@ func init() {
_wx_config(m, "some")
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
- m.Echo(kit.Formats(m.Confv(ACCESS)))
+ m.Echo(m.Config(APPID))
}},
}})
}
diff --git a/misc/wx/login.go b/misc/wx/login.go
index 0274a1ea..7969ff8e 100644
--- a/misc/wx/login.go
+++ b/misc/wx/login.go
@@ -8,11 +8,20 @@ import (
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/mdb"
- "shylinux.com/x/icebergs/base/web"
- "shylinux.com/x/icebergs/core/wiki"
kit "shylinux.com/x/toolkits"
)
+func _wx_check(m *ice.Message) bool {
+ check := kit.Sort([]string{m.Conf(ACCESS, "meta.tokens"), m.Option("timestamp"), m.Option("nonce")})
+ if sig := kit.Format(sha1.Sum([]byte(strings.Join(check, "")))); m.Warn(sig != m.Option("signature"), ice.ErrNotRight) {
+ return false // 验证失败
+ }
+ if m.Option("echostr") != "" {
+ m.RenderResult(m.Option("echostr"))
+ return false // 绑定验证
+ }
+ return true
+}
func _wx_parse(m *ice.Message) {
data := struct {
FromUserName string
@@ -40,38 +49,6 @@ func _wx_reply(m *ice.Message, tmpl string) {
m.Set(ice.MSG_RESULT).RenderResult(string(res))
}
}
-func _wx_action(m *ice.Message) {
- m.Set(ice.MSG_RESULT).RenderResult()
-
- m.Echo(`
-
-
-%s
-
-`, m.Option("ToUserName"), m.Option("FromUserName"), m.Option("CreateTime"), "news")
-
- count := 0
- m.Table(func(index int, value map[string]string, head []string) { count++ })
- m.Echo(`%d`, count)
-
- share := m.Cmdx(web.SHARE, mdb.CREATE, kit.MDB_TYPE, web.LOGIN)
-
- m.Echo(``)
- m.Table(func(index int, value map[string]string, head []string) {
- m.Echo(`-
-
-
-
-
-
-`, value[wiki.TITLE], value[wiki.SPARK], value[wiki.IMAGE],
- kit.MergeURL(kit.Format(value[wiki.REFER]), web.SHARE, share))
- })
- m.Echo(``)
- m.Echo(``)
-
- m.Debug("echo: %v", m.Result())
-}
const LOGIN = "login"
@@ -80,13 +57,8 @@ func init() {
LOGIN: {Name: LOGIN, Help: "登录", Value: kit.Data()},
}, Commands: map[string]*ice.Command{
"/login/": {Name: "/login/", Help: "认证", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
- check := kit.Sort([]string{m.Conf(ACCESS, "meta.tokens"), m.Option("timestamp"), m.Option("nonce")})
- if sig := kit.Format(sha1.Sum([]byte(strings.Join(check, "")))); m.Warn(sig != m.Option("signature"), ice.ErrNotRight) {
- return // 验证失败
- }
- if m.Option("echostr") != "" {
- m.RenderResult(m.Option("echostr"))
- return // 绑定验证
+ if !_wx_check(m) {
+ return // 验签失败
}
// 解析数据
diff --git a/misc/wx/menu.go b/misc/wx/menu.go
index 4869e38b..86c21e93 100644
--- a/misc/wx/menu.go
+++ b/misc/wx/menu.go
@@ -3,9 +3,44 @@ package wx
import (
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb"
+ "shylinux.com/x/icebergs/base/web"
+ "shylinux.com/x/icebergs/core/wiki"
kit "shylinux.com/x/toolkits"
)
+func _wx_action(m *ice.Message) {
+ m.Set(ice.MSG_RESULT).RenderResult()
+
+ m.Echo(`
+
+
+%s
+
+`, m.Option("ToUserName"), m.Option("FromUserName"), m.Option("CreateTime"), "news")
+
+ count := 0
+ m.Table(func(index int, value map[string]string, head []string) { count++ })
+ m.Echo(`%d`, count)
+
+ share := m.Cmdx(web.SHARE, mdb.CREATE, kit.MDB_TYPE, web.LOGIN)
+
+ m.Echo(``)
+ m.Table(func(index int, value map[string]string, head []string) {
+ m.Echo(`-
+
+
+
+
+
+`, value[wiki.TITLE], value[wiki.SPARK], value[wiki.IMAGE],
+ kit.MergeURL(kit.Format(value[wiki.REFER]), web.SHARE, share))
+ })
+ m.Echo(``)
+ m.Echo(``)
+
+ m.Debug("echo: %v", m.Result())
+}
+
const MENU = "menu"
func init() {
diff --git a/misc/wx/wx.go b/misc/wx/wx.go
index 599f9fa1..4e12282a 100644
--- a/misc/wx/wx.go
+++ b/misc/wx/wx.go
@@ -8,13 +8,6 @@ import (
const WX = "wx"
-var Index = &ice.Context{Name: WX, Help: "公众号", Commands: map[string]*ice.Command{
- ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
- m.Load()
- }},
- ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
- m.Save()
- }},
-}}
+var Index = &ice.Context{Name: WX, Help: "公众号"}
func init() { chat.Index.Register(Index, &web.Frame{}) }
diff --git a/misc/wx/wx.shy b/misc/wx/wx.shy
index 2193e6fa..01c496c7 100644
--- a/misc/wx/wx.shy
+++ b/misc/wx/wx.shy
@@ -23,6 +23,9 @@ field "共享" web.share
field "会话" aaa.sess
field "用户" aaa.user
+chapter "企业微信"
+field "机器人" web.chat.wework.bot
+
chapter "项目"
field "源代码" web.code.inner args `usr/icebergs/ misc/wx/wx.go`
field "趋势图" web.code.git.trend args `icebergs`
diff --git a/render.go b/render.go
index 0cddcb5d..dd621f79 100644
--- a/render.go
+++ b/render.go
@@ -26,7 +26,7 @@ func Render(m *Message, cmd string, args ...interface{}) string {
break
}
list := []string{}
- for _, k := range kit.Split(strings.ToLower(kit.Join(arg))) {
+ for _, k := range kit.Split(kit.Join(arg)) {
list = append(list, kit.Format(``,
k, kit.Select(k, kit.Value(m._cmd.Meta, kit.Keys("_trans", k)), m.Option(MSG_LANGUAGE) != "en")))
}
diff --git a/type.go b/type.go
index 064ac52b..239e7fb8 100644
--- a/type.go
+++ b/type.go
@@ -105,6 +105,12 @@ func (c *Context) Merge(s *Context) *Context {
if c.Commands == nil {
c.Commands = map[string]*Command{}
}
+ if c.Commands[CTX_INIT] == nil {
+ c.Commands[CTX_INIT] = &Command{Hand: func(m *Message, c *Context, cmd string, arg ...string) { m.Load() }}
+ }
+ if c.Commands[CTX_EXIT] == nil {
+ c.Commands[CTX_EXIT] = &Command{Hand: func(m *Message, c *Context, cmd string, arg ...string) { m.Save() }}
+ }
for k, v := range s.Commands {
if o, ok := c.Commands[k]; ok && s != c {
func() {