1
0
forked from x/icebergs

add web.Render

This commit is contained in:
shaoying 2020-03-17 04:04:28 +08:00
parent da9a2d5894
commit 0b9351f5c3
11 changed files with 333 additions and 256 deletions

View File

@ -238,8 +238,25 @@ var Index = &ice.Context{Name: "ssh", Help: "终端模块",
)}, )},
"super": {Name: "super", Help: "super", Value: kit.Data()}, "super": {Name: "super", Help: "super", Value: kit.Data()},
"demo": {Name: "demo", Help: "demo", Value: kit.Data(
"short", "name",
"limit", "5", "least", "2",
)},
}, },
Commands: map[string]*ice.Command{ Commands: map[string]*ice.Command{
"demo": {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
data := m.Richs("demo", nil, arg[0], nil)
if data != nil {
m.Echo("%v", data)
return
}
m.Rich("demo", nil, kit.Dict(
"name", arg[0],
))
}},
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Load() m.Load()
}}, }},

View File

@ -35,66 +35,73 @@ type Frame struct {
send map[string]*ice.Message send map[string]*ice.Message
} }
func Refresh(msg *ice.Message, n int) string {
return fmt.Sprintf(`<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta http-equiv="Refresh" content="%d">
</head>
<body>
请稍后系统初始化中...
</body>
`, n)
}
func Redirect(msg *ice.Message, url string, arg ...interface{}) *ice.Message {
msg.Push("_output", "redirect")
msg.Echo(kit.MergeURL(url, arg...))
return msg
}
func Cookie(msg *ice.Message, sessid string) string {
expire := time.Now().Add(kit.Duration(msg.Conf(ice.AAA_SESS, "meta.expire")))
msg.Log("cookie", "expire:%v sessid:%s", kit.Format(expire), sessid)
http.SetCookie(msg.W, &http.Cookie{Name: ice.WEB_SESS, Value: sessid, Path: "/", Expires: expire})
return sessid
}
func Upload(m *ice.Message, name string) string {
m.Cmdy(ice.WEB_STORY, "upload")
if s, e := os.Stat(name); e == nil && s.IsDir() {
name = path.Join(name, m.Append("name"))
}
m.Cmd(ice.WEB_STORY, ice.STORY_WATCH, m.Append("data"), name)
return name
}
func Count(m *ice.Message, cmd, key, name string) int { func Count(m *ice.Message, cmd, key, name string) int {
count := kit.Int(m.Conf(cmd, kit.Keys(key, name))) count := kit.Int(m.Conf(cmd, kit.Keys(key, name)))
m.Conf(cmd, kit.Keys(key, name), count+1) m.Conf(cmd, kit.Keys(key, name), count+1)
return count return count
} }
func Render(msg *ice.Message, cmd string, args ...interface{}) *ice.Message {
msg.Info("render %s: %v", cmd, args)
switch arg := kit.Simple(args...); cmd {
case "redirect":
http.Redirect(msg.W, msg.R, kit.MergeURL(arg[0], arg[1:]), 307)
case "refresh":
arg = []string{"200", fmt.Sprintf(`<!DOCTYPE html><head><meta charset="utf-8"><meta http-equiv="Refresh" content="%d"></head><body>%s</body>`,
kit.Int(kit.Select("3", arg, 0)), kit.Select("请稍后,系统初始化中...", arg, 1),
)}
fallthrough
case "status":
msg.W.WriteHeader(kit.Int(kit.Select("200", arg, 0)))
msg.W.Write([]byte(kit.Select("", arg, 1)))
case "result":
msg.W.Write([]byte(kit.Format(arg[0], args[1:]...)))
case "cookie":
expire := time.Now().Add(kit.Duration(msg.Conf(ice.AAA_SESS, "meta.expire")))
http.SetCookie(msg.W, &http.Cookie{Value: arg[0], Name: kit.Select(ice.MSG_SESSID, arg, 1), Path: "/", Expires: expire})
case "qrcode":
if qr, e := qrcode.New(arg[0], qrcode.Medium); msg.Assert(e) {
msg.W.Header().Set("Content-Type", "image/png")
msg.Assert(qr.Write(256, msg.W))
}
case "download":
msg.W.Header().Set("Content-Disposition", fmt.Sprintf("filename=%s", kit.Select(path.Base(arg[0]), arg, 2)))
msg.W.Header().Set("Content-Type", kit.Select("text/html", arg, 1))
http.ServeFile(msg.W, msg.R, arg[0])
default:
msg.W.Write([]byte(kit.Format(cmd, args...)))
}
msg.Append("_output", "render")
return msg
}
func IsLocalIP(ip string) bool { func IsLocalIP(ip string) bool {
return ip == "::1" || strings.HasPrefix(ip, "127.") return ip == "::1" || strings.HasPrefix(ip, "127.")
} }
func (web *Frame) Login(msg *ice.Message, w http.ResponseWriter, r *http.Request) bool { func (web *Frame) Login(msg *ice.Message, w http.ResponseWriter, r *http.Request) bool {
msg.Option(ice.MSG_USERNAME, "")
msg.Option(ice.MSG_USERROLE, "")
if msg.Options(ice.WEB_SESS) { if msg.Options(ice.WEB_SESS) {
// 会话认证 // 会话认证
sub := msg.Cmd(ice.AAA_SESS, "check", msg.Option(ice.WEB_SESS)) sub := msg.Cmd(ice.AAA_SESS, "check", msg.Option(ice.WEB_SESS))
msg.Info("role: %s user: %s", msg.Option(ice.MSG_USERROLE, sub.Append("userrole")), msg.Log(ice.LOG_LOGIN, "role: %s user: %s", msg.Option(ice.MSG_USERROLE, sub.Append("userrole")),
msg.Option(ice.MSG_USERNAME, sub.Append("username"))) msg.Option(ice.MSG_USERNAME, sub.Append("username")))
} }
if strings.HasPrefix(msg.Option(ice.MSG_USERURL), "/space/") {
return true
}
if (!msg.Options(ice.MSG_SESSID) || !msg.Options(ice.MSG_USERNAME)) && IsLocalIP(msg.Option(ice.MSG_USERIP)) { if (!msg.Options(ice.MSG_SESSID) || !msg.Options(ice.MSG_USERNAME)) && IsLocalIP(msg.Option(ice.MSG_USERIP)) {
// 自动认证 // 自动认证
msg.Option(ice.MSG_USERNAME, msg.Conf(ice.CLI_RUNTIME, "boot.username")) msg.Option(ice.MSG_USERNAME, msg.Conf(ice.CLI_RUNTIME, "boot.username"))
msg.Option(ice.MSG_USERROLE, msg.Cmdx(ice.AAA_ROLE, "check", msg.Option(ice.MSG_USERNAME))) msg.Option(ice.MSG_USERROLE, msg.Cmdx(ice.AAA_ROLE, "check", msg.Option(ice.MSG_USERNAME)))
msg.Option(ice.MSG_SESSID, msg.Rich(ice.AAA_SESS, nil, kit.Dict( if strings.HasPrefix(msg.Option(ice.MSG_USERUA), "Mozilla/5.0") {
"username", msg.Option(ice.MSG_USERNAME), "userrole", msg.Option(ice.MSG_USERROLE), msg.Option(ice.MSG_SESSID, msg.Cmdx(ice.AAA_SESS, "create", msg.Option(ice.MSG_USERNAME), msg.Option(ice.MSG_USERROLE)))
))) Render(msg, "cookie", msg.Option(ice.MSG_SESSID))
Cookie(msg, msg.Option(ice.MSG_SESSID)) }
msg.Info("user: %s role: %s sess: %s", msg.Option(ice.MSG_USERNAME), msg.Option(ice.MSG_USERROLE), msg.Option(ice.MSG_SESSID)) msg.Log(ice.LOG_LOGIN, "user: %s role: %s sess: %s", msg.Option(ice.MSG_USERNAME), msg.Option(ice.MSG_USERROLE), msg.Option(ice.MSG_SESSID))
} }
if s, ok := msg.Target().Commands[ice.WEB_LOGIN]; ok { if s, ok := msg.Target().Commands[ice.WEB_LOGIN]; ok {
@ -213,7 +220,6 @@ func (web *Frame) HandleCmd(m *ice.Message, key string, cmd *ice.Command) {
msg.Option(ice.MSG_USERUA, r.Header.Get("User-Agent")) msg.Option(ice.MSG_USERUA, r.Header.Get("User-Agent"))
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_USERURL, r.URL.Path) msg.Option(ice.MSG_USERURL, r.URL.Path)
msg.Option(ice.MSG_USERNAME, "")
msg.Option(ice.WEB_SESS, "") msg.Option(ice.WEB_SESS, "")
msg.R, msg.W = r, w msg.R, msg.W = r, w
@ -250,9 +256,8 @@ func (web *Frame) HandleCmd(m *ice.Message, key string, cmd *ice.Command) {
// 请求参数 // 请求参数
for k, v := range r.Form { for k, v := range r.Form {
msg.Optionv(k, v) if msg.Optionv(k, v); k == ice.MSG_SESSID {
if k == ice.MSG_SESSID { Render(msg, "cookie", v[0])
Cookie(msg, v[0])
} }
} }
@ -262,42 +267,19 @@ func (web *Frame) HandleCmd(m *ice.Message, key string, cmd *ice.Command) {
return return
} }
// 解析命令
if msg.Optionv("cmds") == nil { if msg.Optionv("cmds") == nil {
msg.Optionv("cmds", strings.Split(msg.Option(ice.MSG_USERURL), "/")[2:]) msg.Optionv("cmds", strings.Split(msg.Option(ice.MSG_USERURL), "/")[2:])
} }
cmds := kit.Simple(msg.Optionv("cmds")) cmds := kit.Simple(msg.Optionv("cmds"))
// 执行命令 // 执行命令
if msg.Option("proxy") != "" { msg.Target().Run(msg, cmd, msg.Option(ice.MSG_USERURL), cmds...)
msg.Cmd(ice.WEB_PROXY, msg.Option("proxy"), msg.Option(ice.MSG_USERURL), cmds)
} else {
msg.Target().Run(msg, cmd, msg.Option(ice.MSG_USERURL), cmds...)
}
// 输出响应 // 输出响应
switch msg.Append("_output") { switch msg.Append("_output") {
case "void": case "render":
case "status":
msg.Info("status %s", msg.Result())
w.WriteHeader(kit.Int(kit.Select("200", msg.Result(0))))
case "redirect":
http.Redirect(w, r, msg.Result(), 302)
case "file":
msg.Info("_output: %s %s", msg.Append("_output"), msg.Append("file"))
w.Header().Set("Content-Disposition", fmt.Sprintf("filename=%s", kit.Select(msg.Append("name"), msg.Append("story"))))
w.Header().Set("Content-Type", kit.Select("text/html", msg.Append("type")))
http.ServeFile(w, r, msg.Append("file"))
case "qrcode":
if qr, e := qrcode.New(msg.Result(), qrcode.Medium); m.Assert(e) {
w.Header().Set("Content-Type", "image/png")
m.Assert(qr.Write(256, w))
}
case "result": case "result":
w.Header().Set("Content-Type", kit.Select("text/html", msg.Append("type")))
fmt.Fprint(w, msg.Result()) fmt.Fprint(w, msg.Result())
default: default:
fmt.Fprint(w, msg.Formats("meta")) fmt.Fprint(w, msg.Formats("meta"))
@ -341,8 +323,10 @@ func (web *Frame) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// 初始化成功 // 初始化成功
m.Conf(ice.WEB_SERVE, "meta.init", "true") m.Conf(ice.WEB_SERVE, "meta.init", "true")
} }
w.Write([]byte(Refresh(m, 5))) m.W = w
Render(m, "refresh")
m.Event(ice.SYSTEM_INIT) m.Event(ice.SYSTEM_INIT)
m.W = nil
} else { } else {
web.ServeMux.ServeHTTP(w, r) web.ServeMux.ServeHTTP(w, r)
} }
@ -483,16 +467,8 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
m.Conf(ice.WEB_FAVOR, "meta.template", favor_template) m.Conf(ice.WEB_FAVOR, "meta.template", favor_template)
}}, }},
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
p := m.Conf(ice.WEB_CACHE, "meta.store") m.Save(ice.WEB_SPIDE, ice.WEB_SERVE,
m.Richs(ice.WEB_CACHE, nil, "*", func(key string, value map[string]interface{}) { ice.WEB_FAVOR, ice.WEB_CACHE, ice.WEB_STORY, ice.WEB_SHARE)
if f, _, e := kit.Create(path.Join(p, key[:2], key)); e == nil {
defer f.Close()
f.WriteString(kit.Formats(value))
}
})
// m.Conf(ice.WEB_CACHE, "hash", kit.Dict())
m.Save(ice.WEB_FAVOR, ice.WEB_CACHE, ice.WEB_STORY, ice.WEB_SHARE,
ice.WEB_SPIDE, ice.WEB_SERVE)
m.Done() m.Done()
m.Richs(ice.WEB_SPACE, nil, "*", func(key string, value map[string]interface{}) { m.Richs(ice.WEB_SPACE, nil, "*", func(key string, value map[string]interface{}) {
@ -971,10 +947,10 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
), List: kit.List( ), List: kit.List(
kit.MDB_INPUT, "text", "name", "favor", "action", "auto", kit.MDB_INPUT, "text", "name", "favor", "action", "auto",
kit.MDB_INPUT, "text", "name", "id", "action", "auto", kit.MDB_INPUT, "text", "name", "id", "action", "auto",
kit.MDB_INPUT, "button", "value", "查看", "action", "auto", kit.MDB_INPUT, "button", "name", "查看", "action", "auto",
kit.MDB_INPUT, "button", "value", "返回", "cb", "Last", kit.MDB_INPUT, "button", "name", "返回", "cb", "Last",
kit.MDB_INPUT, "button", "value", "渲染", kit.MDB_INPUT, "button", "name", "渲染",
kit.MDB_INPUT, "button", "value", "回放", kit.MDB_INPUT, "button", "name", "回放",
), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch m.Option("_action") { switch m.Option("_action") {
case "渲染": case "渲染":
@ -1055,6 +1031,37 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
return return
} }
switch arg[0] {
case "sync":
m.Richs(ice.WEB_FAVOR, nil, arg[1], func(key string, value map[string]interface{}) {
count := kit.Int(kit.Value(value, kit.Keys("meta.count")))
pull := kit.Int(kit.Value(value, kit.Keys("meta.remote", arg[2], "pull"))) + 1
pull = 1
m.Cmd(ice.WEB_SPIDE, arg[2], "msg", "/favor/pull", "favor", arg[3], "begin", pull).Table(func(index int, value map[string]string, head []string) {
kit.Value(value, kit.Keys("meta.remote", arg[2], arg[3], "pull"), value["id"])
m.Log(ice.LOG_IMPORT, "%v", value)
m.Grow(ice.WEB_FAVOR, kit.Keys(kit.MDB_HASH, key), kit.Dict(
kit.MDB_TYPE, value["type"], kit.MDB_NAME, value["name"], kit.MDB_TEXT, value["text"],
"extra", kit.UnMarshal(value["extra"]),
))
})
push := kit.Int(kit.Value(value, kit.Keys("meta.remote", arg[0], "push"))) + 1
push = 1
for i := push; i <= count; i++ {
m.Grows(ice.WEB_FAVOR, kit.Keys(kit.MDB_HASH, key), "id", kit.Format(i), func(index int, value map[string]interface{}) {
kit.Value(value, kit.Keys("meta.remote", arg[2], arg[3], "push"), value["id"])
m.Cmd(ice.WEB_SPIDE, arg[2], "msg", "/favor/push", "favor", arg[3],
"type", value["type"], "name", value["name"], "text", value["text"],
"time", value["time"], "extra", kit.Format(value["extra"]),
)
})
}
return
})
}
m.Option("favor", arg[0]) m.Option("favor", arg[0])
fields := []string{kit.MDB_TIME, kit.MDB_ID, kit.MDB_TYPE, kit.MDB_NAME, kit.MDB_TEXT} fields := []string{kit.MDB_TIME, kit.MDB_ID, kit.MDB_TYPE, kit.MDB_NAME, kit.MDB_TEXT}
if len(arg) > 1 && arg[1] == "extra" { if len(arg) > 1 && arg[1] == "extra" {
@ -1671,42 +1678,36 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
switch kit.Select("", arg, 1) { switch kit.Select("", arg, 1) {
case "download", "下载": case "download", "下载":
if m.Append("_output", "file"); strings.HasPrefix(kit.Format(value["text"]), m.Conf(ice.WEB_CACHE, "meta.path")) { if strings.HasPrefix(kit.Format(value["text"]), m.Conf(ice.WEB_CACHE, "meta.path")) {
m.Append("type", value["type"]) Render(m, "download", value["text"], value["type"], value["name"])
m.Append("name", value["name"])
m.Append("file", value["text"])
} else { } else {
m.Append("_output", "result") Render(m, "%s", value["text"])
m.Echo("%s", value["text"])
} }
return return
case "detail", "详情": case "detail", "详情":
m.Append("_output", "result") Render(m, kit.Formats(value))
m.Echo(kit.Formats(value))
return return
case "share", "共享码": case "share", "共享码":
m.Append("_output", "qrcode") Render(m, "qrcode", kit.Format("%s/%s/", m.Conf(ice.WEB_SHARE, "meta.domain"), key))
m.Echo("%s/%s/", m.Conf(ice.WEB_SHARE, "meta.domain"), key)
return return
case "value", "数据值": case "value", "数据值":
m.Append("_output", "qrcode") Render(m, "%s", value["text"])
m.Echo("%s", value["text"])
return return
} }
switch value["type"] { switch value["type"] {
case ice.TYPE_RIVER: case ice.TYPE_RIVER:
// 共享群组 // 共享群组
Redirect(m, "/", "share", key, "river", value["text"]) Render(m, "redirect", "/", "share", key, "river", kit.Format(value["text"]))
case ice.TYPE_STORM: case ice.TYPE_STORM:
// 共享应用 // 共享应用
Redirect(m, "/", "share", key, "storm", value["text"], "river", kit.Value(value, "extra.river")) Render(m, "redirect", "/", "share", key, "storm", kit.Format(value["text"]), "river", kit.Format(kit.Value(value, "extra.river")))
case ice.TYPE_ACTION: case ice.TYPE_ACTION:
if len(arg) == 1 { if len(arg) == 1 {
// 跳转主页 // 跳转主页
Redirect(m, "/share/"+arg[0]+"/", "title", value["name"]) Render(m, "redirect", "/share/"+arg[0]+"/", "title", kit.Format(value["name"]))
break break
} }
@ -1757,8 +1758,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
case ice.TYPE_ACTIVE: case ice.TYPE_ACTIVE:
// 扫码数据 // 扫码数据
m.Append("_output", "qrcode") Render(m, "qrcode", kit.Format(value))
m.Echo(kit.Format(value))
default: default:
// 查看数据 // 查看数据
@ -1829,7 +1829,28 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
case ice.STORY_DOWNLOAD: case ice.STORY_DOWNLOAD:
// 下载数据 // 下载数据
m.Cmdy(ice.WEB_STORY, ice.STORY_INDEX, arg[1]) m.Cmdy(ice.WEB_STORY, ice.STORY_INDEX, arg[1])
m.Push("_output", kit.Select("file", "result", m.Append("file") == "")) Render(m, kit.Select("download", "result", m.Append("file") == ""), m.Append("text"))
}
}},
"/favor/": {Name: "/story/", Help: "故事会", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch arg[0] {
case "pull":
m.Richs(ice.WEB_FAVOR, nil, m.Option("favor"), func(key string, value map[string]interface{}) {
m.Option("cache.limit", kit.Int(kit.Value(value, "meta.count"))+1-kit.Int(m.Option("begin")))
m.Grows(ice.WEB_FAVOR, kit.Keys(kit.MDB_HASH, key), "", "", func(index int, value map[string]interface{}) {
m.Log(ice.LOG_EXPORT, "%v", value)
m.Push("", value, []string{"id", "type", "name", "text"})
m.Push("extra", kit.Format(value["extra"]))
})
})
case "push":
m.Richs(ice.WEB_FAVOR, nil, m.Option("favor"), func(key string, value map[string]interface{}) {
m.Log(ice.LOG_IMPORT, "%v", value)
m.Grow(ice.WEB_FAVOR, kit.Keys(kit.MDB_HASH, key), kit.Dict(
kit.MDB_TYPE, m.Option("type"), kit.MDB_NAME, m.Option("name"), kit.MDB_TEXT, m.Option("text"),
"extra", kit.UnMarshal(m.Option("extra")),
))
})
} }
}}, }},
"/space/": {Name: "/space/", Help: "空间站", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { "/space/": {Name: "/space/", Help: "空间站", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
@ -1837,7 +1858,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
switch list[2] { switch list[2] {
case "login": case "login":
m.Option(ice.MSG_SESSID, Cookie(m, m.Cmdx(ice.AAA_USER, "login", m.Option("username"), m.Option("password")))) m.Option(ice.MSG_SESSID, Render(m, "cookie", m.Cmdx(ice.AAA_USER, "login", m.Option("username"), m.Option("password"))))
return return
case "share": case "share":
m.Cmdy(ice.WEB_SHARE, list[3:]) m.Cmdy(ice.WEB_SHARE, list[3:])
@ -1889,8 +1910,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
path.Join("usr/volcanos", strings.Join(strings.Split(cmd, "/")[3:7], "/"))) path.Join("usr/volcanos", strings.Join(strings.Split(cmd, "/")[3:7], "/")))
} }
m.Push("_output", "void") Render(m, "download", path.Join("usr/volcanos", file))
http.ServeFile(m.W, m.R, path.Join("usr/volcanos", file))
}}, }},
"/plugin/github.com/": {Name: "/space/", Help: "空间站", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { "/plugin/github.com/": {Name: "/space/", Help: "空间站", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if _, e := os.Stat(path.Join("usr/volcanos", cmd)); e != nil { if _, e := os.Stat(path.Join("usr/volcanos", cmd)); e != nil {
@ -1898,8 +1918,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
path.Join("usr/volcanos", strings.Join(strings.Split(cmd, "/")[1:5], "/"))) path.Join("usr/volcanos", strings.Join(strings.Split(cmd, "/")[1:5], "/")))
} }
m.Push("_output", "void") Render(m, "download", path.Join("usr/volcanos", cmd))
http.ServeFile(m.W, m.R, path.Join("usr/volcanos", cmd))
}}, }},
}, },
} }

