1
0
mirror of https://shylinux.com/x/icebergs synced 2025-05-01 03:09:21 +08:00
This commit is contained in:
shaoying 2021-01-07 21:17:04 +08:00
parent 9febae9beb
commit f550be9b6c
29 changed files with 492 additions and 405 deletions

View File

@ -98,6 +98,9 @@ const (
USER_CREATE = "user.create"
)
const (
INVITE = "invite"
)
const USER = "user"

View File

@ -31,6 +31,8 @@ var Index = &ice.Context{Name: "cli", Help: "命令模块",
m.Conf(RUNTIME, "conf.ctx_shy", os.Getenv("ctx_shy"))
m.Conf(RUNTIME, "conf.ctx_pid", os.Getenv("ctx_pid"))
m.Conf(RUNTIME, "conf.ctx_user", os.Getenv("ctx_user"))
m.Conf(RUNTIME, "conf.ctx_share", os.Getenv("ctx_share"))
m.Conf(RUNTIME, "conf.ctx_river", os.Getenv("ctx_river"))
// 主机信息
m.Conf(RUNTIME, "host.GOARCH", runtime.GOARCH)
@ -58,6 +60,9 @@ var Index = &ice.Context{Name: "cli", Help: "命令模块",
ice.Info.PathName = m.Conf(RUNTIME, "boot.pathname")
ice.Info.UserName = m.Conf(RUNTIME, "boot.username")
ice.Info.CtxShare = m.Conf(RUNTIME, "conf.ctx_share")
ice.Info.CtxRiver = m.Conf(RUNTIME, "conf.ctx_river")
// 启动记录
count := kit.Int(m.Conf(RUNTIME, "boot.count")) + 1
m.Conf(RUNTIME, "boot.count", count)

View File

@ -410,7 +410,6 @@ const (
IMPORT = "import"
PRUNES = "prunes"
INPUTS = "inputs"
INVITE = "invite"
COMMIT = "commit"
SOURCE = "source"
)

View File

@ -288,7 +288,7 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool {
case STDIO: // 终端交互
r, f.stdout = os.Stdin, os.Stdout
m.Option(ice.MSG_USEROPT, ice.MSG_USERNAME)
m.Option(ice.MSG_OPTS, ice.MSG_USERNAME)
m.Option(ice.MSG_USERNAME, ice.Info.UserName)
m.Option(ice.MSG_USERROLE, aaa.ROOT)
m.Option(ice.MSG_USERZONE, "boot")

View File

@ -29,7 +29,7 @@ func _ssh_meta(conn ssh.ConnMetadata) map[string]string {
func _ssh_config(m *ice.Message, h string) *ssh.ServerConfig {
config := &ssh.ServerConfig{
PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
meta, err := _ssh_meta(conn), errors.New(ice.ErrNotAuth)
meta, err := _ssh_meta(conn), errors.New(ice.ErrNotRight)
if tcp.IsLocalHost(m, strings.Split(conn.RemoteAddr().String(), ":")[0]) {
m.Log_AUTH(tcp.HOSTPORT, conn.RemoteAddr(), aaa.USERNAME, conn.User())
err = nil // 本机用户
@ -53,7 +53,7 @@ func _ssh_config(m *ice.Message, h string) *ssh.ServerConfig {
return &ssh.Permissions{Extensions: meta}, err
},
PasswordCallback: func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
meta, err := _ssh_meta(conn), errors.New(ice.ErrNotAuth)
meta, err := _ssh_meta(conn), errors.New(ice.ErrNotRight)
m.Richs(aaa.USER, "", conn.User(), func(k string, value map[string]interface{}) {
if string(password) == kit.Format(value[aaa.PASSWORD]) {
m.Log_AUTH(tcp.HOSTPORT, conn.RemoteAddr(), aaa.USERNAME, conn.User(), aaa.PASSWORD, strings.Repeat("*", len(kit.Format(value[aaa.PASSWORD]))))
@ -203,7 +203,7 @@ func init() {
mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.PRUNES, SERVICE, "", mdb.HASH, kit.MDB_STATUS, tcp.CLOSE)
}},
mdb.INVITE: {Name: "invite", Help: "邀请", Hand: func(m *ice.Message, arg ...string) {
aaa.INVITE: {Name: "invite", Help: "邀请", Hand: func(m *ice.Message, arg ...string) {
u := kit.ParseURL(m.Option(ice.MSG_USERWEB))
m.Option("hostname", strings.Split(u.Host, ":")[0])
@ -218,7 +218,7 @@ ssh {{.Option "user.name"}}@{{.Option "hostname"}} -p {{.Option "port"}}
if len(arg) == 0 {
m.Option(mdb.FIELDS, "time,status,port,private,auth,count")
m.Cmdy(mdb.SELECT, SERVICE, "", mdb.HASH)
m.PushAction(mdb.IMPORT, mdb.INSERT, mdb.EXPORT, mdb.INVITE)
m.PushAction(mdb.IMPORT, mdb.INSERT, mdb.EXPORT, aaa.INVITE)
return
}

View File

@ -38,6 +38,8 @@ func (c *Conn) Close() error {
}
const (
SOCKET = "socket"
OPEN = "open"
START = "start"
ERROR = "error"

View File

@ -63,6 +63,7 @@ func IsLocalHost(m *ice.Message, ip string) bool { return _islocalhost(m, ip) }
const (
HOSTPORT = "hostport"
HOSTNAME = "hostname"
PROTOCOL = "protocol"
LOCALHOST = "localhost"
)

View File

@ -62,6 +62,7 @@ func _cache_catch(m *ice.Message, name string) (file, size string) {
}
return "", "0"
}
func _cache_upload(m *ice.Message, r *http.Request) (kind, name, file, size string) {
if buf, h, e := r.FormFile(UPLOAD); e == nil {
defer buf.Close()
@ -83,36 +84,41 @@ func _cache_upload(m *ice.Message, r *http.Request) (kind, name, file, size stri
func _cache_download(m *ice.Message, r *http.Response) (file, size string) {
defer r.Body.Close()
total := kit.Int(kit.Select("1", r.Header.Get(ContentLength)))
if f, p, e := kit.Create(path.Join("var/tmp", kit.Hashs("uniq"))); m.Assert(e) {
size, buf := 0, make([]byte, 1024)
step, total := 0, kit.Int(kit.Select("1", r.Header.Get(ContentLength)))
size, buf := 0, make([]byte, ice.MOD_BUFS)
for {
if n, _ := r.Body.Read(buf); n > 0 {
size += n
f.Write(buf[0:n])
switch size += n; cb := m.Optionv(DOWNLOAD_CB).(type) {
case []string:
m.Richs(cb[0], cb[1], cb[2], func(key string, value map[string]interface{}) {
value = value[kit.MDB_META].(map[string]interface{})
s := size * 100 / total
s := size * 100 / total
if s != kit.Int(value[kit.SSH_STEP]) && s%10 == 0 {
m.Log_IMPORT(kit.MDB_FILE, path.Base(cb[2]), kit.SSH_STEP, s, kit.MDB_SIZE, kit.FmtSize(int64(size)), kit.MDB_TOTAL, kit.FmtSize(int64(total)))
}
value[kit.SSH_STEP], value[kit.MDB_SIZE], value[kit.MDB_TOTAL] = kit.Format(s), size, total
})
switch cb := m.Optionv(DOWNLOAD_CB).(type) {
case func(int, int):
cb(size, total)
case []string:
m.Richs(cb[0], cb[1], cb[2], func(key string, value map[string]interface{}) {
value = kit.GetMeta(value)
value[kit.SSH_STEP], value[kit.MDB_SIZE], value[kit.MDB_TOTAL] = kit.Format(s), size, total
})
default:
m.Log_IMPORT(kit.MDB_FILE, p, "per", size*100/total, kit.MDB_SIZE, kit.FmtSize(int64(size)), "total", kit.FmtSize(int64(total)))
if s != step && s%10 == 0 {
m.Log_IMPORT(kit.MDB_FILE, p, kit.SSH_STEP, s,
kit.MDB_SIZE, kit.FmtSize(int64(size)), kit.MDB_TOTAL, kit.FmtSize(int64(total)))
}
}
} else {
f.Close()
break
step = s
continue
}
f.Close()
break
}
if f, e := os.Open(p); m.Assert(e) {
defer f.Close()
m.Log_IMPORT(kit.MDB_FILE, p, kit.MDB_SIZE, kit.FmtSize(int64(size)))
c := _cache_name(m, kit.Hashs(f))
m.Cmd(nfs.LINK, c, p)
@ -147,13 +153,13 @@ func init() {
WATCH: {Name: "watch key file", Help: "释放", Hand: func(m *ice.Message, arg ...string) {
_cache_watch(m, arg[0], arg[1])
}},
WRITE: {Name: "write type name text", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
_cache_save(m, arg[0], arg[1], arg[2])
}},
CATCH: {Name: "catch type name", Help: "捕获", Hand: func(m *ice.Message, arg ...string) {
file, size := _cache_catch(m, arg[1])
_cache_save(m, arg[0], arg[1], "", file, size)
}},
WRITE: {Name: "write type name text", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
_cache_save(m, arg[0], arg[1], arg[2])
}},
UPLOAD: {Name: "upload", Help: "上传", Hand: func(m *ice.Message, arg ...string) {
kind, name, file, size := _cache_upload(m, m.R)
_cache_save(m, kind, name, "", file, size)
@ -165,8 +171,16 @@ func init() {
}
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Option(mdb.FIELDS, kit.Select("time,hash,size,type,name,text,file", mdb.DETAIL, len(arg) > 0))
m.Option(mdb.FIELDS, kit.Select("time,hash,size,type,name,text", mdb.DETAIL, len(arg) > 0))
m.Cmdy(mdb.SELECT, CACHE, "", mdb.HASH, kit.MDB_HASH, arg)
if len(arg) > 0 {
if m.Append(kit.MDB_FILE) == "" {
m.Push(kit.MDB_LINK, m.Append(kit.MDB_TEXT))
} else {
m.PushAnchor(DOWNLOAD, kit.MergeURL2(m.Option(ice.MSG_USERWEB), "/share/cache/"+arg[0]))
}
}
}},
"/cache/": {Name: "/cache/", Help: "缓存池", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {

View File

@ -16,55 +16,44 @@ import (
)
func _dream_list(m *ice.Message) {
m.Cmdy(nfs.DIR, m.Conf(DREAM, kit.META_PATH), "time size name").Table(func(index int, value map[string]string, head []string) {
m.Cmdy(nfs.DIR, m.Conf(DREAM, kit.META_PATH), "time,size,name").Table(func(index int, value map[string]string, head []string) {
if m.Richs(SPACE, nil, value[kit.MDB_NAME], func(key string, value map[string]interface{}) {
m.Push(kit.MDB_TYPE, value[kit.MDB_TYPE])
m.Push(kit.MDB_STATUS, gdb.START)
m.PushButton(gdb.STOP)
m.Push(kit.MDB_STATUS, tcp.START)
m.PushButton(tcp.STOP)
}) == nil {
m.Push(kit.MDB_TYPE, WORKER)
m.Push(kit.MDB_STATUS, gdb.STOP)
m.PushButton(gdb.START)
m.Push(kit.MDB_STATUS, tcp.STOP)
m.PushButton(tcp.START)
}
})
m.Sort(kit.MDB_NAME, "str_r")
m.SortStrR(kit.MDB_NAME)
}
func _dream_show(m *ice.Message, name string) {
// 规范命名
if !strings.Contains(name, "-") || !strings.HasPrefix(name, "20") {
name = m.Time("20060102-") + strings.ReplaceAll(name, "-", "_")
}
// 创建目录
// 任务目录
p := path.Join(m.Conf(DREAM, kit.META_PATH), name)
os.MkdirAll(p, ice.MOD_DIR)
// 下载代码
if m.Option(kit.SSH_REPOS) != "" {
if m.Option(kit.SSH_REPOS) != "" { // 下载源码
m.Cmd("web.code.git.repos", mdb.CREATE, kit.SSH_REPOS, m.Option(kit.SSH_REPOS), kit.MDB_PATH, p)
} else { // 创建目录
os.MkdirAll(p, ice.MOD_DIR)
}
// 任务模板
if m.Option("template") != "" {
for _, file := range []string{"etc/miss.sh", "go.mod", "src/main.go", "src/main.shy"} {
for _, file := range []string{"etc/miss.sh", "src/main.shy", "src/main.go", "go.mod"} {
if _, e := os.Stat(path.Join(p, file)); os.IsNotExist(e) {
m.Cmdy(nfs.COPY, path.Join(p, file), path.Join(m.Option("template"), file))
switch file {
switch m.Cmdy(nfs.COPY, path.Join(p, file), path.Join(m.Option("template"), file)); file {
case "go.mod":
kit.Rewrite(path.Join(p, file), func(line string) string {
if strings.HasPrefix(line, "module") {
m.Info("module %s", name)
return "module " + name
}
return line
return kit.Select(line, "module "+name, strings.HasPrefix(line, "module"))
})
}
}
}
go func() {
m.Option(cli.CMD_DIR, p)
m.Cmd(cli.SYSTEM, "bash", "-c", "source etc/miss.sh")
}()
}
// 任务脚本
@ -89,9 +78,9 @@ func _dream_show(m *ice.Message, name string) {
))
// 启动任务
m.Optionv(cli.CMD_STDERR, path.Join(p, m.Conf(DREAM, "meta.env.ctx_log")))
m.Cmd(cli.DAEMON, m.Confv(DREAM, "meta.cmd"), "dev", "self", "name", name)
m.Cmd(cli.DAEMON, m.Confv(DREAM, "meta.cmd"), SPIDE_DEV, SPIDE_SELF, kit.MDB_NAME, name)
m.Event(DREAM_CREATE, kit.MDB_TYPE, m.Option(kit.MDB_TYPE), kit.MDB_NAME, name)
m.Sleep("1s")
m.Sleep(ice.MOD_TICK)
}
m.Cmdy(nfs.DIR, p)
}
@ -105,18 +94,56 @@ const DREAM = "dream"
func init() {
Index.Merge(&ice.Context{
Commands: map[string]*ice.Command{
DREAM: {Name: "dream name path auto start create", Help: "梦想家", Action: map[string]*ice.Action{
mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
switch arg[0] {
case kit.MDB_NAME:
m.Cmdy(nfs.DIR, m.Conf(DREAM, kit.META_PATH), "name,time")
}
}},
mdb.CREATE: {Name: "create main=src/main.go@key name=hi@key from=usr/icebergs/misc/bash/bash.go@key", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(SPACE, m.Option(ROUTE), "web.code.autogen", mdb.CREATE, arg)
m.Option(ice.MSG_PROCESS, ice.PROCESS_INNER)
}},
tcp.START: {Name: "start name repos", Help: "启动", Hand: func(m *ice.Message, arg ...string) {
if m.Option(kit.MDB_NAME) == SPIDE_SELF {
m.Option(kit.MDB_NAME, "")
}
_dream_show(m, m.Option(kit.MDB_NAME, kit.Select(path.Base(m.Option(kit.SSH_REPOS)), m.Option(kit.MDB_NAME))))
}},
tcp.STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(SPACE, m.Option(kit.MDB_NAME), "exit", "0")
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) == 0 {
_dream_list(m)
return
}
m.Option(nfs.DIR_ROOT, path.Join(m.Conf(DREAM, kit.META_PATH), arg[0]))
if len(arg) == 1 || strings.HasSuffix(arg[1], "/") {
m.Cmdy(nfs.DIR, arg[1:])
} else {
m.Cmdy(nfs.CAT, arg[1:])
}
}},
},
Configs: map[string]*ice.Config{
DREAM: {Name: DREAM, Help: "梦想家", Value: kit.Data(kit.MDB_PATH, "usr/local/work",
"cmd", []interface{}{"ice.bin", SPACE, tcp.DIAL},
"env", kit.Dict("ctx_log", "bin/boot.log"),
"miss", `#!/bin/bash
[ -f ~/.ish/plug.sh ] || [ -f ./.ish/plug.sh ] || git clone ${ISH_CONF_HUB_PROXY:="https://"}github.com/shylinux/intshell ./.ish
[ "$ISH_CONF_PRE" != "" ] || source ./.ish/plug.sh || source ~/.ish/plug.sh
[ -f ~/.ish/plug.sh ] || [ -f $PWD/.ish/plug.sh ] || git clone ${ISH_CONF_HUB_PROXY:="https://"}github.com/shylinux/intshell $PWD/.ish
[ "$ISH_CONF_PRE" != "" ] || source $PWD/.ish/plug.sh || source ~/.ish/plug.sh
require miss.sh
ish_miss_prepare_develop
ish_miss_prepare_compile
ish_miss_prepare_install
# ish_miss_prepare_intshell
# ish_miss_prepare_contexts
# ish_miss_prepare_icebergs
# ish_miss_prepare_toolkits
@ -124,31 +151,5 @@ make
`,
)},
},
Commands: map[string]*ice.Command{
DREAM: {Name: "dream name path auto 启动", Help: "梦想家", Action: map[string]*ice.Action{
gdb.START: {Name: "start name repos", Help: "启动", Hand: func(m *ice.Message, arg ...string) {
if m.Option(kit.MDB_NAME) == "self" {
m.Option(kit.MDB_NAME, "")
}
_dream_show(m, m.Option(kit.MDB_NAME, kit.Select(path.Base(m.Option(kit.SSH_REPOS)), m.Option(kit.MDB_NAME))))
}},
gdb.STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(SPACE, m.Option(kit.MDB_NAME), "exit", "0")
}},
mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
switch arg[0] {
case kit.MDB_NAME:
m.Cmdy(nfs.DIR, m.Conf(DREAM, kit.META_PATH), "name,time")
}
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) == 0 {
_dream_list(m)
return
}
m.Option(nfs.DIR_ROOT, path.Join(m.Conf(DREAM, kit.META_PATH), arg[0]))
m.Cmdy(nfs.DIR, arg[1:])
}},
},
})
}

View File

@ -2,43 +2,66 @@ package web
import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/aaa"
"github.com/shylinux/icebergs/base/ctx"
"github.com/shylinux/icebergs/base/gdb"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/nfs"
"github.com/shylinux/icebergs/base/tcp"
kit "github.com/shylinux/toolkits"
"strings"
)
func _route_travel(m *ice.Message, route string) {
if route == "" {
m.Richs(SPACE, nil, kit.MDB_FOREACH, func(key string, val map[string]interface{}) {
switch val[kit.MDB_TYPE] {
case SERVER:
if val[kit.MDB_NAME] == ice.Info.NodeName {
return // 避免循环
}
// 远程查询
m.Cmd(SPACE, val[kit.MDB_NAME], ROUTE).Table(func(index int, value map[string]string, head []string) {
m.Push(kit.MDB_TYPE, value[kit.MDB_TYPE])
m.Push(kit.SSH_ROUTE, kit.Keys(val[kit.MDB_NAME], value[kit.SSH_ROUTE]))
})
fallthrough
case WORKER:
// 本机查询
m.Push(kit.MDB_TYPE, val[kit.MDB_TYPE])
m.Push(kit.SSH_ROUTE, val[kit.MDB_NAME])
m.Richs(SPACE, nil, kit.MDB_FOREACH, func(key string, val map[string]interface{}) {
switch val[kit.MDB_TYPE] {
case SERVER: // 远程查询
if val[kit.MDB_NAME] == ice.Info.NodeName {
return // 避免循环
}
})
} else {
m.Cmd(SPACE, route, ROUTE).Table(func(index int, value map[string]string, head []string) {
m.Push(kit.MDB_TYPE, value[kit.MDB_TYPE])
m.Push(kit.SSH_ROUTE, kit.Keys(route, value[kit.SSH_ROUTE]))
})
}
m.Cmd(SPACE, val[kit.MDB_NAME], ROUTE).Table(func(index int, value map[string]string, head []string) {
m.Push(kit.MDB_TYPE, value[kit.MDB_TYPE])
m.Push(kit.SSH_ROUTE, kit.Keys(val[kit.MDB_NAME], value[kit.SSH_ROUTE]))
})
fallthrough
case WORKER: // 本机查询
m.Push(kit.MDB_TYPE, val[kit.MDB_TYPE])
m.Push(kit.SSH_ROUTE, val[kit.MDB_NAME])
}
})
}
func _route_list(m *ice.Message) {
// 链接操作
m.Table(func(index int, value map[string]string, field []string) {
m.PushAnchor(value[kit.SSH_ROUTE], kit.MergeURL(m.Option(ice.MSG_USERWEB),
kit.SSH_POD, kit.Keys(m.Option(ice.MSG_USERPOD), value[kit.SSH_ROUTE])))
switch value[kit.MDB_TYPE] {
case WORKER:
m.PushButton(mdb.CREATE)
case SERVER:
m.PushButton(tcp.START)
default:
m.PushButton("")
}
})
// 网卡信息
u := kit.ParseURL(m.Option(ice.MSG_USERWEB))
m.Cmd(tcp.HOST).Table(func(index int, value map[string]string, head []string) {
m.Push(kit.MDB_TYPE, MYSELF)
m.Push(kit.SSH_ROUTE, ice.Info.NodeName)
m.PushAnchor(value["ip"], kit.Format("%s://%s:%s", u.Scheme, value["ip"], u.Port()))
m.PushButton(tcp.START)
})
// 本机信息
m.Push(kit.MDB_TYPE, MYSELF)
m.Push(kit.SSH_ROUTE, ice.Info.NodeName)
m.PushAnchor("localhost", kit.Format("%s://%s:%s", u.Scheme, "localhost", u.Port()))
m.PushButton(tcp.START)
m.Sort(kit.SSH_ROUTE)
}
const ROUTE = "route"
@ -49,111 +72,71 @@ func init() {
ROUTE: {Name: ROUTE, Help: "路由器", Value: kit.Data(kit.MDB_SHORT, kit.SSH_ROUTE)},
},
Commands: map[string]*ice.Command{
ROUTE: {Name: "route route ctx cmd auto invite share", Help: "路由", Action: map[string]*ice.Action{
ROUTE: {Name: "route route ctx cmd auto invite share", Help: "路由", Action: map[string]*ice.Action{
SHARE: {Name: "share", Help: "共享", Hand: func(m *ice.Message, arg ...string) {
h := m.Cmdx(SHARE, mdb.CREATE, kit.MDB_TYPE, "login")
p := kit.MergeURL(m.Option(ice.MSG_USERWEB), SHARE, h)
m.Cmdy("web.wiki.spark", "shell", p).Render("")
m.Cmdy("web.wiki.image", "qrcode", p)
p := kit.MergeURL(m.Option(ice.MSG_USERWEB), SHARE, m.Cmdx(SHARE, mdb.CREATE, kit.MDB_TYPE, LOGIN))
m.EchoScript(p)
m.EchoQRCode(p)
m.EchoAnchor(p)
}},
mdb.INVITE: {Name: "invite", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
aaa.INVITE: {Name: "invite", Help: "脚本", Hand: func(m *ice.Message, arg ...string) {
for _, k := range []string{"tmux", "base", "miss"} {
m.Cmdy("web.code.publish", "contexts", k)
m.Cmdy("web.wiki.spark")
m.EchoScript("break")
}
m.Cmdy("web.wiki.spark", "shell", strings.Join([]string{"# 共享环境", m.Option(ice.MSG_USERWEB)}, "\n"))
m.Cmdy("web.wiki.image", "qrcode", m.Option(ice.MSG_USERWEB))
m.EchoScript("shell", "# 共享环境", m.Option(ice.MSG_USERWEB))
m.EchoQRCode(m.Option(ice.MSG_USERWEB))
m.EchoAnchor(m.Option(ice.MSG_USERWEB))
}},
mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
switch m.Option("action") {
case "autogen":
m.Cmdy(SPACE, m.Option(ROUTE), "web.code.autogen", "inputs", arg)
switch m.Option(kit.MDB_ACTION) {
case mdb.CREATE:
m.Cmdy(SPACE, m.Option(ROUTE), "web.code.autogen", mdb.INPUTS, arg)
return
}
switch arg[0] {
case "name":
case kit.MDB_NAME:
m.Cmdy(nfs.DIR, m.Conf(DREAM, kit.META_PATH), "name,size,time")
m.SortStrR(kit.MDB_PATH)
case "template":
case kit.SSH_TEMPLATE:
m.Cmdy(nfs.DIR, m.Conf(DREAM, kit.META_PATH), "path,size,time")
m.SortStrR(kit.MDB_PATH)
}
}},
gdb.START: {Name: "start name repos template", Help: "启动", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(SPACE, m.Option(ROUTE), DREAM, gdb.START, arg)
mdb.CREATE: {Name: "create main=src/main.go@key name=hi@key from=usr/icebergs/misc/bash/bash.go@key", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(SPACE, m.Option(ROUTE), "web.code.autogen", mdb.CREATE, arg)
m.Option(ice.MSG_PROCESS, ice.PROCESS_INNER)
}},
gdb.STOP: {Name: "stop", Help: "结束", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(SPACE, m.Option(ROUTE), "exit")
m.Sleep("3s")
}},
"autogen": {Name: "autogen main=src/main.go@key name=hi@key from=usr/icebergs/misc/bash/bash.go@key", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(SPACE, m.Option(ROUTE), "web.code.autogen", "create", arg)
tcp.START: {Name: "start name repos template", Help: "启动", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(SPACE, m.Option(ROUTE), DREAM, tcp.START, arg)
m.Option(ice.MSG_PROCESS, ice.PROCESS_INNER)
}},
ctx.COMMAND: {Name: "command", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(SPACE, m.Option(ROUTE), kit.Keys(m.Option(kit.SSH_CTX), m.Option(kit.SSH_CMD)), arg)
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) == 0 || arg[0] == "" {
if _route_travel(m, kit.Select("", arg, 0)); m.W == nil {
return
if len(arg) == 0 || arg[0] == "" { // 路由列表
if _route_travel(m, kit.Select("", arg, 0)); m.W != nil {
_route_list(m)
}
m.Table(func(index int, value map[string]string, field []string) {
if value[kit.MDB_TYPE] != MYSELF {
m.PushRender(kit.MDB_LINK, "a", value[kit.SSH_ROUTE],
kit.MergeURL(m.Option(ice.MSG_USERWEB), kit.SSH_POD, kit.Keys(m.Option(kit.SSH_POD, value[kit.SSH_ROUTE]))))
}
switch value[kit.MDB_TYPE] {
case SERVER:
m.PushButton(gdb.START)
case WORKER:
m.PushButton("autogen")
default:
m.PushButton("")
}
})
m.Cmd(tcp.HOST).Table(func(index int, value map[string]string, head []string) {
m.Push(kit.MDB_TYPE, MYSELF)
m.Push(kit.SSH_ROUTE, ice.Info.NodeName)
u := kit.ParseURL(m.Option(ice.MSG_USERWEB))
m.PushRender(kit.MDB_LINK, "a", value["ip"], kit.Format("%s://%s:%s", u.Scheme, value["ip"], u.Port()))
m.PushButton(gdb.START)
})
m.Push(kit.MDB_TYPE, MYSELF)
m.Push(kit.SSH_ROUTE, ice.Info.NodeName)
u := kit.ParseURL(m.Option(ice.MSG_USERWEB))
m.PushRender(kit.MDB_LINK, "a", "localhost", kit.Format("%s://%s:%s", u.Scheme, "localhost", u.Port()))
m.PushButton(gdb.START)
m.Sort(kit.SSH_ROUTE)
return // 设备列表
}
if len(arg) > 3 { // 执行命令
m.Cmdy(SPACE, arg[0], kit.Keys(arg[1], arg[2]), arg[4:])
} else if len(arg) > 2 { // 加载插件
m.Cmdy(SPACE, arg[0], ctx.CONTEXT, arg[1], ctx.COMMAND, arg[2])
m.Option("_prefix", arg[0], arg[1], arg[2], "run")
m.Option(ice.MSG_PROCESS, ice.PROCESS_FIELD)
m.PushPlugins(arg[0], arg[1], arg[2], ctx.COMMAND)
} else if len(arg) > 1 { // 命令列表
m.Cmd(SPACE, arg[0], ctx.CONTEXT, arg[1], ctx.COMMAND).Table(func(index int, value map[string]string, head []string) {
m.Push("cmd", value["key"])
m.Push("name", value["name"])
m.Push("help", value["help"])
m.Push(kit.SSH_CMD, value[kit.MDB_KEY])
m.Push("", value, []string{kit.MDB_NAME, kit.MDB_HELP})
})
} else if len(arg) > 0 { // 模块列表
m.Cmd(SPACE, arg[0], ctx.CONTEXT).Table(func(index int, value map[string]string, head []string) {
m.Push("ctx", kit.Keys(value["ups"], value["name"]))
m.Push("status", value["status"])
m.Push("stream", value["stream"])
m.Push("help", value["help"])
m.Push(kit.SSH_CTX, kit.Keys(value["ups"], value[kit.MDB_NAME]))
m.Push("", value, []string{ice.CTX_STATUS, ice.CTX_STREAM, kit.MDB_HELP})
})
}
}},

View File

@ -4,7 +4,6 @@ import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/aaa"
"github.com/shylinux/icebergs/base/cli"
"github.com/shylinux/icebergs/base/gdb"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/tcp"
kit "github.com/shylinux/toolkits"
@ -19,7 +18,7 @@ import (
func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool {
if r.Header.Get("index.module") == "" {
r.Header.Set("index.module", m.Target().Name)
} else {
} else { // 模块接口
return true
}
@ -67,8 +66,11 @@ func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool {
return false
}
// 内置文件
return !ice.DumpBinPack(w, r.URL.Path, func(name string) { RenderType(w, name, "") })
// 文件接口
if ice.DumpBinPack(w, r.URL.Path, func(name string) { RenderType(w, name, "") }) {
return false
}
return true
}
func _serve_handle(key string, cmd *ice.Command, msg *ice.Message, w http.ResponseWriter, r *http.Request) {
defer func() {
@ -98,7 +100,7 @@ func _serve_handle(key string, cmd *ice.Command, msg *ice.Message, w http.Respon
if msg.R, msg.W = r, w; r.Header.Get("X-Real-Port") != "" {
msg.Option(ice.MSG_USERADDR, msg.Option(ice.MSG_USERIP)+":"+r.Header.Get("X-Real-Port"))
} else {
msg.Option(ice.MSG_USERADDR, r.RemoteAddr)
msg.Option(ice.MSG_USERADDR, msg.Option(ice.MSG_USERIP))
}
// 请求数据
@ -144,7 +146,7 @@ func _serve_handle(key string, cmd *ice.Command, msg *ice.Message, w http.Respon
// 执行命令
if cmds, ok := _serve_login(msg, kit.Simple(msg.Optionv(ice.MSG_CMDS)), w, r); ok {
msg.Option(ice.MSG_USEROPT, msg.Optionv(ice.MSG_OPTION))
msg.Option(ice.MSG_OPTS, msg.Optionv(ice.MSG_OPTION))
msg.Target().Cmd(msg, key, r.URL.Path, cmds...)
}
@ -156,13 +158,13 @@ func _serve_login(msg *ice.Message, cmds []string, w http.ResponseWriter, r *htt
msg.Option(ice.MSG_USERROLE, aaa.VOID)
msg.Option(ice.MSG_USERNAME, "")
if msg.Options(ice.MSG_SESSID) {
// 会话认证
if msg.Option(ice.MSG_SESSID) != "" {
aaa.SessCheck(msg, msg.Option(ice.MSG_SESSID))
// 会话认证
}
if !msg.Options(ice.MSG_USERNAME) && tcp.IsLocalHost(msg, msg.Option(ice.MSG_USERIP)) && msg.Conf(SERVE, kit.Keym(tcp.LOCALHOST)) == "true" {
// 自动认证
if msg.Option(ice.MSG_USERNAME) == "" && tcp.IsLocalHost(msg, msg.Option(ice.MSG_USERIP)) && msg.Conf(SERVE, kit.Keym(tcp.LOCALHOST)) == "true" {
aaa.UserLogin(msg, ice.Info.UserName, ice.Info.PassWord)
// 主机认证
}
if _, ok := msg.Target().Commands[LOGIN]; ok {
@ -177,24 +179,19 @@ func _serve_login(msg *ice.Message, cmds []string, w http.ResponseWriter, r *htt
return cmds, true // 白名单
}
if msg.Warn(!msg.Options(ice.MSG_USERNAME), ice.ErrNotLogin, r.URL.Path) {
msg.Render(STATUS, 401, ice.ErrNotLogin)
if msg.Warn(msg.Option(ice.MSG_USERNAME) == "", ice.ErrNotLogin, r.URL.Path) {
msg.Render(STATUS, http.StatusUnauthorized, ice.ErrNotLogin)
return cmds, false // 未登录
}
if msg.Warn(!msg.Right(r.URL.Path)) {
msg.Render(STATUS, 403, ice.ErrNotAuth)
msg.Render(STATUS, http.StatusForbidden, ice.ErrNotRight)
return cmds, false // 未授权
}
return cmds, true
}
const (
LOGIN = "_login"
)
const (
SERVE_START = "serve.start"
SERVE_CLOSE = "serve.close"
WEB_LOGIN = "_login"
)
const SERVE = "serve"
@ -203,12 +200,13 @@ func init() {
Configs: map[string]*ice.Config{
SERVE: {Name: SERVE, Help: "服务器", Value: kit.Data(kit.MDB_SHORT, kit.MDB_NAME,
tcp.LOCALHOST, true, aaa.BLACK, kit.Dict(), aaa.WHITE, kit.Dict(
"intshell", true, "volcanos", true, "publish", true, "plugin", true,
"login", true, "space", true, "share", true,
"intshell", true, "volcanos", true,
"publish", true, "require", true,
SPACE, true, SHARE, true,
), "logheaders", false,
"static", kit.Dict("/", "usr/volcanos/"),
"volcanos", kit.Dict("path", "usr/volcanos", "index", "page/index.html",
"volcanos", kit.Dict("path", "usr/volcanos", "index", "index.html",
"repos", "https://github.com/shylinux/volcanos", "branch", "master",
), "publish", "usr/publish/",
@ -229,7 +227,7 @@ func init() {
m.Conf(SERVE, kit.Keys(kit.MDB_META, aaa.WHITE, k), true)
}
}},
gdb.START: {Name: "start dev= name=self proto=http host= port=9020", Help: "启动", Hand: func(m *ice.Message, arg ...string) {
tcp.START: {Name: "start dev= name=self proto=http host= port=9020", Help: "启动", Hand: func(m *ice.Message, arg ...string) {
if cli.NodeInfo(m, SERVER, ice.Info.HostName); m.Option(tcp.PORT) == "random" {
m.Option(tcp.PORT, m.Cmdx(tcp.PORT, aaa.RIGHT))
}
@ -255,8 +253,8 @@ func init() {
"/publish/": {Name: "/publish/", Help: "源码", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
_share_local(m, m.Conf(SERVE, kit.Keym("publish")), path.Join(arg...))
}},
"/plugin/github.com/": {Name: "/plugin/github.com/", Help: "源码", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
_share_repos(m, path.Join("github.com", arg[0], arg[1]), arg[2:]...)
"/require/": {Name: "/require/", Help: "源码", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
_share_repos(m, path.Join(arg[0], arg[1], arg[2]), arg[3:]...)
}},
}})
}

View File

@ -3,7 +3,6 @@ package web
import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/aaa"
"github.com/shylinux/icebergs/base/cli"
"github.com/shylinux/icebergs/base/mdb"
kit "github.com/shylinux/toolkits"
@ -21,14 +20,14 @@ func _share_cache(m *ice.Message, arg ...string) {
func _share_local(m *ice.Message, arg ...string) {
p := path.Join(arg...)
switch ls := strings.Split(p, "/"); ls[0] {
case "etc", "var": // 私有文件
case kit.SSH_ETC, kit.SSH_VAR: // 私有文件
if m.Option(ice.MSG_USERROLE) == aaa.VOID {
m.Render(STATUS, http.StatusUnauthorized, "not auth")
m.Render(STATUS, http.StatusUnauthorized, ice.ErrNotRight)
return // 没有权限
}
default:
if m.Warn(!m.Right(ls), ice.ErrNotAuth, m.Option(ice.MSG_USERROLE), " of ", p) {
m.Render(STATUS, http.StatusUnauthorized, "not auth")
if !m.Right(ls) {
m.Render(STATUS, http.StatusUnauthorized, ice.ErrNotRight)
return // 没有权限
}
}
@ -41,18 +40,19 @@ func _share_local(m *ice.Message, arg ...string) {
}
m.Cmdy(SPACE, m.Option(kit.SSH_POD), SPIDE, SPIDE_DEV, SPIDE_RAW, kit.MergeURL2(m.Option(ice.MSG_USERWEB), "/share/proxy/"),
SPIDE_PART, kit.SSH_POD, m.Option(kit.SSH_POD), kit.MDB_PATH, p, "cache", cache.Format(ice.MOD_TIME), "upload", "@"+p)
SPIDE_PART, kit.SSH_POD, m.Option(kit.SSH_POD), kit.MDB_PATH, p, CACHE, cache.Format(ice.MOD_TIME), UPLOAD, "@"+p)
p = path.Join("var/proxy", m.Option(kit.SSH_POD), p)
p = pp
}
m.Render(ice.RENDER_DOWNLOAD, p)
}
func _share_proxy(m *ice.Message, arg ...string) {
switch m.R.Method {
case http.MethodGet:
case http.MethodGet: // 下发文件
m.Render(ice.RENDER_DOWNLOAD, path.Join("var/proxy", path.Join(m.Option(kit.SSH_POD), m.Option(kit.MDB_PATH), m.Option(kit.MDB_NAME))))
case http.MethodPost:
case http.MethodPost: // 上传文件
m.Cmdy(CACHE, UPLOAD)
m.Cmdy(CACHE, WATCH, m.Option("data"), path.Join("var/proxy", m.Option(kit.SSH_POD), m.Option(kit.MDB_PATH)))
m.Render(ice.RENDER_RESULT, m.Option(kit.MDB_PATH))
@ -61,11 +61,16 @@ func _share_proxy(m *ice.Message, arg ...string) {
func _share_repos(m *ice.Message, repos string, arg ...string) {
prefix := kit.Path(m.Conf(SERVE, "meta.require"))
if _, e := os.Stat(path.Join(prefix, repos)); e != nil {
m.Cmd(cli.SYSTEM, "git", "clone", "https://"+repos, path.Join(prefix, repos))
m.Cmd("web.code.git.repos", mdb.CREATE, kit.SSH_REPOS, "https://"+repos, kit.MDB_PATH, path.Join(prefix, repos))
}
m.Render(ice.RENDER_DOWNLOAD, path.Join(prefix, repos, path.Join(arg...)))
}
const (
LOGIN = "login"
RIVER = "river"
STORM = "storm"
)
const SHARE = "share"
func init() {
@ -76,63 +81,53 @@ func init() {
Commands: map[string]*ice.Command{
SHARE: {Name: "share hash auto", Help: "共享链", Action: map[string]*ice.Action{
mdb.CREATE: {Name: "create type name text", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.INSERT, SHARE, "", mdb.HASH,
m.Cmdy(mdb.INSERT, SHARE, "", mdb.HASH, kit.MDB_TIME, m.Time(m.Conf(SHARE, "meta.expire")),
aaa.USERROLE, m.Option(ice.MSG_USERROLE), aaa.USERNAME, m.Option(ice.MSG_USERNAME),
"river", m.Option(ice.MSG_RIVER), "storm", m.Option(ice.MSG_STORM),
kit.MDB_TIME, m.Time(m.Conf(SHARE, "meta.expire")), arg)
RIVER, m.Option(ice.MSG_RIVER), STORM, m.Option(ice.MSG_STORM), arg)
}},
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.DELETE, SHARE, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH))
}},
mdb.SELECT: {Name: "select hash", Help: "查询", Hand: func(m *ice.Message, arg ...string) {
m.Option(mdb.FIELDS, "time,userrole,username,river,storm,type,name,text")
m.Cmdy(mdb.SELECT, SHARE, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH))
}},
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.DELETE, SHARE, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH))
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Option(mdb.FIELDS, kit.Select("time,hash,userrole,username,river,storm,type,name,text", mdb.DETAIL, len(arg) > 0))
m.Cmdy(mdb.SELECT, SHARE, "", mdb.HASH, kit.MDB_HASH, arg)
m.PushAction(mdb.REMOVE)
if len(arg) > 0 {
m.PushAnchor(kit.MergeURL2(m.Option(ice.MSG_USERWEB), "/share/"+arg[0], SHARE, arg[0]))
m.PushQRCode("share", kit.MergeURL2(m.Option(ice.MSG_USERWEB), "/share/"+arg[0], SHARE, arg[0]))
}
}},
"/share/": {Name: "/share/", Help: "共享链", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Option(mdb.FIELDS, kit.Select("time,hash,userrole,username,river,storm,type,name,text"))
switch msg := m.Cmd(mdb.SELECT, SHARE, "", mdb.HASH, kit.MDB_HASH, kit.Select(m.Option("share"), arg, 0)); msg.Append(kit.MDB_TYPE) {
case "login":
switch kit.Select("", arg, 1) {
case "share":
list := []string{}
for _, k := range []string{"river", "storm"} {
if msg.Append(k) != "" {
list = append(list, k, msg.Append(k))
}
}
m.Render(ice.RENDER_QRCODE, kit.MergeURL2(m.Option(ice.MSG_USERWEB), "/", SHARE, arg[0], list))
}
case "river":
switch kit.Select("", arg, 1) {
case "share":
list := []string{}
for _, k := range []string{"river"} {
if msg.Append(k) != "" {
list = append(list, k, msg.Append(k))
}
}
m.Render(ice.RENDER_QRCODE, kit.MergeURL2(m.Option(ice.MSG_USERWEB), "/", SHARE, arg[0], list))
default:
m.Render("redirect", "/", "river", msg.Append("river"))
msg := m.Cmd(mdb.SELECT, SHARE, "", mdb.HASH, kit.MDB_HASH, kit.Select(m.Option(SHARE), arg, 0))
list := []string{SHARE, kit.Select(m.Option(SHARE), arg, 0)}
for _, k := range []string{RIVER, STORM} {
if msg.Append(k) != "" {
list = append(list, k, msg.Append(k))
}
case "storm":
}
switch msg.Append(kit.MDB_TYPE) {
case LOGIN, RIVER:
switch kit.Select("", arg, 1) {
case "share":
list := []string{}
for _, k := range []string{"river", "storm"} {
if msg.Append(k) != "" {
list = append(list, k, msg.Append(k))
}
}
m.Render(ice.RENDER_QRCODE, kit.MergeURL2(m.Option(ice.MSG_USERWEB), "/page/share.html", SHARE, arg[0], list))
case SHARE:
m.Render(ice.RENDER_QRCODE, kit.MergeURL2(m.Option(ice.MSG_USERWEB), "/", list))
default:
m.Render("redirect", "/page/share.html", "share", m.Option("share"))
m.Render(REDIRECT, "/", list)
}
case STORM:
switch kit.Select("", arg, 1) {
case SHARE:
m.Render(ice.RENDER_QRCODE, kit.MergeURL2(m.Option(ice.MSG_USERWEB), "/page/share.html", list))
default:
m.Render(REDIRECT, "/page/share.html", SHARE, m.Option(SHARE))
}
}
}},

View File

@ -11,7 +11,6 @@ import (
"math/rand"
"net"
"net/url"
"os"
"strings"
"time"
)
@ -19,45 +18,51 @@ import (
func _space_list(m *ice.Message, space string) {
m.Option(mdb.FIELDS, kit.Select("time,type,name,text", mdb.DETAIL, space != ""))
m.Cmdy(mdb.SELECT, SPACE, "", mdb.HASH, kit.MDB_NAME, space)
m.Table(func(index int, value map[string]string, head []string) {
p := kit.MergeURL(m.Option(ice.MSG_USERWEB), kit.SSH_POD, kit.Keys(m.Option(kit.SSH_POD), kit.Select(value[kit.MDB_VALUE], value[kit.MDB_NAME])))
m.PushRender(kit.MDB_LINK, "a", value[kit.MDB_NAME], p)
})
m.Sort(kit.MDB_NAME)
if space == "" {
m.Table(func(index int, value map[string]string, head []string) {
m.PushAnchor(value[kit.MDB_NAME], kit.MergeURL(strings.Split(m.Option(ice.MSG_USERWEB), "?")[0],
kit.SSH_POD, kit.Keys(m.Option(ice.MSG_USERPOD), value[kit.MDB_NAME])))
})
m.SortStrR(kit.MDB_NAME)
}
}
func _space_dial(m *ice.Message, dev, name string, arg ...string) {
m.Richs(SPIDE, nil, dev, func(key string, value map[string]interface{}) {
client := kit.Value(value, "client").(map[string]interface{})
client := kit.Value(value, tcp.CLIENT).(map[string]interface{})
redial := m.Confm(SPACE, "meta.redial")
web := m.Target().Server().(*Frame)
frame := m.Target().Server().(*Frame)
host := kit.Format(client[tcp.HOSTNAME])
proto := strings.Replace(kit.Format(client[tcp.PROTOCOL]), "http", "ws", 1)
uri := kit.MergeURL(proto+"://"+host+"/space/", kit.MDB_TYPE, ice.Info.NodeType,
kit.MDB_NAME, name, "share", ice.Info.CtxShare, "river", ice.Info.CtxRiver, arg)
host := kit.Format(client["hostname"])
proto := kit.Select("ws", "wss", client["protocol"] == "https")
uri := kit.MergeURL(proto+"://"+host+"/space/", "name", name, "type", ice.Info.NodeType, "share", os.Getenv("ctx_share"), "river", os.Getenv("ctx_river"))
if u, e := url.Parse(uri); m.Assert(e) {
m.Go(func() {
for i := 0; i >= 0 && i < kit.Int(redial["c"]); i++ {
m.Option(tcp.DIAL_CB, func(s net.Conn, e error) {
if m.Warn(e != nil, e) {
msg := m.Spawn()
msg.Option(tcp.DIAL_CB, func(s net.Conn, e error) {
if msg.Warn(e != nil, e) {
return
}
if s, _, e := websocket.NewClient(s, u, nil, kit.Int(redial["r"]), kit.Int(redial["w"])); !m.Warn(e != nil, e) {
m.Rich(SPACE, nil, kit.Dict("socket", s, kit.MDB_TYPE, MASTER, kit.MDB_NAME, dev, kit.MDB_TEXT, host))
m.Log_CREATE(SPACE, dev, "retry", i, "uri", uri)
if s, _, e := websocket.NewClient(s, u, nil, kit.Int(redial["r"]), kit.Int(redial["w"])); !msg.Warn(e != nil, e) {
msg.Rich(SPACE, nil, kit.Dict(tcp.SOCKET, s, kit.MDB_TYPE, MASTER, kit.MDB_NAME, dev, kit.MDB_TEXT, host))
msg.Log_CREATE(SPACE, dev, "retry", i, "uri", uri)
// 连接成功
m = m.Spawn()
if i = 0; _space_handle(m, true, web.send, s, dev) {
i = -1 // 连接关闭
if i = 0; _space_handle(msg, true, frame.send, s, dev) {
i = -2 // 连接关闭
}
}
})
ls := strings.Split(host, ":")
m.Cmd(tcp.CLIENT, tcp.DIAL, kit.MDB_TYPE, "wss", kit.MDB_NAME, dev, tcp.HOST, ls[0], tcp.PORT, ls[1])
msg.Cmd(tcp.CLIENT, tcp.DIAL, kit.MDB_TYPE, "wss", kit.MDB_NAME, dev, tcp.HOST, ls[0], tcp.PORT, ls[1])
// 断线重连
sleep := time.Duration(rand.Intn(kit.Int(redial["a"])*i+2)+kit.Int(redial["b"])) * time.Millisecond
m.Cost("order", i, "sleep", sleep, "reconnect", u)
msg.Cost("order", i, "sleep", sleep, "reconnect", u)
time.Sleep(sleep)
}
})
@ -66,37 +71,37 @@ func _space_dial(m *ice.Message, dev, name string, arg ...string) {
}
func _space_send(m *ice.Message, space string, arg ...string) {
if space == "" || space == MYSELF || space == ice.Info.NodeName {
m.Cmdy(arg)
return // 本地命令
m.Cmdy(arg) // 本地命令
return
}
target := strings.Split(space, ".")
frame := m.Target().Server().(*Frame)
target := kit.Split(space, ".", ".")
m.Warn(m.Richs(SPACE, nil, target[0], func(key string, value map[string]interface{}) {
if socket, ok := value["socket"].(*websocket.Conn); !m.Warn(!ok, "socket err") {
if socket, ok := value[tcp.SOCKET].(*websocket.Conn); !m.Warn(!ok, ice.ErrNotFound, tcp.SOCKET) {
// 复制选项
for _, k := range kit.Simple(m.Optionv(ice.MSG_USEROPT)) {
for _, k := range kit.Simple(m.Optionv(ice.MSG_OPTS)) {
switch k {
case "detail", "cmds", ice.MSG_SESSID:
case ice.MSG_DETAIL, ice.MSG_CMDS, ice.MSG_SESSID:
default:
m.Optionv(k, m.Optionv(k))
}
}
m.Optionv(ice.MSG_USEROPT, m.Optionv(ice.MSG_USEROPT))
m.Optionv("option", nil)
m.Optionv(ice.MSG_OPTS, m.Optionv(ice.MSG_OPTS))
m.Optionv(ice.MSG_OPTION, nil)
// 构造路由
frame := m.Target().Server().(*Frame)
id := kit.Format(m.Target().ID())
frame.send[id] = m
// 下发命令
m.Set(ice.MSG_DETAIL, arg...)
_space_echo(m, []string{id}, target[1:], socket, target[0])
_space_echo(m.Set(ice.MSG_DETAIL, arg...), []string{id}, target[1:], socket, target[0])
m.Option("timeout", m.Conf(SPACE, "meta.timeout.c"))
m.Call(m.Option("_async") == "", func(res *ice.Message) *ice.Message {
// 返回结果
if delete(frame.send, id); res != nil && m != nil {
// 返回结果
return m.Cost(kit.Format("[%v]->%v %v %v", id, target, arg, m.Copy(res).Format(ice.MSG_APPEND)))
}
return nil
@ -106,24 +111,19 @@ func _space_send(m *ice.Message, space string, arg ...string) {
}
func _space_echo(msg *ice.Message, source, target []string, c *websocket.Conn, name string) {
_args, _ := msg.Optionv(ice.MSG_ARGS).([]interface{})
switch arg := kit.Simple(_args...); msg.Option(ice.MSG_OUTPUT) {
case ice.RENDER_DOWNLOAD:
msg.Cmdy("nfs.cat", arg[0])
}
msg.Optionv(ice.MSG_SOURCE, source)
msg.Optionv(ice.MSG_TARGET, target)
e := c.WriteMessage(1, []byte(msg.Format("meta")))
msg.Assert(e)
msg.Assert(c.WriteMessage(1, []byte(msg.Format(kit.MDB_META))))
target = append([]string{name}, target...)
msg.Log("send", "%v->%v %v %v", source, target, msg.Detailv(), msg.Format("meta"))
msg.Log("send", "%v->%v %v %v", source, target, msg.Detailv(), msg.Format(kit.MDB_META))
}
func _space_exec(msg *ice.Message, source, target []string, c *websocket.Conn, name string) {
if !msg.Warn(!msg.Right(msg.Detailv()), ice.ErrNotAuth) {
if !msg.Warn(!msg.Right(msg.Detailv()), ice.ErrNotRight) {
msg = msg.Cmd()
}
msg.Set(ice.MSG_USEROPT)
msg.Set(ice.MSG_OPTS)
_space_echo(msg, []string{}, kit.Revert(source)[1:], c, name)
msg.Cost(kit.Format("%v->%v %v %v", source, target, msg.Detailv(), msg.Format(ice.MSG_APPEND)))
}
@ -135,61 +135,64 @@ func _space_handle(m *ice.Message, safe bool, send map[string]*ice.Message, c *w
socket, msg := c, m.Spawn(b)
target := kit.Simple(msg.Optionv(ice.MSG_TARGET))
source := kit.Simple(msg.Optionv(ice.MSG_SOURCE), name)
msg.Log("recv", "%v->%v %s %v", source, target, msg.Detailv(), msg.Format("meta"))
msg.Log("recv", "%v->%v %s %v", source, target, msg.Detailv(), msg.Format(kit.MDB_META))
if len(target) == 0 {
if len(target) == 0 { // 本地执行
if msg.Option(ice.MSG_USERROLE, aaa.UserRole(msg, msg.Option(ice.MSG_USERNAME))) == aaa.VOID {
role := msg.Cmdx(SPIDE, SPIDE_DEV, SPIDE_MSG, SPIDE_GET, "/chat/header", "cmds", aaa.USERROLE, "who", msg.Option(ice.MSG_USERNAME))
msg.Option(ice.MSG_USERROLE, kit.Select(role, aaa.TECH, role == aaa.ROOT))
}
msg.Log_AUTH(aaa.USERROLE, msg.Option(ice.MSG_USERROLE), aaa.USERNAME, msg.Option(ice.MSG_USERNAME))
if msg.Optionv(ice.MSG_HANDLE, "true"); !msg.Warn(!safe, ice.ErrNotAuth) {
// 本地执行
msg.Option("_dev", name)
if msg.Optionv(ice.MSG_HANDLE, "true"); !msg.Warn(!safe, ice.ErrNotRight) {
msg.Go(func() { _space_exec(msg, source, target, c, name) })
}
} else if msg.Richs(SPACE, nil, target[0], func(key string, value map[string]interface{}) {
// 查询节点
name := target[0]
if s, ok := value["socket"].(*websocket.Conn); ok {
socket, source, target = s, source, target[1:]
} else {
if s, ok := value[tcp.SOCKET].(*websocket.Conn); ok {
socket, source, target = s, source, target[1:]
_space_echo(msg, source, target, socket, target[0])
return // 转发报文
}
_space_echo(msg, source, target, socket, name)
}) != nil {
// 转发报文
} else if res, ok := send[msg.Option(ice.MSG_TARGET)]; len(target) == 1 && ok {
// 接收响应
if msg.Warn(msg.Option(ice.MSG_HANDLE) == "true", ice.ErrNotFound) {
// 回复失败
} else { // 下发失败
msg.Warn(true, ice.ErrNotFound)
source, target = []string{}, kit.Revert(source)[1:]
}
}) != nil { // 转发成功
} else if res, ok := send[msg.Option(ice.MSG_TARGET)]; len(target) != 1 || !ok {
if msg.Warn(msg.Option(ice.MSG_HANDLE) == "true", ice.ErrNotFound) {
// 回复失败
} else { // 下发失败
msg.Warn(true, ice.ErrNotFound)
source, target = []string{}, kit.Revert(source)[1:]
}
} else { // 接收响应
res.Back(msg)
} else if msg.Warn(msg.Option("_handle") == "true", "space miss") {
// 回复失败
} else {
// 下发失败
msg.Warn(true, "space error")
source, target = []string{}, kit.Revert(source)[1:]
}
}
}
return false
}
func _space_search(m *ice.Message, kind, name, text string, arg ...string) {
m.Richs(SPACE, nil, kit.MDB_FOREACH, func(key string, val map[string]interface{}) {
if val = kit.GetMeta(val); strings.Contains(kit.Format(val["name"]), name) {
m.PushSearch("cmd", SPACE, "type", val["type"], "name", val["name"], "text", kit.MergeURL(m.Option(ice.MSG_USERWEB), "pod", val["name"]))
m.Richs(SPACE, nil, kit.MDB_FOREACH, func(key string, value map[string]interface{}) {
if value = kit.GetMeta(value); strings.Contains(kit.Format(value[kit.MDB_NAME]), name) {
m.PushSearch(kit.SSH_CMD, SPACE, kit.MDB_TYPE, value[kit.MDB_TYPE], kit.MDB_NAME, value[kit.MDB_NAME],
kit.MDB_TEXT, kit.MergeURL(m.Option(ice.MSG_USERWEB), kit.SSH_POD, kit.Keys(m.Option(ice.MSG_USERPOD), value[kit.MDB_NAME])))
}
})
}
const (
CHROME = "chrome"
MASTER = "master"
MYSELF = "myself"
BETTER = "better"
CHROME = "chrome"
SERVER = "server"
WORKER = "worker"
)
@ -211,9 +214,9 @@ func init() {
Commands: map[string]*ice.Command{
SPACE: {Name: "space name cmd auto", Help: "空间站", Action: map[string]*ice.Action{
tcp.DIAL: {Name: "dial dev name", Help: "连接", Hand: func(m *ice.Message, arg ...string) {
_space_dial(m, m.Option("dev"), kit.Select(ice.Info.NodeName, m.Option(kit.MDB_NAME)))
_space_dial(m, m.Option(SPIDE_DEV), kit.Select(ice.Info.NodeName, m.Option(kit.MDB_NAME)))
}},
mdb.SEARCH: {Name: "search type name text arg...", Help: "搜索", Hand: func(m *ice.Message, arg ...string) {
mdb.SEARCH: {Name: "search type name text", Help: "搜索", Hand: func(m *ice.Message, arg ...string) {
_space_search(m, arg[0], arg[1], kit.Select("", arg, 2))
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
@ -224,32 +227,33 @@ func init() {
_space_send(m, arg[0], arg[1:]...)
}},
"/space/": {Name: "/space/ type name", Help: "空间站", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
"/space/": {Name: "/space/ type name share river", Help: "空间站", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if s, e := websocket.Upgrade(m.W, m.R, nil, kit.Int(m.Conf(SPACE, "meta.buffer.r")), kit.Int(m.Conf(SPACE, "meta.buffer.w"))); m.Assert(e) {
name := m.Option(kit.MDB_NAME, strings.Replace(kit.Select(m.Option(ice.MSG_USERADDR), m.Option(kit.MDB_NAME)), ".", "_", -1))
name := m.Option(kit.MDB_NAME, strings.Replace(kit.Select(s.RemoteAddr().String(), m.Option(kit.MDB_NAME)), ".", "_", -1))
kind := kit.Select(WORKER, m.Option(kit.MDB_TYPE))
share := m.Option("share")
river := m.Option("river")
// 添加节点
h := m.Rich(SPACE, nil, kit.Dict("socket", s, "share", share, "river", river,
h := m.Rich(SPACE, nil, kit.Dict(tcp.SOCKET, s, "share", share, "river", river,
kit.MDB_TYPE, kind, kit.MDB_NAME, name, kit.MDB_TEXT, s.RemoteAddr().String(),
))
m.Go(func() {
defer m.Confv(SPACE, kit.Keys(kit.MDB_HASH, h), "")
// 监听消息
switch kind {
switch args := []string{kit.MDB_TYPE, kind, kit.MDB_NAME, name, "share", share, "river", river}; kind {
case WORKER:
m.Event(DREAM_START, "type", kind, "name", name, "share", share, "river", river)
defer m.Event(DREAM_STOP, "type", kind, "name", name, "share", share, "river", river)
m.Event(DREAM_START, args...)
defer m.Event(DREAM_STOP, args...)
default:
m.Event(SPACE_START, "type", kind, "name", name, "share", share, "river", river)
defer m.Event(SPACE_STOP, "type", kind, "name", name, "share", share, "river", river)
m.Event(SPACE_START, args...)
defer m.Event(SPACE_STOP, args...)
}
frame := m.Target().Server().(*Frame)
_space_handle(m, false, frame.send, s, name)
m.Confv(SPACE, kit.Keys(kit.MDB_HASH, h), "")
})
}
}},

View File

@ -72,8 +72,6 @@ func (web *Frame) Start(m *ice.Message, arg ...string) bool {
web.m, web.Server = m, &http.Server{Handler: web}
m.Option(tcp.LISTEN_CB, func(l net.Listener) {
m.Cmdy(mdb.INSERT, SERVE, "", mdb.HASH, arg, kit.MDB_STATUS, tcp.START, kit.MDB_PROTO, m.Option(kit.MDB_PROTO), SPIDE_DEV, m.Option(SPIDE_DEV))
m.Event(SERVE_START, arg...)
defer m.Event(SERVE_CLOSE, arg...)
defer m.Cmd(mdb.MODIFY, SERVE, "", mdb.HASH, kit.MDB_NAME, m.Option(kit.MDB_NAME), kit.MDB_STATUS, tcp.STOP)
// 启动服务
@ -113,7 +111,7 @@ var Index = &ice.Context{Name: WEB, Help: "网络模块",
func init() {
ice.Index.Register(Index, &Frame{},
SPIDE, SERVE, SPACE, DREAM,
ROUTE, CACHE, SHARE, STORY,
ROUTE, SERVE, SPACE, DREAM,
SPIDE, SHARE, CACHE, STORY,
)
}

View File

@ -1,11 +1,11 @@
chapter "web"
field "蜘蛛侠" web.spide
field "路由器" web.route
field "服务器" web.serve
field "空间站" web.space
field "梦想家" web.dream
field "路由器" web.route
field "蜘蛛侠" web.spide
field "共享链" web.share
field "缓存池" web.cache
field "故事会" web.story

61
conf.go
View File

@ -6,7 +6,7 @@ const ( //MOD
MOD_CHAN = 16
MOD_TICK = "1s"
MOD_BUF = 1024
MOD_BUFS = 1024
MOD_DATE = "2006-01-02"
MOD_TIME = "2006-01-02 15:04:05"
@ -25,26 +25,25 @@ const ( // MSG
MSG_OUTPUT = "_output"
MSG_ARGS = "_args"
MSG_PROCESS = "_process"
MSG_CONTROL = "_control"
MSG_DISPLAY = "_display"
MSG_PROCESS = "_process"
MSG_CMDS = "cmds"
MSG_DOMAIN = "domain"
MSG_SESSID = "sessid"
MSG_DOMAIN = "domain"
MSG_OPTS = "_option"
MSG_USERIP = "user.ip"
MSG_USERUA = "user.ua"
MSG_USERWEB = "user.web"
MSG_USERPOD = "user.pod"
// MSG_USEROPT = "user.opt"
MSG_USEROPT = "_option"
MSG_USERIP = "user.ip"
MSG_USERUA = "user.ua"
MSG_USERWEB = "user.web"
MSG_USERPOD = "user.pod"
MSG_USERADDR = "user.addr"
MSG_USERDATA = "user.data"
MSG_USERNICK = "user.nick"
MSG_USERNAME = "user.name"
MSG_USERZONE = "user.zone"
MSG_USERROLE = "user.role"
MSG_USERDATA = "user.data"
MSG_USERADDR = "user.addr"
MSG_RIVER = "sess.river"
MSG_STORM = "sess.storm"
@ -53,41 +52,32 @@ const ( // MSG
const ( // RENDER
RENDER_VOID = "_void"
RENDER_RESULT = "_result"
RENDER_ANCHOR = "_anchor"
RENDER_BUTTON = "_button"
RENDER_QRCODE = "_qrcode"
RENDER_SCRIPT = "_script"
RENDER_DOWNLOAD = "_download"
RENDER_TEMPLATE = "_template"
)
const (
CONTROL_PAGE = "_page"
const ( // PROCESS
PROCESS_REFRESH = "_refresh"
PROCESS_FOLLOW = "_follow"
PROCESS_INNER = "_inner"
PROCESS_FIELD = "_field"
)
const ( // CTX
CTX_FOLLOW = "follow"
CTX_STATUS = "status"
CTX_STREAM = "stream"
CTX_BEGIN = "begin"
CTX_START = "start"
CTX_SERVE = "serve"
CTX_CLOSE = "close"
CTX_INIT = "_init"
CTX_EXIT = "_exit"
FIELD_PREFIX = "_prefix"
CONTROL_PAGE = "_page"
)
const ( // LOG
// 数据
LOG_IMPORT = "import"
LOG_EXPORT = "export"
LOG_CREATE = "create"
LOG_REMOVE = "remove"
LOG_MODIFY = "modify"
LOG_INSERT = "insert"
LOG_DELETE = "delete"
LOG_SELECT = "select"
LOG_MODIFY = "modify"
LOG_EXPORT = "export"
LOG_IMPORT = "import"
// 状态
LOG_BEGIN = "begin"
@ -104,3 +94,16 @@ const ( // LOG
LOG_ERROR = "error"
LOG_DEBUG = "debug"
)
const ( // CTX
CTX_FOLLOW = "follow"
CTX_STATUS = "status"
CTX_STREAM = "stream"
CTX_BEGIN = "begin"
CTX_START = "start"
CTX_SERVE = "serve"
CTX_CLOSE = "close"
CTX_INIT = "_init"
CTX_EXIT = "_exit"
)

View File

@ -73,7 +73,7 @@ func _action_show(m *ice.Message, river, storm, index string, arg ...string) {
if cmds = kit.Simple(kit.Keys(value[CTX], value[CMD])); kit.Format(value[POD]) != "" {
m.Option(POD, value[POD])
}
}) == nil && m.Warn(!m.Right(cmds), ice.ErrNotAuth) {
}) == nil && m.Warn(!m.Right(cmds), ice.ErrNotRight) {
return
}
@ -121,7 +121,7 @@ func init() {
if m.Warn(m.Option(ice.MSG_USERNAME) == "", ice.ErrNotLogin) {
return // 没有登录
}
if m.Warn(!_action_right(m, arg[0], arg[1]), ice.ErrNotAuth) {
if m.Warn(!_action_right(m, arg[0], arg[1]), ice.ErrNotRight) {
return // 没有授权
}
}

View File

@ -106,7 +106,7 @@ func init() {
mdb.INSERT: {Name: "insert type name share", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.INSERT, RIVER, kit.Keys(kit.MDB_HASH, m.Option(RIVER), NODE), mdb.HASH, arg)
}},
mdb.INVITE: {Name: "invite", Help: "邀请", Hand: func(m *ice.Message, arg ...string) {
aaa.INVITE: {Name: "invite", Help: "邀请", Hand: func(m *ice.Message, arg ...string) {
m.Option(web.SHARE, m.Cmdx(m.Prefix(AUTH), mdb.CREATE, kit.MDB_TYPE, NODE))
m.Cmdy(code.PUBLISH, "contexts", "tool")
}},
@ -232,7 +232,7 @@ func init() {
})
}},
USER: {Name: "user username auto insert invite", Help: "用户", Action: map[string]*ice.Action{
mdb.INVITE: {Name: "invite", Help: "邀请", Hand: func(m *ice.Message, arg ...string) {
aaa.INVITE: {Name: "invite", Help: "邀请", Hand: func(m *ice.Message, arg ...string) {
share := m.Option(web.SHARE, m.Cmdx(m.Prefix(AUTH), mdb.CREATE, kit.MDB_TYPE, USER))
m.Cmdy(wiki.SPARK, "inner", kit.MergeURL(m.Option(ice.MSG_USERWEB), RIVER, m.Option(ice.MSG_RIVER), web.SHARE, share))
m.Cmdy(wiki.IMAGE, "qrcode", kit.MergeURL(m.Option(ice.MSG_USERWEB), RIVER, m.Option(ice.MSG_RIVER), web.SHARE, share))
@ -329,7 +329,7 @@ func init() {
m.Cmdy(m.Prefix(arg[1]), arg[2:])
return // 应用列表
}
if m.Warn(!m.Right(RIVER, arg), ice.ErrNotAuth) {
if m.Warn(!m.Right(RIVER, arg), ice.ErrNotRight) {
return // 没有授权
}

View File

@ -34,7 +34,7 @@ func _inner_list(m *ice.Message, ext, file, dir string, arg ...string) {
return
}
if m.Warn(!m.Right(dir, file), ice.ErrNotAuth, path.Join(dir, file)) {
if m.Warn(!m.Right(dir, file), ice.ErrNotRight, path.Join(dir, file)) {
return // 没有权限
}
if m.Cmdy(mdb.RENDER, ext, file, dir, arg); m.Result() != "" {
@ -49,7 +49,7 @@ func _inner_list(m *ice.Message, ext, file, dir string, arg ...string) {
m.Echo(path.Join(dir, file))
}
func _inner_show(m *ice.Message, ext, file, dir string, arg ...string) {
if m.Warn(!m.Right(dir, file), ice.ErrNotAuth, path.Join(dir, file)) {
if m.Warn(!m.Right(dir, file), ice.ErrNotRight, path.Join(dir, file)) {
return // 没有权限
}
if m.Cmdy(mdb.ENGINE, ext, file, dir, arg); m.Result() != "" {

View File

@ -388,7 +388,7 @@ func init() {
}},
FIELD: {Name: "field [name] cmd", Help: "插件", Action: map[string]*ice.Action{
"run": {Name: "run", Help: "运行", Hand: func(m *ice.Message, arg ...string) {
if !m.Warn(!m.Right(arg[1:]), ice.ErrNotAuth, arg[1:]) {
if !m.Warn(!m.Right(arg[1:]), ice.ErrNotRight, arg[1:]) {
m.Cmdy(arg[1:])
}
}},

View File

@ -15,8 +15,11 @@ var Info = struct {
PathName string
UserName string
PassWord string
NodeType string
NodeName string
CtxShare string
CtxRiver string
Build struct {
Time string

View File

@ -9,10 +9,10 @@ import (
)
var ErrWarn = "warn: "
var ErrNotFound = "not found: "
var ErrNotLogin = "not login: "
var ErrNotAuth = "not auth: "
var ErrNotJoin = "not join: "
var ErrNotRight = "not right: "
var ErrNotFound = "not found: "
var ErrNotShare = "not share: "
var _log_disable = true
var Log func(m *Message, p, l, s string)

View File

@ -170,7 +170,7 @@ func (m *Message) Copy(msg *Message, arg ...string) *Message {
if i := kit.IndexOf(m.meta[MSG_OPTION], k); i > -1 && len(m.meta[k]) > 0 {
m.meta[k] = m.meta[k][:0]
}
if i := kit.IndexOf(m.meta[MSG_USEROPT], k); i > -1 && len(m.meta[k]) > 0 {
if i := kit.IndexOf(m.meta[MSG_OPTS], k); i > -1 && len(m.meta[k]) > 0 {
m.meta[k] = m.meta[k][:0]
}
if kit.IndexOf(m.meta[MSG_APPEND], k) == -1 {

102
misc.go
View File

@ -3,7 +3,10 @@ package ice
import (
kit "github.com/shylinux/toolkits"
"bytes"
"encoding/base64"
"fmt"
"github.com/skip2/go-qrcode"
"net/url"
"path"
"strings"
@ -47,7 +50,9 @@ func (m *Message) Event(key string, arg ...string) *Message {
return m
}
func (m *Message) Right(arg ...interface{}) bool {
return m.Option(MSG_USERROLE) == "root" || !m.Warn(m.Cmdx("aaa.role", "right", m.Option(MSG_USERROLE), strings.ReplaceAll(kit.Keys(arg...), "/", ".")) != "ok", ErrNotAuth, m.Option(MSG_USERROLE), " of ", strings.Join(kit.Simple(arg), "."))
return m.Option(MSG_USERROLE) == "root" || !m.Warn(m.Cmdx("aaa.role", "right",
m.Option(MSG_USERROLE), strings.ReplaceAll(kit.Keys(arg...), "/", ".")) != "ok",
ErrNotRight, m.Option(MSG_USERROLE), " of ", strings.Join(kit.Simple(arg), "."), " at ", kit.FileLine(2, 3))
}
func (m *Message) Space(arg interface{}) []string {
if arg == nil || arg == "" || kit.Format(arg) == m.Conf("cli.runtime", "node.name") {
@ -56,10 +61,15 @@ func (m *Message) Space(arg interface{}) []string {
return []string{"web.space", kit.Format(arg)}
}
func (m *Message) PushPlugin(key string, arg ...string) {
func (m *Message) PushPlugins(pod, ctx, cmd string, arg ...string) {
m.Cmdy("space", pod, "context", ctx, "command", cmd)
m.Option(MSG_PROCESS, PROCESS_FIELD)
m.Option("_prefix", arg)
m.Option(FIELD_PREFIX, arg)
}
func (m *Message) PushPlugin(key string, arg ...string) {
m.Cmdy("command", key)
m.Option(MSG_PROCESS, PROCESS_FIELD)
m.Option(FIELD_PREFIX, arg)
}
func (m *Message) PushRender(key, view, name string, arg ...string) *Message {
if m.Option(MSG_USERUA) == "" {
@ -81,22 +91,16 @@ func (m *Message) PushRender(key, view, name string, arg ...string) *Message {
m.Push(key, fmt.Sprintf(`<video src="%s" height=%s controls>`, name, kit.Select("120", arg, 0)))
case "img":
m.Push(key, fmt.Sprintf(`<img src="%s" height=%s>`, name, kit.Select("120", arg, 0)))
case "a":
case "a": // name [link]
m.Push(key, fmt.Sprintf(`<a href="%s" target="_blank">%s</a>`, kit.Select(name, arg, 0), name))
case "download":
case "download": // name [link]
m.Push(key, fmt.Sprintf(`<a href="%s" download="%s">%s</a>`, kit.Select(name, arg, 0), path.Base(name), name))
default:
m.Push(key, name)
}
return m
}
func (m *Message) PushButton(arg ...string) {
m.PushRender("action", "button", strings.Join(arg, ","))
}
func (m *Message) PushAnchor(name string, arg ...string) {
m.PushRender("link", "a", name, arg...)
}
func (m *Message) PushDownload(name string, arg ...string) {
func (m *Message) PushDownload(name string, arg ...string) { // name [file]
if len(arg) == 0 {
name = kit.MergeURL2(m.Option(MSG_USERWEB), path.Join("/share/local", name), "pod", m.Option(MSG_USERPOD))
} else {
@ -168,6 +172,80 @@ func (m *Message) SortIntR(key string) { m.Sort(key, "int_r") }
func (m *Message) SortTime(key string) { m.Sort(key, "time") }
func (m *Message) SortTimeR(key string) { m.Sort(key, "time_r") }
func _render(m *Message, cmd string, args ...interface{}) string {
switch arg := kit.Simple(args...); cmd {
case RENDER_ANCHOR: // [name] link
return fmt.Sprintf(`<a href="%s" target="_blank">%s</a>`, kit.Select(arg[0], arg, 1), arg[0])
case RENDER_BUTTON: // name...
list := []string{}
for _, k := range kit.Split(strings.Join(arg, ",")) {
list = append(list, fmt.Sprintf(`<input type="button" name="%s" value="%s">`,
k, kit.Select(k, kit.Value(m.cmd.Meta, kit.Keys("trans", k)))))
}
return strings.Join(list, "")
case RENDER_QRCODE: // text size height
buf := bytes.NewBuffer(make([]byte, 0, MOD_BUFS))
if qr, e := qrcode.New(arg[0], qrcode.Medium); m.Assert(e) {
m.Assert(qr.Write(kit.Int(kit.Select("240", arg, 1)), buf))
}
arg[0] = "data:image/png;base64," + base64.StdEncoding.EncodeToString(buf.Bytes())
return fmt.Sprintf(`<img src="%s" height=%s>`, arg[0], kit.Select("240", arg, 1))
case RENDER_SCRIPT: // type text
list := []string{}
list = append(list, kit.Format(`<div class="story" data-type="spark" data-name="%s">`, arg[0]))
for _, l := range strings.Split(arg[1], "\n") {
list = append(list, "<div>")
switch arg[0] {
case "shell":
list = append(list, "<label>$ </label>")
default:
list = append(list, "<label>&lt; </label>")
}
list = append(list, "<span>")
list = append(list, l)
list = append(list, "</span>")
list = append(list, "</div>")
}
list = append(list, "</div>")
return strings.Join(list, "")
case RENDER_DOWNLOAD: // file [link]
return fmt.Sprintf(`<a href="%s" download="%s">%s</a>`, kit.Select(arg[0], arg, 1), path.Base(arg[0]), arg[0])
}
return ""
}
func (m *Message) PushAnchor(arg ...interface{}) { // [name] link
m.Push("link", _render(m, RENDER_ANCHOR, arg...))
}
func (m *Message) PushButton(arg ...string) {
m.Push("action", _render(m, RENDER_BUTTON, strings.Join(arg, ",")))
}
func (m *Message) PushQRCode(key string, text string, arg ...string) { // text [size]
m.Push(key, _render(m, RENDER_QRCODE, text, arg))
}
func (m *Message) EchoAnchor(arg ...interface{}) *Message { // [name] link
return m.Echo(_render(m, RENDER_ANCHOR, arg...))
}
func (m *Message) EchoButton(arg ...string) *Message {
return m.Echo(_render(m, RENDER_BUTTON, strings.Join(arg, ",")))
}
func (m *Message) EchoQRCode(text string, arg ...string) *Message { // text [size]
return m.Echo(_render(m, RENDER_QRCODE, text, arg))
}
func (m *Message) EchoScript(text string, arg ...string) *Message {
if text == "break" {
return m.Echo("<br>")
}
mime := "shell"
if len(arg) > 0 {
mime, text = text, strings.Join(arg, "\n")
}
return m.Echo(_render(m, RENDER_SCRIPT, mime, text))
}
var count = int32(0)
func (m *Message) AddCmd(cmd *Command) string {

View File

@ -43,7 +43,7 @@ func init() {
m.Cmdy(mdb.SELECT, m.Prefix(SESS), "", mdb.HASH, kit.MDB_HASH, arg)
}},
web.LOGIN: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
web.WEB_LOGIN: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if f, _, e := m.R.FormFile(SUB); e == nil {
defer f.Close()
// 文件参数

View File

@ -19,7 +19,7 @@ func init() {
)},
},
Commands: map[string]*ice.Command{
web.LOGIN: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
web.WEB_LOGIN: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Render(ice.RENDER_RESULT)
}},
"/github.com/": {Name: "github.com", Help: "github.com", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {

View File

@ -390,7 +390,7 @@ var Index = &ice.Context{Name: LARK, Help: "机器人",
m.Echo(list[rand.Intn(len(list))])
}},
web.LOGIN: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
web.WEB_LOGIN: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
"/msg": {Name: "/msg", Help: "聊天消息", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) {
data := m.Optionv(ice.MSG_USERDATA)
if kit.Value(data, "action") != nil {

View File

@ -46,7 +46,7 @@ func init() {
m.Cmdy(mdb.SELECT, m.Prefix(SESS), "", mdb.HASH, kit.MDB_HASH, arg)
}},
web.LOGIN: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
web.WEB_LOGIN: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if f, _, e := m.R.FormFile(SUB); e == nil {
defer f.Close()
// 文件参数

View File

@ -173,7 +173,7 @@ var Index = &ice.Context{Name: WX, Help: "公众号",
"/login/": {Name: "/login/", Help: "认证", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
check := kit.Sort([]string{m.Conf(LOGIN, "meta.token"), m.Option("timestamp"), m.Option("nonce")})
if b := sha1.Sum([]byte(strings.Join(check, ""))); m.Warn(m.Option("signature") != hex.EncodeToString(b[:]), ice.ErrNotAuth) {
if b := sha1.Sum([]byte(strings.Join(check, ""))); m.Warn(m.Option("signature") != hex.EncodeToString(b[:]), ice.ErrNotRight) {
return // 验证失败
}
if m.Option("echostr") != "" {
@ -198,7 +198,7 @@ var Index = &ice.Context{Name: WX, Help: "公众号",
}
case "text":
if cmds := kit.Split(m.Option("Content")); m.Warn(!m.Right(cmds), ice.ErrNotAuth) {
if cmds := kit.Split(m.Option("Content")); m.Warn(!m.Right(cmds), ice.ErrNotRight) {
_wx_action(m.Cmdy("menu", mdb.CREATE))
break // 没有权限
} else {