View File

@ -86,19 +86,19 @@ const ( // LOG
// 数据 // 数据
LOG_ENABLE = "enable" LOG_ENABLE = "enable"
LOG_IMPORT = "import" LOG_IMPORT = "import"
LOG_EXPORT = "export"
LOG_CREATE = "create" LOG_CREATE = "create"
LOG_REMOVE = "remove"
LOG_INSERT = "insert" LOG_INSERT = "insert"
LOG_DELETE = "delete"
LOG_SELECT = "select" LOG_SELECT = "select"
LOG_MODIFY = "modify" LOG_MODIFY = "modify"
LOG_DELETE = "delete"
LOG_REMOVE = "remove"
LOG_EXPORT = "export"
// 事件 // 事件
LOG_LISTEN = "listen" LOG_LISTEN = "listen"
LOG_SIGNAL = "signal" LOG_SIGNAL = "signal"
LOG_TIMERS = "timers"
LOG_EVENTS = "events" LOG_EVENTS = "events"
LOG_TIMERS = "timers"
// 状态 // 状态
LOG_BEGIN = "begin" LOG_BEGIN = "begin"
@ -165,6 +165,7 @@ const ( // ROLE
) )
const ( // CHAT const ( // CHAT
CHAT_RIVER = "river" CHAT_RIVER = "river"
CHAT_STORM = "storm"
) )
const ( // TYPE const ( // TYPE
TYPE_SPIDE = "spide" TYPE_SPIDE = "spide"

View File

@ -2,7 +2,6 @@ package chat
import ( import (
"github.com/shylinux/icebergs" "github.com/shylinux/icebergs"
_ "github.com/shylinux/icebergs/base"
"github.com/shylinux/icebergs/base/web" "github.com/shylinux/icebergs/base/web"
"github.com/shylinux/toolkits" "github.com/shylinux/toolkits"
) )
@ -55,6 +54,7 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心",
[]interface{}{"field", "note", "web.wiki"}, []interface{}{"field", "note", "web.wiki"},
}), }),
"black", kit.Dict("void", []interface{}{ "black", kit.Dict("void", []interface{}{
[]interface{}{"/debug"},
[]interface{}{"/river", "add"}, []interface{}{"/river", "add"},
[]interface{}{"/river", "share"}, []interface{}{"/river", "share"},
[]interface{}{"/river", "rename"}, []interface{}{"/river", "rename"},
@ -65,6 +65,10 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心",
[]interface{}{"/storm", "add"}, []interface{}{"/storm", "add"},
}), }),
"white", kit.Dict("void", []interface{}{ "white", kit.Dict("void", []interface{}{
[]interface{}{"/toast"},
[]interface{}{"/carte"},
[]interface{}{"/tutor"},
[]interface{}{"/login"},
[]interface{}{"/river"}, []interface{}{"/river"},
[]interface{}{"/storm"}, []interface{}{"/storm"},
[]interface{}{"/action"}, []interface{}{"/action"},
@ -75,9 +79,9 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心",
}, },
Commands: map[string]*ice.Command{ Commands: map[string]*ice.Command{
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Watch(ice.USER_CREATE, m.Prefix(ice.WEB_LOGIN), "init")
m.Watch(ice.SYSTEM_INIT, m.Prefix("init"))
m.Load() m.Load()
m.Watch(ice.SYSTEM_INIT, m.Prefix("init"))
m.Watch(ice.USER_CREATE, m.Prefix("auto"))
}}, }},
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Save("river") m.Save("river")
@ -103,8 +107,7 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心",
m.Cmd(ice.AAA_ROLE, "white", ice.ROLE_VOID, "enable", value) m.Cmd(ice.AAA_ROLE, "white", ice.ROLE_VOID, "enable", value)
}) })
} }
// 超级用户
// 用户权限
m.Cmd(ice.AAA_USER, "first", m.Conf(ice.CLI_RUNTIME, "boot.username")) m.Cmd(ice.AAA_USER, "first", m.Conf(ice.CLI_RUNTIME, "boot.username"))
} }
@ -113,50 +116,58 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心",
m.Cap(ice.CTX_STREAM, m.Conf(ice.CHAT_RIVER, "meta.fe")) m.Cap(ice.CTX_STREAM, m.Conf(ice.CHAT_RIVER, "meta.fe"))
m.Cap(ice.CTX_STATUS, "start") m.Cap(ice.CTX_STATUS, "start")
}}, }},
ice.WEB_LOGIN: {Name: "_login", Help: "登录", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { "auto": {Name: "auto user", Help: "自动化", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Richs(ice.AAA_USER, nil, arg[0], func(key string, value map[string]interface{}) {
m.Option(ice.MSG_USERNAME, value["username"])
m.Option(ice.MSG_USERROLE, m.Cmdx(ice.AAA_ROLE, "check", value["username"]))
if len(arg[0]) > 8 {
arg[0] = arg[0][:8]
}
// 创建群组
name := kit.Select(arg[0], value["nickname"]) + "@" + m.Conf(ice.CLI_RUNTIME, "boot.hostname")
storm, river := "", m.Option(ice.MSG_RIVER, m.Cmdx("/ocean", "spawn", name, m.Option(ice.MSG_USERNAME)))
// 创建应用
m.Option("cache.limit", -2)
m.Richs(ice.WEB_FAVOR, nil, kit.Keys("river", m.Option(ice.MSG_USERROLE)), func(key string, value map[string]interface{}) {
m.Grows(ice.WEB_FAVOR, kit.Keys("hash", key), "", "", func(index int, value map[string]interface{}) {
switch value["type"] {
case "storm":
storm = m.Option(ice.MSG_STORM, m.Cmdx("/steam", river, "spawn", value["name"]))
case "field":
m.Cmd("/storm", river, storm, "add", "", kit.Select("", value["text"]), value["name"], "")
}
})
})
})
}},
ice.WEB_LOGIN: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Option(ice.MSG_RIVER, "")
m.Option(ice.MSG_STORM, "")
if len(arg) > 0 { if len(arg) > 0 {
switch arg[0] { switch arg[0] {
case "login": case "login":
// 用户登录 // 密码登录
m.Option(ice.MSG_SESSID, web.Cookie(m, m.Cmdx(ice.AAA_USER, "login", m.Option(ice.MSG_USERNAME, arg[1]), arg[2]))) if len(arg) > 2 {
m.Option(ice.MSG_SESSID, web.Render(m, "cookie", m.Cmdx(ice.AAA_USER, "login", m.Option(ice.MSG_USERNAME, arg[1]), arg[2])))
case "init": }
// 用户创建
m.Richs(ice.AAA_USER, nil, arg[1], func(key string, value map[string]interface{}) {
m.Option(ice.MSG_USERNAME, value["username"])
m.Option(ice.MSG_USERROLE, m.Cmdx(ice.AAA_ROLE, "check", value["username"]))
name := kit.Select(arg[1], value["nickname"]) + "@" + m.Conf(ice.CLI_RUNTIME, "boot.hostname")
if len(arg[1]) > 8 {
name = kit.Select(arg[1][:8], value["nickname"]) + "@" + m.Conf(ice.CLI_RUNTIME, "boot.hostname")
}
// 创建群组
storm, river := "", m.Option(ice.MSG_RIVER, m.Cmdx("/ocean", "spawn", name, m.Option(ice.MSG_USERNAME)))
// 创建应用
m.Option("cache.limit", "100")
m.Richs(ice.WEB_FAVOR, nil, kit.Keys("river", m.Option(ice.MSG_USERROLE)), func(key string, value map[string]interface{}) {
m.Grows(ice.WEB_FAVOR, kit.Keys("hash", key), "", "", func(index int, value map[string]interface{}) {
switch value["type"] {
case "storm":
storm = m.Option(ice.MSG_STORM, m.Cmdx("/steam", river, "spawn", value["name"]))
case "field":
m.Cmd("/storm", river, storm, "add", "", kit.Select("", value["text"]), value["name"], "")
}
})
})
})
default: default:
// 用户群组 // 群组检查
m.Richs(ice.CHAT_RIVER, nil, arg[0], func(value map[string]interface{}) { m.Richs(ice.CHAT_RIVER, nil, arg[0], func(key string, value map[string]interface{}) {
if m.Option(ice.MSG_RIVER, arg[0]); len(arg) > 1 { m.Richs(ice.CHAT_RIVER, kit.Keys(kit.MDB_HASH, arg[0], "user"), m.Option(ice.MSG_USERNAME), func(key string, value map[string]interface{}) {
m.Richs(ice.CHAT_RIVER, kit.Keys(kit.MDB_HASH, arg[0], "tool"), arg[1], func(value map[string]interface{}) { if m.Option(ice.MSG_RIVER, arg[0]); len(arg) > 1 {
m.Option(ice.MSG_STORM, arg[1]) // 应用检查
}) m.Richs(ice.CHAT_RIVER, kit.Keys(kit.MDB_HASH, arg[0], "tool"), arg[1], func(key string, value map[string]interface{}) {
} m.Option(ice.MSG_STORM, arg[1])
m.Info("river: %s storm: %s", m.Option(ice.MSG_RIVER), m.Option(ice.MSG_STORM)) })
}
m.Log(ice.LOG_LOGIN, "river: %s storm: %s", m.Option(ice.MSG_RIVER), m.Option(ice.MSG_STORM))
})
}) })
} }
} }
@ -166,33 +177,24 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心",
// 登录检查 // 登录检查
if m.Warn(!m.Options(ice.MSG_SESSID) || !m.Options(ice.MSG_USERNAME), "not login") { if m.Warn(!m.Options(ice.MSG_SESSID) || !m.Options(ice.MSG_USERNAME), "not login") {
web.Render(m, "status", 401, "not login")
m.Option(ice.MSG_USERURL, "") m.Option(ice.MSG_USERURL, "")
m.Push("_output", "status")
m.Set("result").Echo("401")
return return
} }
// 权限检查 // 权限检查
if !m.Right(m.Option(ice.MSG_USERURL), m.Optionv("cmds")) { if m.Warn(!m.Right(m.Option(ice.MSG_USERURL), m.Optionv("cmds")), "not auth") {
web.Render(m, "status", 403, "not auth")
m.Option(ice.MSG_USERURL, "") m.Option(ice.MSG_USERURL, "")
m.Push("_output", "status")
m.Set("result").Echo("403")
return return
} }
}}, }},
"/toast": {Name: "/toast", Help: "提示", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}}, "/toast": {Name: "/toast", Help: "提示", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
"/carte": {Name: "/carte", Help: "菜单", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}}, "/carte": {Name: "/carte", Help: "菜单", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
"/debug": {Name: "/debug", Help: "调试", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
"/tutor": {Name: "/tutor", Help: "向导", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}}, "/tutor": {Name: "/tutor", Help: "向导", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
"/favor": {Name: "/favor", Help: "收藏", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { "/debug": {Name: "/debug", Help: "调试", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
m.Hand = false "/input": {Name: "/input", Help: "输入", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
if msg := m.Cmd(arg); !msg.Hand {
m.Set("result").Cmdy(ice.CLI_SYSTEM, arg)
} else {
m.Copy(msg)
}
}},
"/login": {Name: "/login", Help: "登录", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { "/login": {Name: "/login", Help: "登录", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch arg[0] { switch arg[0] {
case "check": case "check":
@ -254,8 +256,7 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心",
} }
}}, }},
"/river": {Name: "/river", Help: "小河流", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { "/river": {Name: "/river", Help: "小河流", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch len(arg) { if len(arg) < 2 {
case 0:
// 群组列表 // 群组列表
m.Richs(ice.CHAT_RIVER, nil, "*", func(key string, value map[string]interface{}) { m.Richs(ice.CHAT_RIVER, nil, "*", func(key string, value map[string]interface{}) {
m.Richs(ice.CHAT_RIVER, kit.Keys(kit.MDB_HASH, key, "user"), m.Option(ice.MSG_USERNAME), func(k string, val map[string]interface{}) { m.Richs(ice.CHAT_RIVER, kit.Keys(kit.MDB_HASH, key, "user"), m.Option(ice.MSG_USERNAME), func(k string, val map[string]interface{}) {
@ -263,45 +264,44 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心",
}) })
}) })
m.Log(ice.LOG_SELECT, "%s", m.Format("append")) m.Log(ice.LOG_SELECT, "%s", m.Format("append"))
case 1: return
// 群组详情 }
m.Richs(ice.CHAT_RIVER, nil, arg[0], func(key string, value map[string]interface{}) {
m.Push(key, value["meta"], []string{kit.MDB_KEY, kit.MDB_NAME}) if !m.Right(cmd, arg[1]) {
web.Render(m, "status", 403, "not auth")
return
}
switch arg[1] {
case "add":
m.Rich(ice.CHAT_RIVER, kit.Keys(kit.MDB_HASH, arg[0], "user"), kit.Data("username", m.Conf(ice.CLI_RUNTIME, "boot.username")))
// 添加用户
for _, v := range arg[2:] {
user := m.Rich(ice.CHAT_RIVER, kit.Keys(kit.MDB_HASH, arg[0], "user"), kit.Data("username", v))
m.Log(ice.LOG_INSERT, "river: %s user: %s name: %s", arg[0], user, v)
}
case "rename":
// 重命名群组
old := m.Conf(ice.CHAT_RIVER, kit.Keys(kit.MDB_HASH, arg[0], kit.MDB_META, kit.MDB_NAME))
m.Log(ice.LOG_MODIFY, "river: %s %s->%s", arg[0], old, arg[2])
m.Conf(ice.CHAT_RIVER, kit.Keys(kit.MDB_HASH, arg[0], kit.MDB_META, kit.MDB_NAME), arg[2])
case "remove":
// 删除群组
m.Richs(ice.CHAT_RIVER, nil, arg[0], func(value map[string]interface{}) {
m.Log(ice.LOG_REMOVE, "river: %s value: %s", arg[0], kit.Format(value))
}) })
default: m.Conf(ice.CHAT_RIVER, kit.Keys(kit.MDB_HASH, arg[0]), "")
if !m.Right(cmd, arg[1]) {
// 没有权限
m.Push("_output", "status")
m.Set("result").Echo("403")
break
}
switch arg[1] {
case "add":
m.Rich(ice.CHAT_RIVER, kit.Keys(kit.MDB_HASH, arg[0], "user"), kit.Data("username", m.Conf(ice.CLI_RUNTIME, "boot.username")))
// 添加用户
for _, v := range arg[2:] {
user := m.Rich(ice.CHAT_RIVER, kit.Keys(kit.MDB_HASH, arg[0], "user"), kit.Data("username", v))
m.Log(ice.LOG_INSERT, "river: %s user: %s name: %s", arg[0], user, v)
}
case "rename":
// 重命名群组
old := m.Conf(ice.CHAT_RIVER, kit.Keys(kit.MDB_HASH, arg[0], kit.MDB_META, kit.MDB_NAME))
m.Log(ice.LOG_MODIFY, "river: %s %s->%s", arg[0], old, arg[2])
m.Conf(ice.CHAT_RIVER, kit.Keys(kit.MDB_HASH, arg[0], kit.MDB_META, kit.MDB_NAME), arg[2])
case "remove":
// 删除群组
m.Richs(ice.CHAT_RIVER, nil, arg[0], func(value map[string]interface{}) {
m.Log(ice.LOG_REMOVE, "river: %s value: %s", arg[0], kit.Format(value))
})
m.Conf(ice.CHAT_RIVER, kit.Keys(kit.MDB_HASH, arg[0]), "")
}
} }
}}, }},
"/storm": {Name: "/storm", Help: "暴风雨", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { "/storm": {Name: "/storm", Help: "暴风雨", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if m.Warn(m.Option(ice.MSG_RIVER) == "", "not join") {
web.Render(m, "status", 402, "not join")
return
}
prefix := kit.Keys(kit.MDB_HASH, arg[0], "tool") prefix := kit.Keys(kit.MDB_HASH, arg[0], "tool")
if len(arg) < 2 { if len(arg) < 3 {
// 应用列表 // 应用列表
m.Richs(ice.CHAT_RIVER, prefix, "*", func(key string, value map[string]interface{}) { m.Richs(ice.CHAT_RIVER, prefix, "*", func(key string, value map[string]interface{}) {
m.Push(key, value["meta"], []string{kit.MDB_KEY, kit.MDB_NAME}) m.Push(key, value["meta"], []string{kit.MDB_KEY, kit.MDB_NAME})
@ -310,18 +310,9 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心",
m.Sort(kit.MDB_NAME) m.Sort(kit.MDB_NAME)
return return
} }
if len(arg) == 2 {
// 应用详情
m.Richs(ice.CHAT_RIVER, prefix, arg[1], func(key string, value map[string]interface{}) {
m.Push(key, value["meta"], []string{kit.MDB_KEY, kit.MDB_NAME})
})
return
}
if !m.Right(cmd, arg[2]) { if !m.Right(cmd, arg[2]) {
// 没有权限 web.Render(m, "status", 403, "not auth")
m.Push("_output", "status")
m.Set("result").Echo("403")
return return
} }
@ -350,22 +341,29 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心",
} }
}}, }},
"/steam": {Name: "/steam", Help: "大气层", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { "/steam": {Name: "/steam", Help: "大气层", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if m.Warn(m.Option(ice.MSG_RIVER) == "", "not join") {
web.Render(m, "status", 402, "not join")
return
}
if len(arg) < 2 { if len(arg) < 2 {
if pod := m.Option("pod"); pod != "" { if list := []string{}; m.Option("pod") != "" {
// 远程命令 // 远程空间
m.Option("pod", "") m.Cmdy(ice.WEB_SPACE, m.Option("pod"), "web.chat./steam").Table(func(index int, value map[string]string, head []string) {
list := []string{} list = append(list, kit.Keys(m.Option("pod"), value["name"]))
m.Cmdy(ice.WEB_SPACE, pod, "web.chat./steam").Table(func(index int, value map[string]string, head []string) {
list = append(list, pod+"."+value["name"])
}) })
m.Append("name", list) m.Append("name", list)
return } else {
// 本地空间
m.Richs(ice.WEB_SPACE, nil, "*", func(key string, value map[string]interface{}) {
m.Push(key, value, []string{"type", "name", "user"})
})
} }
return
}
// 设备列表 if !m.Right(cmd, arg[1]) {
m.Richs(ice.WEB_SPACE, nil, "*", func(key string, value map[string]interface{}) { web.Render(m, "status", 403, "not auth")
m.Push(key, value, []string{"type", "name", "user"})
})
return return
} }
@ -376,12 +374,12 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心",
kit.MDB_META, kit.Dict(kit.MDB_NAME, arg[2]), kit.MDB_META, kit.Dict(kit.MDB_NAME, arg[2]),
)) ))
m.Log(ice.LOG_CREATE, "storm: %s name: %v", storm, arg[2]) m.Log(ice.LOG_CREATE, "storm: %s name: %v", storm, arg[2])
// 添加工具 // 添加命令
m.Cmd("/storm", arg[0], storm, "add", arg[3:]) m.Cmd("/storm", arg[0], storm, "add", arg[3:])
m.Echo(storm) m.Echo(storm)
case "append": case "append":
// 追加工具 // 追加命令
m.Cmd("/storm", arg[0], arg[2], "add", arg[3:]) m.Cmd("/storm", arg[0], arg[2], "add", arg[3:])
default: default:
@ -396,6 +394,11 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心",
"/target": {Name: "/target", Help: "对话框", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}}, "/target": {Name: "/target", Help: "对话框", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
"/source": {Name: "/source", Help: "输入框", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}}, "/source": {Name: "/source", Help: "输入框", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
"/action": {Name: "/action", Help: "工作台", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { "/action": {Name: "/action", Help: "工作台", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if m.Warn(m.Option(ice.MSG_RIVER) == "" || m.Option(ice.MSG_STORM) == "", "not join") {
web.Render(m, "status", 402, "not join")
return
}
prefix := kit.Keys(kit.MDB_HASH, arg[0], "tool", kit.MDB_HASH, arg[1]) prefix := kit.Keys(kit.MDB_HASH, arg[0], "tool", kit.MDB_HASH, arg[1])
if len(arg) == 2 { if len(arg) == 2 {
// 命令列表 // 命令列表
@ -439,8 +442,8 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心",
cmds := []string{} cmds := []string{}
m.Grows(ice.CHAT_RIVER, prefix, kit.MDB_ID, kit.Format(kit.Int(arg[2])+1), func(index int, value map[string]interface{}) { m.Grows(ice.CHAT_RIVER, prefix, kit.MDB_ID, kit.Format(kit.Int(arg[2])+1), func(index int, value map[string]interface{}) {
if meta, ok := kit.Value(value, "meta").(map[string]interface{}); ok { if meta, ok := kit.Value(value, "meta").(map[string]interface{}); ok {
// 命令补全
if len(arg) > 3 && arg[3] == "action" { if len(arg) > 3 && arg[3] == "action" {
// 命令补全
switch arg[4] { switch arg[4] {
case "input": case "input":
switch arg[5] { switch arg[5] {
@ -453,21 +456,16 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心",
case "favor": case "favor":
m.Cmdy(ice.WEB_FAVOR, arg[5:]) m.Cmdy(ice.WEB_FAVOR, arg[5:])
return return
case "location": case "location":
// 记录位置 // 记录位置
m.Cmdy("aaa.location", arg[5:]) m.Cmdy("aaa.location", arg[5:])
return return
case "upload": case "upload":
m.Cmdy(ice.WEB_STORY, "upload") m.Cmdy(ice.WEB_STORY, "upload")
return return
case "story":
// cmds := kit.Split(arg[7])
// if m.Right(cmds, arg[8:]) {
// m.Cmdy(cmds, arg[8:])
// }
// return
case "share": case "share":
list := []string{} list := []string{}
for k, v := range meta { for k, v := range meta {
@ -485,16 +483,12 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心",
}) })
if len(cmds) == 0 { if len(cmds) == 0 {
// 没有命令 web.Render(m, "status", 404, "not found")
m.Push("_output", "status")
m.Set("result").Echo("404")
return return
} }
if !m.Right(cmds) { if !m.Right(cmds) {
// 没有权限 web.Render(m, "status", 403, "not auth")
m.Push("_output", "status")
m.Set("result").Echo("403")
return return
} }
@ -508,7 +502,6 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心",
// 执行命令 // 执行命令
m.Cmdy(proxy, cmds).Option("cmds", cmds) m.Cmdy(proxy, cmds).Option("cmds", cmds)
// m.Cmd(ice.WEB_FAVOR, "cmd.history", "cmd", m.Option(ice.MSG_SESSID)[:6], strings.Join(cmds, " "))
}}, }},
}, },
} }

2
go.sum
View File

@ -4,6 +4,8 @@ github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvK
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/shylinux/toolkits v0.1.2 h1:yP24DXfcU5c7u3NVAxCGiMy5UMBRQH4gkKUZXOIN5fk= github.com/shylinux/toolkits v0.1.2 h1:yP24DXfcU5c7u3NVAxCGiMy5UMBRQH4gkKUZXOIN5fk=
github.com/shylinux/toolkits v0.1.2/go.mod h1:Y68Ot6xOmo1bun67YvqC3chDGeU2gDxtsUnvVDGJm4g= github.com/shylinux/toolkits v0.1.2/go.mod h1:Y68Ot6xOmo1bun67YvqC3chDGeU2gDxtsUnvVDGJm4g=
github.com/shylinux/toolkits v0.1.3 h1:bqxmbPFBKkOpv9uEb4bbeeovowsiBK7zDrPrQMUDlSc=
github.com/shylinux/toolkits v0.1.3/go.mod h1:Y68Ot6xOmo1bun67YvqC3chDGeU2gDxtsUnvVDGJm4g=
github.com/skip2/go-qrcode v0.0.0-20191027152451-9434209cb086 h1:RYiqpb2ii2Z6J4x0wxK46kvPBbFuZcdhS+CIztmYgZs= github.com/skip2/go-qrcode v0.0.0-20191027152451-9434209cb086 h1:RYiqpb2ii2Z6J4x0wxK46kvPBbFuZcdhS+CIztmYgZs=
github.com/skip2/go-qrcode v0.0.0-20191027152451-9434209cb086/go.mod h1:PLPIyL7ikehBD1OAjmKKiOEhbvWyHGaNDjquXMcYABo= github.com/skip2/go-qrcode v0.0.0-20191027152451-9434209cb086/go.mod h1:PLPIyL7ikehBD1OAjmKKiOEhbvWyHGaNDjquXMcYABo=
golang.org/dl v0.0.0-20190829154251-82a15e2f2ead/go.mod h1:IUMfjQLJQd4UTqG1Z90tenwKoCX93Gn3MAQJMOSBsDQ= golang.org/dl v0.0.0-20190829154251-82a15e2f2ead/go.mod h1:IUMfjQLJQd4UTqG1Z90tenwKoCX93Gn3MAQJMOSBsDQ=

View File

@ -276,7 +276,7 @@ var Index = &ice.Context{Name: "lark", Help: "机器人",
switch parse(m); m.Option("msg.type") { switch parse(m); m.Option("msg.type") {
case "url_verification": case "url_verification":
// 绑定验证 // 绑定验证
m.Push("_output", "result") m.Append("_output", "result")
m.Echo(kit.Format(map[string]interface{}{"challenge": m.Option("msg.challenge")})) m.Echo(kit.Format(map[string]interface{}{"challenge": m.Option("msg.challenge")}))
case "event_callback": case "event_callback":

View File

@ -55,11 +55,11 @@ var Index = &ice.Context{Name: "mp", Help: "小程序",
}) })
case "scan": case "scan":
m.Echo(m.Option("scan")).Push("_output", "qrcode") web.Render(m, "qrcode", m.Option("scan"))
case "auth": case "auth":
if !m.Options(ice.MSG_USERNAME) || !m.Options(ice.MSG_SESSID) { if !m.Options(ice.MSG_USERNAME) || !m.Options(ice.MSG_SESSID) {
m.Echo("401").Push("_output", "status") web.Render(m, "status", 401, "not login")
break break
} }
switch kit.Select("active", m.Option("type")) { switch kit.Select("active", m.Option("type")) {

View File

@ -346,7 +346,7 @@ var Index = &ice.Context{Name: "tmux", Help: "工作台",
switch arg = kit.Split(kit.Select("tmux.auto", arg, 0)); arg[0] { switch arg = kit.Split(kit.Select("tmux.auto", arg, 0)); arg[0] {
default: default:
m.Append("_output", "void") m.Append("_output", "result")
m.Cmd("auto", current, arg) m.Cmd("auto", current, arg)
} }
}}, }},

View File

@ -32,11 +32,11 @@ func parse(m *ice.Message) {
} }
func reply(m *ice.Message) { func reply(m *ice.Message) {
m.Push("_output", "result") m.Append("_output", "result")
m.Render(m.Conf("login", "meta.template.text")) m.Render(m.Conf("login", "meta.template.text"))
} }
func action(m *ice.Message) { func action(m *ice.Message) {
m.Push("_output", "result") m.Append("_output", "result")
m.Echo(`<xml> m.Echo(`<xml>
<ToUserName><![CDATA[%s]]></ToUserName> <ToUserName><![CDATA[%s]]></ToUserName>
@ -115,8 +115,7 @@ var Index = &ice.Context{Name: "wx", Help: "公众号",
if m.Option("echostr") != "" { if m.Option("echostr") != "" {
// 绑定验证 // 绑定验证
m.Push("_output", "result") web.Render(m, m.Option("echostr"))
m.Echo(m.Option("echostr"))
return return
} }

View File

@ -196,7 +196,7 @@ var Index = &ice.Context{Name: "zsh", Help: "命令行",
} }
// 下载文件 // 下载文件
m.Append("_output", kit.Select("file", "result", m.Append("file") == "")) web.Render(m, "download", kit.Select("file", "result", m.Append("file") == ""))
}}, }},
"/upload": {Name: "/upload", Help: "上传", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { "/upload": {Name: "/upload", Help: "上传", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
// 缓存文件 // 缓存文件

52
type.go
View File

@ -9,6 +9,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"math/rand" "math/rand"
"net/http" "net/http"
"os" "os"
@ -1161,8 +1162,25 @@ func (m *Message) Richs(key string, chain interface{}, raw interface{}, cb inter
switch kit.Format(kit.Value(meta, kit.MDB_SHORT)) { switch kit.Format(kit.Value(meta, kit.MDB_SHORT)) {
case "", "uniq": case "", "uniq":
default: default:
h = kit.Hashs(h) hh := kit.Hashs(h)
res, ok = hash[h].(map[string]interface{}) if res, ok = hash[hh].(map[string]interface{}); ok {
h = hh
break
}
prefix := path.Join(kit.Select(m.Conf(WEB_CACHE, "meta.store"), kit.Format(meta["store"])), key)
for _, k := range []string{h, hh} {
if f, e := os.Open(path.Join(prefix, kit.Keys(k, "json"))); e == nil {
defer f.Close()
if b, e := ioutil.ReadAll(f); e == nil {
if json.Unmarshal(b, &res) == e {
h = k
m.Log(LOG_IMPORT, "%s/%s.json", prefix, k)
break
}
}
}
}
} }
} }
} }
@ -1220,7 +1238,35 @@ func (m *Message) Rich(key string, chain interface{}, data interface{}) string {
} }
// 添加数据 // 添加数据
hash[h] = data if hash[h] = data; len(hash) >= kit.Int(kit.Select(m.Conf(WEB_CACHE, "meta.limit"), kit.Format(meta["limit"]))) {
least := kit.Int(kit.Select(m.Conf(WEB_CACHE, "meta.least"), kit.Format(meta["least"])))
// 时间淘汰
list := []int{}
for _, v := range hash {
list = append(list, kit.Time(kit.Format(kit.Value(v, "time"))))
}
sort.Ints(list)
dead := list[len(list)-1-least]
prefix := path.Join(kit.Select(m.Conf(WEB_CACHE, "meta.store"), kit.Format(meta["store"])), key)
for k, v := range hash {
if kit.Time(kit.Format(kit.Value(v, "time"))) > dead {
break
}
name := path.Join(prefix, kit.Keys(k, "json"))
if f, p, e := kit.Create(name); m.Assert(e) {
defer f.Close()
// 保存数据
if n, e := f.WriteString(kit.Format(v)); m.Assert(e) {
m.Log(LOG_EXPORT, "%s: %d", p, n)
delete(hash, k)
}
}
}
}
return h return h
} }
func (m *Message) Grow(key string, chain interface{}, data interface{}) int { func (m *Message) Grow(key string, chain interface{}, data interface{}) int {