1
0
forked from x/icebergs
This commit is contained in:
harveyshao 2022-12-11 20:18:08 +08:00
parent b791c5aa77
commit 3de5a53832
56 changed files with 566 additions and 634 deletions

View File

@ -18,6 +18,7 @@ const (
CENTOS = "centos" CENTOS = "centos"
ALPINE = "alpine" ALPINE = "alpine"
BUSYBOX = "busybox" BUSYBOX = "busybox"
RELEASE = "release"
) )
const MIRRORS = "mirrors" const MIRRORS = "mirrors"
@ -40,6 +41,7 @@ func init() {
} }
var _release = "" var _release = ""
func release(m *ice.Message) string { func release(m *ice.Message) string {
osid := runtime.GOOS osid := runtime.GOOS
if osid != "linux" { if osid != "linux" {
@ -71,4 +73,6 @@ func insert(m *ice.Message, sys, cmd string, arg ...string) bool {
func IsAlpine(m *ice.Message, arg ...string) bool { return insert(m, ALPINE, "system apk add", arg...) } func IsAlpine(m *ice.Message, arg ...string) bool { return insert(m, ALPINE, "system apk add", arg...) }
func IsCentos(m *ice.Message, arg ...string) bool { return insert(m, CENTOS, "yum install -y", arg...) } func IsCentos(m *ice.Message, arg ...string) bool { return insert(m, CENTOS, "yum install -y", arg...) }
func IsUbuntu(m *ice.Message, arg ...string) bool { return insert(m, UBUNTU, "apt get -y", arg...) } func IsUbuntu(m *ice.Message, arg ...string) bool { return insert(m, UBUNTU, "apt get -y", arg...) }
func IsSystem(m *ice.Message, arg ...string) bool { return IsAlpine(m, arg...) || IsCentos(m, arg...) || IsUbuntu(m, arg...) } func IsSystem(m *ice.Message, arg ...string) bool {
return IsAlpine(m, arg...) || IsCentos(m, arg...) || IsUbuntu(m, arg...)
}

View File

@ -11,6 +11,7 @@ import (
"shylinux.com/x/go-qrcode" "shylinux.com/x/go-qrcode"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
@ -76,7 +77,7 @@ func _qrcode_cli(m *ice.Message, text string) {
} }
m.Echo(ice.NL) m.Echo(ice.NL)
} }
m.Echo(text) m.Echo(text).Echo(ice.NL)
} }
func _qrcode_web(m *ice.Message, text string) { func _qrcode_web(m *ice.Message, text string) {
qr, _ := qrcode.New(text, qrcode.Medium) qr, _ := qrcode.New(text, qrcode.Medium)
@ -148,3 +149,12 @@ func Color(m *ice.Message, c string, str ice.Any) string {
func ColorRed(m *ice.Message, str ice.Any) string { return Color(m, RED, str) } func ColorRed(m *ice.Message, str ice.Any) string { return Color(m, RED, str) }
func ColorGreen(m *ice.Message, str ice.Any) string { return Color(m, GREEN, str) } func ColorGreen(m *ice.Message, str ice.Any) string { return Color(m, GREEN, str) }
func ColorYellow(m *ice.Message, str ice.Any) string { return Color(m, YELLOW, str) } func ColorYellow(m *ice.Message, str ice.Any) string { return Color(m, YELLOW, str) }
func PushText(m *ice.Message, text string) {
m.OptionFields(ice.MSG_DETAIL)
if m.PushScript(nfs.SCRIPT, text); strings.HasPrefix(text, ice.HTTP) {
m.PushQRCode(QRCODE, text)
m.PushAnchor(text)
}
m.Echo(text)
}

View File

@ -2,10 +2,11 @@ package log
import ( import (
"path" "path"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
) )
const ERROR = "error" const ERROR = "error"
func init() { func init() {

View File

@ -3,10 +3,10 @@ package log
import ( import (
"path" "path"
"strings" "strings"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )

View File

@ -220,6 +220,7 @@ func HashSelects(m *ice.Message, arg ...string) *ice.Message {
return HashSelect(m, arg...) return HashSelect(m, arg...)
} }
func HashSelectValue(m *ice.Message, cb Any) *ice.Message { func HashSelectValue(m *ice.Message, cb Any) *ice.Message {
m.OptionFields(m.Config(FIELD))
defer RLock(m, m.PrefixKey(), "")() defer RLock(m, m.PrefixKey(), "")()
Richs(m, m.PrefixKey(), nil, FOREACH, func(key string, value Map) { _mdb_select(m, cb, key, value, nil, nil) }) Richs(m, m.PrefixKey(), nil, FOREACH, func(key string, value Map) { _mdb_select(m, cb, key, value, nil, nil) })
return m return m

View File

@ -197,9 +197,14 @@ const (
CACHE_FIELD = "cache.field" CACHE_FIELD = "cache.field"
) )
func Grows(m *ice.Message, prefix string, chain Any, match string, value string, cb Any) Map { type Message interface {
cache := m.Confm(prefix, chain) Confv(arg ...Any) (val Any)
if cache == nil { Option(key string, arg ...Any) string
}
func Grows(m Message, prefix string, chain Any, match string, value string, cb Any) Map {
cache, ok := m.Confv(prefix, chain).(ice.Map)
if cache == nil || !ok {
return nil return nil
} }
limit := kit.Int(m.Option(CACHE_LIMIT)) limit := kit.Int(m.Option(CACHE_LIMIT))
@ -216,9 +221,9 @@ func Grows(m *ice.Message, prefix string, chain Any, match string, value string,
kit.Int(kit.Select("10", m.Option(CACHE_LIMIT))), kit.Int(kit.Select("10", m.Option(CACHE_LIMIT))),
match, value, cb) match, value, cb)
} }
func Grow(m *ice.Message, prefix string, chain Any, data Any) int { func Grow(m Message, prefix string, chain Any, data Any) int {
cache := m.Confm(prefix, chain) cache, ok := m.Confv(prefix, chain).(ice.Map)
if cache == nil { if cache == nil || !ok {
cache = kit.Data() cache = kit.Data()
m.Confv(prefix, chain, cache) m.Confv(prefix, chain, cache)
} }

View File

@ -25,7 +25,7 @@ func _zone_inputs(m *ice.Message, prefix, chain, zone string, field, value strin
func _zone_insert(m *ice.Message, prefix, chain, zone string, arg ...string) { func _zone_insert(m *ice.Message, prefix, chain, zone string, arg ...string) {
h := _hash_select_field(m, prefix, chain, zone, HASH) h := _hash_select_field(m, prefix, chain, zone, HASH)
if h == "" { if h == "" {
h = _hash_insert(m, prefix, chain, _mdb_getmeta(m, prefix, chain, SHORT), zone) h = _hash_insert(m, prefix, chain, kit.Select(ZONE, _mdb_getmeta(m, prefix, chain, SHORT)), zone)
} }
m.Assert(h != "") m.Assert(h != "")
defer Lock(m, prefix, chain)() defer Lock(m, prefix, chain)()
@ -193,7 +193,7 @@ func ZoneSelect(m *ice.Message, arg ...string) *ice.Message {
arg = kit.Slice(arg, 0, 2) arg = kit.Slice(arg, 0, 2)
m.Fields(len(arg), kit.Select(kit.Fields(TIME, m.Config(SHORT), COUNT), m.Config(FIELDS)), ZoneField(m)) m.Fields(len(arg), kit.Select(kit.Fields(TIME, m.Config(SHORT), COUNT), m.Config(FIELDS)), ZoneField(m))
if m.Cmdy(SELECT, m.PrefixKey(), "", ZONE, arg, logs.FileLineMeta(-1)); len(arg) == 0 { if m.Cmdy(SELECT, m.PrefixKey(), "", ZONE, arg, logs.FileLineMeta(-1)); len(arg) == 0 {
m.Sort(ZoneShort(m)).StatusTimeCount().PushAction(m.Config(ACTION), REMOVE) m.StatusTimeCount().PushAction(m.Config(ACTION), REMOVE).Sort(ZoneShort(m))
} else if len(arg) == 1 { } else if len(arg) == 1 {
m.StatusTimeCountTotal(_mdb_getmeta(m, "", kit.Keys(HASH, HashSelectField(m, arg[0], HASH)), COUNT)) m.StatusTimeCountTotal(_mdb_getmeta(m, "", kit.Keys(HASH, HashSelectField(m, arg[0], HASH)), COUNT))
} }

View File

@ -80,19 +80,19 @@ func StatFile(m Message, p string) (os.FileInfo, error) {
func OpenFile(m Message, p string) (io.ReadCloser, error) { func OpenFile(m Message, p string) (io.ReadCloser, error) {
return OptionFiles(m).OpenFile(p) return OptionFiles(m).OpenFile(p)
} }
func CreateFile(m *ice.Message, p string) (io.WriteCloser, string, error) { func CreateFile(m Message, p string) (io.WriteCloser, string, error) {
return OptionFiles(m).CreateFile(p) return OptionFiles(m).CreateFile(p)
} }
func AppendFile(m *ice.Message, p string) (io.ReadWriteCloser, string, error) { func AppendFile(m Message, p string) (io.ReadWriteCloser, string, error) {
file := OptionFiles(m) file := OptionFiles(m)
w, e := file.AppendFile(p) w, e := file.AppendFile(p)
return w, p, e return w, p, e
} }
func WriteFile(m *ice.Message, p string, b []byte) error { func WriteFile(m Message, p string, b []byte) error {
return OptionFiles(m).WriteFile(p, b) return OptionFiles(m).WriteFile(p, b)
} }
func ReadDir(m *ice.Message, p string) ([]os.FileInfo, error) { func ReadDir(m Message, p string) ([]os.FileInfo, error) {
list, e := OptionFiles(m).ReadDir(p) list, e := OptionFiles(m).ReadDir(p)
for i := 0; i < len(list)-1; i++ { for i := 0; i < len(list)-1; i++ {
for j := i + 1; j < len(list); j++ { for j := i + 1; j < len(list); j++ {
@ -103,23 +103,23 @@ func ReadDir(m *ice.Message, p string) ([]os.FileInfo, error) {
} }
return list, e return list, e
} }
func MkdirAll(m *ice.Message, p string) error { func MkdirAll(m Message, p string) error {
return OptionFiles(m).MkdirAll(p, ice.MOD_DIR) return OptionFiles(m).MkdirAll(p, ice.MOD_DIR)
} }
func RemoveAll(m *ice.Message, p string) error { func RemoveAll(m Message, p string) error {
return OptionFiles(m).RemoveAll(p) return OptionFiles(m).RemoveAll(p)
} }
func Remove(m *ice.Message, p string) error { func Remove(m Message, p string) error {
return OptionFiles(m).Remove(p) return OptionFiles(m).Remove(p)
} }
func Rename(m *ice.Message, oldname string, newname string) error { func Rename(m Message, oldname string, newname string) error {
MkdirAll(m, path.Dir(newname)) MkdirAll(m, path.Dir(newname))
return OptionFiles(m).Rename(oldname, newname) return OptionFiles(m).Rename(oldname, newname)
} }
func Symlink(m *ice.Message, oldname string, newname string) error { func Symlink(m Message, oldname string, newname string) error {
return OptionFiles(m).Symlink(oldname, newname) return OptionFiles(m).Symlink(oldname, newname)
} }
func Link(m *ice.Message, oldname string, newname string) error { func Link(m Message, oldname string, newname string) error {
return OptionFiles(m).Link(oldname, newname) return OptionFiles(m).Link(oldname, newname)
} }
@ -133,7 +133,7 @@ func ExistsFile(m Message, p string) bool {
} }
return false return false
} }
func ReadFile(m *ice.Message, p string) ([]byte, error) { func ReadFile(m Message, p string) ([]byte, error) {
if f, e := OptionFiles(m).OpenFile(p); e == nil { if f, e := OptionFiles(m).OpenFile(p); e == nil {
defer f.Close() defer f.Close()
return ioutil.ReadAll(f) return ioutil.ReadAll(f)
@ -141,7 +141,7 @@ func ReadFile(m *ice.Message, p string) ([]byte, error) {
return nil, e return nil, e
} }
} }
func CloseFile(m *ice.Message, p ice.Any) { func CloseFile(m Message, p ice.Any) {
if w, ok := p.(io.Closer); ok { if w, ok := p.(io.Closer); ok {
w.Close() w.Close()
} }

View File

@ -72,8 +72,8 @@ func init() {
} }
}}, }},
PUBLISH: {Hand: func(m *ice.Message, arg ...string) { PUBLISH: {Hand: func(m *ice.Message, arg ...string) {
if strings.Contains(arg[0], "://"+LOCALHOST) { if strings.Contains(arg[0], LOCALHOST) {
arg[0] = strings.Replace(arg[0], "://"+LOCALHOST, "://"+m.Cmd("").Append(aaa.IP), 1) arg[0] = strings.Replace(arg[0], LOCALHOST, m.Cmd("").Append(aaa.IP), 1)
} }
m.Echo(arg[0]) m.Echo(arg[0])
}}, }},

View File

@ -171,6 +171,13 @@ func init() {
}) })
ctx.Upload = Upload ctx.Upload = Upload
} }
func RenderCache(m *ice.Message, h string) {
if msg := m.Cmd(CACHE, h); msg.Append(nfs.FILE) == "" {
m.RenderResult(msg.Append(mdb.TEXT))
} else {
m.RenderDownload(msg.Append(mdb.FILE), msg.Append(mdb.TYPE), msg.Append(mdb.NAME))
}
}
func Upload(m *ice.Message) []string { func Upload(m *ice.Message) []string {
if up := kit.Simple(m.Optionv(ice.MSG_UPLOAD)); len(up) == 1 { if up := kit.Simple(m.Optionv(ice.MSG_UPLOAD)); len(up) == 1 {
if m.Cmdy(CACHE, UPLOAD).Optionv(ice.MSG_UPLOAD, kit.Simple(m.Append(mdb.HASH), m.Append(mdb.NAME), m.Append(nfs.SIZE))); m.Option(ice.MSG_USERPOD) != "" { if m.Cmdy(CACHE, UPLOAD).Optionv(ice.MSG_UPLOAD, kit.Simple(m.Append(mdb.HASH), m.Append(mdb.NAME), m.Append(nfs.SIZE))); m.Option(ice.MSG_USERPOD) != "" {

View File

@ -31,11 +31,15 @@ const (
func Render(m *ice.Message, cmd string, args ...ice.Any) bool { func Render(m *ice.Message, cmd string, args ...ice.Any) bool {
if cmd == ice.RENDER_VOID { if cmd == ice.RENDER_VOID {
return true return true
} else if cmd != "" {
defer func() { m.Logs(mdb.EXPORT, cmd, args) }()
} }
arg := kit.Simple(args...)
switch arg := kit.Simple(args...); cmd { if len(arg) == 0 {
args = nil
}
if cmd != "" {
defer func() { m.Logs("Render", cmd, args) }()
}
switch cmd {
case COOKIE: // value [name [path [expire]]] case COOKIE: // value [name [path [expire]]]
RenderCookie(m, arg[0], arg[1:]...) RenderCookie(m, arg[0], arg[1:]...)
@ -63,7 +67,9 @@ func Render(m *ice.Message, cmd string, args ...ice.Any) bool {
if len(arg) > 0 { // [str [arg...]] if len(arg) > 0 { // [str [arg...]]
m.W.Write([]byte(kit.Format(arg[0], args[1:]...))) m.W.Write([]byte(kit.Format(arg[0], args[1:]...)))
} else { } else {
args = append(args, nfs.SIZE, len(m.Result())) if m.Result() == "" && m.Length() > 0 {
m.Table()
}
m.W.Write([]byte(m.Result())) m.W.Write([]byte(m.Result()))
} }

View File

@ -58,9 +58,12 @@ func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool {
if m.Logs(r.Header.Get(ice.MSG_USERIP), r.Method, r.URL.String()); m.Config(LOGHEADERS) == ice.TRUE { if m.Logs(r.Header.Get(ice.MSG_USERIP), r.Method, r.URL.String()); m.Config(LOGHEADERS) == ice.TRUE {
kit.Fetch(r.Header, func(k string, v []string) { m.Logs("Header", k, v) }) kit.Fetch(r.Header, func(k string, v []string) { m.Logs("Header", k, v) })
} }
if r.Method == http.MethodGet && r.URL.Path != PP(SPACE) { if r.Method == http.MethodGet && r.URL.Path != PP(SPACE) && !strings.HasPrefix(r.URL.Path, "/code/bash") {
repos := kit.Select(ice.INTSHELL, ice.VOLCANOS, strings.Contains(r.Header.Get(UserAgent), MOZILLA)) repos := kit.Select(ice.INTSHELL, ice.VOLCANOS, strings.Contains(r.Header.Get(UserAgent), MOZILLA))
if msg := gdb.Event(m.Spawn(w, r), SERVE_REWRITE, r.Method, r.URL.Path, path.Join(m.Conf(SERVE, kit.Keym(repos, nfs.PATH)), r.URL.Path), repos); msg.Option(ice.MSG_OUTPUT) != "" { if p := path.Join(ice.USR, repos, r.URL.Path); r.URL.Path != ice.PS && nfs.ExistsFile(m, p) {
Render(m.Spawn(w, r), ice.RENDER_DOWNLOAD, p)
return false
} else if msg := gdb.Event(m.Spawn(w, r), SERVE_REWRITE, r.Method, r.URL.Path, path.Join(m.Conf(SERVE, kit.Keym(repos, nfs.PATH)), r.URL.Path), repos); msg.Option(ice.MSG_OUTPUT) != "" {
Render(msg, msg.Option(ice.MSG_OUTPUT), kit.List(msg.Optionv(ice.MSG_ARGS))...) Render(msg, msg.Option(ice.MSG_OUTPUT), kit.List(msg.Optionv(ice.MSG_ARGS))...)
return false return false
} }
@ -73,9 +76,7 @@ func _serve_handle(key string, cmd *ice.Command, m *ice.Message, w http.Response
kit.Fetch(u.Query(), func(k string, v []string) { m.Logs("Refer", k, v).Optionv(k, v) }) kit.Fetch(u.Query(), func(k string, v []string) { m.Logs("Refer", k, v).Optionv(k, v) })
} }
for k, v := range kit.ParseQuery(r.URL.RawQuery) { for k, v := range kit.ParseQuery(r.URL.RawQuery) {
if m.IsCliUA() { kit.If(m.IsCliUA(), func() { v = kit.Simple(v, func(v string) (string, error) { return url.QueryUnescape(v) }) })
v = kit.Simple(v, func(v string) (string, error) { return url.QueryUnescape(v) })
}
m.Optionv(k, v) m.Optionv(k, v)
} }
switch r.Header.Get(ContentType) { switch r.Header.Get(ContentType) {
@ -85,7 +86,10 @@ func _serve_handle(key string, cmd *ice.Command, m *ice.Message, w http.Response
kit.Fetch(data, func(k string, v ice.Any) { m.Optionv(k, v) }) kit.Fetch(data, func(k string, v ice.Any) { m.Optionv(k, v) })
default: default:
r.ParseMultipartForm(kit.Int64(kit.Select("4096", r.Header.Get(ContentLength)))) r.ParseMultipartForm(kit.Int64(kit.Select("4096", r.Header.Get(ContentLength))))
kit.Fetch(r.PostForm, func(k string, v []string) { m.Logs("Form", k, kit.Join(v, ice.SP)).Optionv(k, v) }) kit.Fetch(r.PostForm, func(k string, v []string) {
kit.If(m.IsCliUA(), func() { v = kit.Simple(v, func(v string) (string, error) { return url.QueryUnescape(v) }) })
m.Logs("Form", k, kit.Join(v, ice.SP)).Optionv(k, v)
})
} }
kit.Fetch(r.Cookies(), func(k, v string) { m.Optionv(k, v) }) kit.Fetch(r.Cookies(), func(k, v string) { m.Optionv(k, v) })
m.OptionDefault(ice.HEIGHT, "480", ice.WIDTH, "320") m.OptionDefault(ice.HEIGHT, "480", ice.WIDTH, "320")
@ -95,6 +99,8 @@ func _serve_handle(key string, cmd *ice.Command, m *ice.Message, w http.Response
if m.Option(ice.MSG_USERWEB, _serve_domain(m)); m.Option(ice.POD) != "" { if m.Option(ice.MSG_USERWEB, _serve_domain(m)); m.Option(ice.POD) != "" {
m.Option(ice.MSG_USERPOD, m.Option(ice.POD)) m.Option(ice.MSG_USERPOD, m.Option(ice.POD))
} }
u := OptionUserWeb(m)
m.Option(ice.MSG_USERHOST, u.Scheme+"//"+u.Host)
m.Option(ice.MSG_SESSID, m.Option(CookieName(m.Option(ice.MSG_USERWEB)))) m.Option(ice.MSG_SESSID, m.Option(CookieName(m.Option(ice.MSG_USERWEB))))
if m.Optionv(ice.MSG_CMDS) == nil { if m.Optionv(ice.MSG_CMDS) == nil {
if p := strings.TrimPrefix(r.URL.Path, key); p != "" { if p := strings.TrimPrefix(r.URL.Path, key); p != "" {
@ -121,7 +127,7 @@ func _serve_domain(m *ice.Message) string {
) )
} }
func _serve_login(m *ice.Message, key string, cmds []string, w http.ResponseWriter, r *http.Request) ([]string, bool) { func _serve_login(m *ice.Message, key string, cmds []string, w http.ResponseWriter, r *http.Request) ([]string, bool) {
if aaa.SessCheck(m, m.Option(ice.MSG_SESSID)); m.Option(ice.MSG_USERNAME) == "" && r.URL.Path != PP(SPACE) { if aaa.SessCheck(m, m.Option(ice.MSG_SESSID)); m.Option(ice.MSG_USERNAME) == "" && r.URL.Path != PP(SPACE) && !strings.HasPrefix(r.URL.Path, "/sync") {
gdb.Event(m, SERVE_LOGIN) gdb.Event(m, SERVE_LOGIN)
} }
if _, ok := m.Target().Commands[WEB_LOGIN]; ok { if _, ok := m.Target().Commands[WEB_LOGIN]; ok {

View File

@ -99,7 +99,7 @@ func init() {
ice.Index.Register(Index, &Frame{}, BROAD, SERVE, SPACE, DREAM, SHARE, CACHE, SPIDE) ice.Index.Register(Index, &Frame{}, BROAD, SERVE, SPACE, DREAM, SHARE, CACHE, SPIDE)
} }
func ApiAction(arg ...string) ice.Actions { return ice.Actions{kit.Select(ice.PS, arg, 0): {}} } func ApiAction(arg ...string) ice.Actions { return ice.Actions{kit.Select(ice.PS, arg, 0): {}} }
func Prefix(arg ...string) string { return kit.Keys(WEB, arg) } func Prefix(arg ...string) string { return kit.Keys(WEB, arg) }
func P(arg ...string) string { return path.Join(ice.PS, path.Join(arg...)) } func P(arg ...string) string { return path.Join(ice.PS, path.Join(arg...)) }
func PP(arg ...string) string { return P(arg...) + ice.PS } func PP(arg ...string) string { return P(arg...) + ice.PS }

View File

@ -189,6 +189,7 @@ const ( // MSG
MSG_USERNICK = "user.nick" MSG_USERNICK = "user.nick"
MSG_USERZONE = "user.zone" MSG_USERZONE = "user.zone"
MSG_LANGUAGE = "user.lang" MSG_LANGUAGE = "user.lang"
MSG_USERHOST = "user.host"
MSG_TITLE = "sess.title" MSG_TITLE = "sess.title"
MSG_TOPIC = "sess.topic" MSG_TOPIC = "sess.topic"

View File

@ -27,7 +27,7 @@ func _action_exec(m *ice.Message, river, storm, index string, arg ...string) {
} }
func _action_auth(m *ice.Message, share string) *ice.Message { func _action_auth(m *ice.Message, share string) *ice.Message {
msg := m.Cmd(web.SHARE, share) msg := m.Cmd(web.SHARE, share)
if web.IsNotValidShare(m, msg.Append(mdb.TIME)) { if web.IsNotValidShare(m, msg.Append(mdb.TIME)) {
msg.Append(mdb.TYPE, "") msg.Append(mdb.TYPE, "")
return msg return msg
} }

View File

@ -137,4 +137,4 @@ var _binpack_template_end = `
} }
} }
} }
` `

View File

@ -58,7 +58,7 @@ func _css_show(m *ice.Message, arg ...string) {
} }
func _css_exec(m *ice.Message, arg ...string) { func _css_exec(m *ice.Message, arg ...string) {
if arg[2] == ice.USR_VOLCANOS && strings.HasPrefix(arg[1], ice.PLUGIN_LOCAL) { if arg[2] == ice.USR_VOLCANOS && strings.HasPrefix(arg[1], ice.PLUGIN_LOCAL) {
key := ctx.GetFileCmd("/require/shylinux.com/x/icebergs/core/"+strings.TrimPrefix(arg[1], ice.PLUGIN_LOCAL)) key := ctx.GetFileCmd("/require/shylinux.com/x/icebergs/core/" + strings.TrimPrefix(arg[1], ice.PLUGIN_LOCAL))
ctx.ProcessCommand(m, kit.Select("can.plugin", key), kit.Simple()) ctx.ProcessCommand(m, kit.Select("can.plugin", key), kit.Simple())
return return
} }

View File

@ -21,11 +21,10 @@ func _install_path(m *ice.Message, link string) string {
link = kit.Select(m.Option(mdb.LINK), link) link = kit.Select(m.Option(mdb.LINK), link)
if p := path.Join(ice.USR_INSTALL, kit.TrimExt(link)); nfs.ExistsFile(m, p) { if p := path.Join(ice.USR_INSTALL, kit.TrimExt(link)); nfs.ExistsFile(m, p) {
return p return p
} else if p := path.Join(ice.USR_INSTALL, path.Base(link)); nfs.ExistsFile(m, p) { } else if pp := path.Join(ice.USR_INSTALL, path.Base(link)); nfs.ExistsFile(m, pp) {
return path.Join(ice.USR_INSTALL, strings.Split(m.Cmd(nfs.TAR, p, "", "1").Append(nfs.FILE), ice.PS)[0]) return path.Join(ice.USR_INSTALL, strings.Split(m.Cmd(nfs.TAR, pp, "", "1").Append(nfs.FILE), ice.PS)[0])
} else { } else {
m.Assert(true) return p
return ""
} }
} }
func _install_download(m *ice.Message) { func _install_download(m *ice.Message) {

View File

@ -45,6 +45,15 @@ func _publish_bin_list(m *ice.Message, dir string) {
} }
m.SortTimeR(mdb.TIME) m.SortTimeR(mdb.TIME)
} }
func PublishScript(m *ice.Message, arg ...string) {
u := web.OptionUserWeb(m)
host := tcp.PublishLocalhost(m, strings.Split(u.Host, ice.DF)[0])
m.Option(cli.CTX_ENV, kit.Select("", ice.SP+kit.JoinKV(ice.EQ, ice.SP, cli.CTX_POD, m.Option(ice.MSG_USERPOD)), m.Option(ice.MSG_USERPOD) != ""))
m.Option("httphost", fmt.Sprintf("%s://%s:%s", u.Scheme, host, kit.Select(kit.Select("443", "80", u.Scheme == ice.HTTP), strings.Split(u.Host, ice.DF), 1)))
for _, v := range arg {
m.EchoScript(kit.Renders(v, m))
}
}
func _publish_contexts(m *ice.Message, arg ...string) { func _publish_contexts(m *ice.Message, arg ...string) {
u := web.OptionUserWeb(m) u := web.OptionUserWeb(m)
host := tcp.PublishLocalhost(m, strings.Split(u.Host, ice.DF)[0]) host := tcp.PublishLocalhost(m, strings.Split(u.Host, ice.DF)[0])
@ -75,7 +84,7 @@ const PUBLISH = "publish"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
PUBLISH: {Name: "publish path auto create volcanos icebergs intshell", Help: "发布", Actions: ice.MergeActions(ice.Actions{ PUBLISH: {Name: "publish path auto create volcanos icebergs intshell", Help: "发布", Actions: ice.MergeActions(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { m.Config(ice.CONTEXTS, _contexts) }}, ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { m.Config(ice.CONTEXTS, _contexts) }},
web.SERVE_START: {Hand: func(m *ice.Message, arg ...string) { _publish_file(m, ice.ICE_BIN) }}, web.SERVE_START: {Hand: func(m *ice.Message, arg ...string) { _publish_file(m, ice.ICE_BIN) }},
ice.VOLCANOS: {Help: "火山架", Hand: func(m *ice.Message, arg ...string) { ice.VOLCANOS: {Help: "火山架", Hand: func(m *ice.Message, arg ...string) {
defer func() { m.EchoQRCode(m.Option(ice.MSG_USERWEB)) }() defer func() { m.EchoQRCode(m.Option(ice.MSG_USERWEB)) }()
@ -91,9 +100,9 @@ func init() {
_publish_list(m, kit.ExtReg(`(sh|vim|conf)`)) _publish_list(m, kit.ExtReg(`(sh|vim|conf)`))
}}, }},
ice.CONTEXTS: {Hand: func(m *ice.Message, arg ...string) { _publish_contexts(m, arg...) }}, ice.CONTEXTS: {Hand: func(m *ice.Message, arg ...string) { _publish_contexts(m, arg...) }},
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(nfs.DIR, arg[1:]).Cut("path,size,time").ProcessAgain() }}, mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(nfs.DIR, arg[1:]).Cut("path,size,time").ProcessAgain() }},
mdb.CREATE: {Name: "create file", Help: "添加", Hand: func(m *ice.Message, arg ...string) { _publish_file(m, m.Option(nfs.FILE)) }}, mdb.CREATE: {Name: "create file", Help: "添加", Hand: func(m *ice.Message, arg ...string) { _publish_file(m, m.Option(nfs.FILE)) }},
nfs.TRASH: {Hand: func(m *ice.Message, arg ...string) { nfs.Trash(m, path.Join(ice.USR_PUBLISH, m.Option(nfs.PATH))) }}, nfs.TRASH: {Hand: func(m *ice.Message, arg ...string) { nfs.Trash(m, path.Join(ice.USR_PUBLISH, m.Option(nfs.PATH))) }},
}, ctx.ConfAction(ice.CONTEXTS, _contexts), aaa.RoleAction()), Hand: func(m *ice.Message, arg ...string) { }, ctx.ConfAction(ice.CONTEXTS, _contexts), aaa.RoleAction()), Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(nfs.DIR, kit.Select("", arg, 0), nfs.DIR_WEB_FIELDS, kit.Dict(nfs.DIR_ROOT, ice.USR_PUBLISH)).SortTimeR(mdb.TIME) m.Cmdy(nfs.DIR, kit.Select("", arg, 0), nfs.DIR_WEB_FIELDS, kit.Dict(nfs.DIR_ROOT, ice.USR_PUBLISH)).SortTimeR(mdb.TIME)
}}, }},

View File

@ -17,9 +17,11 @@ const SHY = "shy"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
SHY: {Name: "shy path auto", Help: "脚本", Actions: ice.MergeActions(ice.Actions{ SHY: {Name: "shy path auto", Help: "脚本", Actions: ice.MergeActions(ice.Actions{
mdb.RENDER: {Hand: func(m *ice.Message, arg ...string) { ctx.ProcessCommand(m, web.WIKI_WORD, kit.Simple(path.Join(arg[2], arg[1]))) }}, mdb.RENDER: {Hand: func(m *ice.Message, arg ...string) {
ctx.ProcessCommand(m, web.WIKI_WORD, kit.Simple(path.Join(arg[2], arg[1])))
}},
mdb.ENGINE: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(ssh.SOURCE, path.Join(arg[2], arg[1])) }}, mdb.ENGINE: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(ssh.SOURCE, path.Join(arg[2], arg[1])) }},
TEMPLATE: {Hand: func(m *ice.Message, arg ...string) { m.Echo(`chapter "hi"`) }}, TEMPLATE: {Hand: func(m *ice.Message, arg ...string) { m.Echo(`chapter "hi"`) }},
}, PlugAction()), Hand: func(m *ice.Message, arg ...string) { }, PlugAction()), Hand: func(m *ice.Message, arg ...string) {
if len(arg) > 0 && kit.Ext(arg[0]) == m.CommandKey() { if len(arg) > 0 && kit.Ext(arg[0]) == m.CommandKey() {
m.Cmdy(web.WIKI_WORD, path.Join(ice.SRC, strings.TrimPrefix(arg[0], "src/"))) m.Cmdy(web.WIKI_WORD, path.Join(ice.SRC, strings.TrimPrefix(arg[0], "src/")))

View File

@ -15,8 +15,12 @@ import (
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
func _volcanos(m *ice.Message, file ...string) string { return path.Join(ice.USR_VOLCANOS, path.Join(file...)) } func _volcanos(m *ice.Message, file ...string) string {
func _publish(m *ice.Message, file ...string) string { return path.Join(ice.USR_PUBLISH, path.Join(file...)) } return path.Join(ice.USR_VOLCANOS, path.Join(file...))
}
func _publish(m *ice.Message, file ...string) string {
return path.Join(ice.USR_PUBLISH, path.Join(file...))
}
func _webpack_can(m *ice.Message) { func _webpack_can(m *ice.Message) {
m.Option(nfs.DIR_ROOT, "") m.Option(nfs.DIR_ROOT, "")
m.Cmd(nfs.COPY, _volcanos(m, PAGE_CAN_CSS), _volcanos(m, PAGE_INDEX_CSS), _volcanos(m, PAGE_CACHE_CSS)) m.Cmd(nfs.COPY, _volcanos(m, PAGE_CAN_CSS), _volcanos(m, PAGE_INDEX_CSS), _volcanos(m, PAGE_CACHE_CSS))
@ -162,4 +166,4 @@ var _webpack_template = `
<script>%s</script> <script>%s</script>
<script>%s</script> <script>%s</script>
</body> </body>
` `

View File

@ -78,6 +78,7 @@ func init() {
FEEL, DRAW, DATA, WORD, FEEL, DRAW, DATA, WORD,
) )
} }
func Prefix(arg ...string) string { return web.Prefix(WIKI, kit.Keys(arg)) }
func WikiAction(dir string, ext ...string) ice.Actions { func WikiAction(dir string, ext ...string) ice.Actions {
return ice.Actions{ice.CTX_INIT: mdb.AutoConfig(nfs.PATH, dir, lex.REGEXP, kit.FileReg(ext...)), return ice.Actions{ice.CTX_INIT: mdb.AutoConfig(nfs.PATH, dir, lex.REGEXP, kit.FileReg(ext...)),

View File

@ -37,7 +37,7 @@ func (m *Message) join(arg ...Any) (string, []Any) {
case time.Time: case time.Time:
arg[i+1] = v.Format(MOD_TIME) arg[i+1] = v.Format(MOD_TIME)
case []string: case []string:
arg[i+1] = kit.Join(v, " ") arg[i+1] = kit.Join(v, SP)
} }
list = append(list, key+kit.Select("", DF, !strings.Contains(key, DF)), kit.Format(arg[i+1])) list = append(list, key+kit.Select("", DF, !strings.Contains(key, DF)), kit.Format(arg[i+1]))
} }

View File

@ -507,3 +507,6 @@ func (m *Message) Result(arg ...Any) string {
} }
return strings.Join(m.Resultv(arg...), "") return strings.Join(m.Resultv(arg...), "")
} }
func (m *Message) Results(arg ...Any) string {
return kit.Select("", strings.TrimSpace(m.Result()), !m.IsErr())
}

View File

@ -105,7 +105,7 @@ func (m *Message) RenameAppend(arg ...string) *Message {
func (m *Message) AppendSimple(key ...string) (res []string) { func (m *Message) AppendSimple(key ...string) (res []string) {
if len(key) == 0 { if len(key) == 0 {
if m.FieldsIsDetail() { if m.FieldsIsDetail() {
key = append(key, m.Appendv(KEY)...) key = append(key, m.meta[KEY]...)
} else { } else {
key = append(key, m.Appendv(MSG_APPEND)...) key = append(key, m.Appendv(MSG_APPEND)...)
} }
@ -173,7 +173,7 @@ func (m *Message) _fileline() string {
} }
} }
func (m *Message) ActionHand(cmd *Command, key, sub string, arg ...string) *Message { func (m *Message) ActionHand(cmd *Command, key, sub string, arg ...string) *Message {
if action, ok := cmd.Actions[sub]; !m.Warn(!ok, ErrNotFound, sub, cmd.GetFileLines()) { if action, ok := cmd.Actions[sub]; !m.Warn(!ok, ErrNotFound, sub, cmd.GetFileLine()) {
return m.Target()._action(m, cmd, key, sub, action, arg...) return m.Target()._action(m, cmd, key, sub, action, arg...)
} }
return m return m

View File

@ -20,62 +20,43 @@ const (
type alpha struct { type alpha struct {
ice.Zone ice.Zone
field string `data:"word,translation,definition"` field string `data:"word,translation,definition"`
store string `data:"usr/local/export"` store string `data:"usr/local/export/"`
fsize string `data:"300000"` fsize string `data:"300000"`
limit string `data:"50000"` limit string `data:"50000"`
least string `data:"1000"` least string `data:"1000"`
load string `name:"load file=usr/word-dict/ecdict zone=ecdict"`
load string `name:"load file=usr/word-dict/ecdict name=ecdict" help:"加载"` list string `name:"list method=word,line word auto load" help:"词典"`
list string `name:"list method=word,line word auto" help:"词典"`
} }
func (s alpha) Load(m *ice.Message, arg ...string) { func (s alpha) Load(m *ice.Message, arg ...string) {
// 清空数据
lib := kit.Select(path.Base(m.Option(nfs.FILE)), m.Option(mdb.ZONE)) lib := kit.Select(path.Base(m.Option(nfs.FILE)), m.Option(mdb.ZONE))
m.Assert(nfs.RemoveAll(m.Message, path.Join(m.Config(mdb.STORE), lib))) m.Assert(nfs.RemoveAll(m, path.Join(m.Config(mdb.STORE), lib)))
s.Zone.Remove(m, mdb.ZONE, lib) s.Zone.Remove(m, mdb.ZONE, lib)
s.Zone.Create(m, kit.Simple(mdb.ZONE, lib, m.ConfigSimple(mdb.FIELD, mdb.LIMIT, mdb.LEAST, mdb.STORE, mdb.FSIZE))...) s.Zone.Create(m, kit.Simple(mdb.ZONE, lib, m.ConfigSimple(mdb.FIELD, mdb.LIMIT, mdb.LEAST, mdb.STORE, mdb.FSIZE))...)
prefix := kit.Keys(mdb.HASH, m.Result()) prefix := kit.Keys(mdb.HASH, m.Result())
// 加载配置
m.Cmd(mdb.IMPORT, m.PrefixKey(), prefix, mdb.LIST, m.Option(nfs.FILE)) m.Cmd(mdb.IMPORT, m.PrefixKey(), prefix, mdb.LIST, m.Option(nfs.FILE))
// 保存词库
m.Conf(m.PrefixKey(), kit.Keys(prefix, kit.Keym(mdb.LIMIT)), 0) m.Conf(m.PrefixKey(), kit.Keys(prefix, kit.Keym(mdb.LIMIT)), 0)
m.Conf(m.PrefixKey(), kit.Keys(prefix, kit.Keym(mdb.LEAST)), 0) m.Conf(m.PrefixKey(), kit.Keys(prefix, kit.Keym(mdb.LEAST)), 0)
m.Echo("%s: %d", lib, mdb.Grow(m.Message, m.PrefixKey(), prefix, kit.Dict(WORD, ice.SP))) m.Echo("%s: %d", lib, mdb.Grow(m, m.PrefixKey(), prefix, kit.Dict(WORD, ice.SP)))
} }
func (s alpha) List(m *ice.Message, arg ...string) { func (s alpha) List(m *ice.Message, arg ...string) {
if len(arg) < 2 || arg[1] == "" { if len(arg) < 2 || arg[1] == "" {
m.Cmdy(cache{}, kit.Slice(arg, 1)) m.Cmdy(cache{}, kit.Slice(arg, 1))
return // 缓存列表 return
} }
switch arg[1] = strings.TrimSpace(arg[1]); arg[0] { switch arg[1] = strings.TrimSpace(arg[1]); arg[0] {
case LINE: case LINE:
case WORD: case WORD:
if m.Cmdy(cache{}, kit.Slice(arg, 1)); m.Length() > 0 { if m.Cmdy(cache{}, kit.Slice(arg, 1)); m.Length() > 0 {
return // 查询缓存 return
} }
defer func() { defer func() { kit.If(m.Length() > 0, func() { m.Cmd(cache{}, mdb.CREATE, m.AppendSimple()) }) }()
if m.Length() > 0 { // 写入缓存
m.Cmd(cache{}, mdb.CREATE, m.AppendSimple())
}
}()
// 精确匹配
m.OptionFields(ice.FIELDS_DETAIL) m.OptionFields(ice.FIELDS_DETAIL)
arg[1] = "^" + arg[1] + ice.FS arg[1] = "^" + arg[1] + ice.FS
} }
wiki.CSV(m.Message.Spawn(), m.Cmdx(cli.SYSTEM, "grep", "-rih", arg[1], m.Config(mdb.STORE)), kit.Split(m.Config(mdb.FIELD))...).Tables(func(value ice.Maps) {
// 搜索词汇 kit.If(m.FieldsIsDetail(), func() { m.PushDetail(value, m.Config(mdb.FIELD)) }, func() { m.PushRecord(value, m.Config(mdb.FIELD)) })
wiki.CSV(m.Message, m.Cmdx(cli.SYSTEM, "grep", "-rih", arg[1], m.Config(mdb.STORE)), kit.Split(m.Config(mdb.FIELD))...).Tables(func(value ice.Maps) {
if m.FieldsIsDetail() {
m.PushDetail(value, m.Config(mdb.FIELD))
} else {
m.PushRecord(value, m.Config(mdb.FIELD))
}
}).StatusTimeCount() }).StatusTimeCount()
} }
func init() { ice.Cmd("web.wiki.alpha.alpha", alpha{}) } func init() { ice.WikiCtxCmd(alpha{}) }

View File

@ -1,3 +0,0 @@
chapter "alpha"
field web.wiki.alpha.alpha

View File

@ -11,4 +11,4 @@ type cache struct {
list string `name:"list word auto create prunes" help:"缓存"` list string `name:"list word auto create prunes" help:"缓存"`
} }
func init() { ice.Cmd("web.wiki.alpha.cache", cache{}) } func init() { ice.WikiCtxCmd(cache{}) }

View File

@ -12,11 +12,11 @@ const BASH = "bash"
var Index = &ice.Context{Name: BASH, Help: "命令行", Commands: ice.Commands{ var Index = &ice.Context{Name: BASH, Help: "命令行", Commands: ice.Commands{
BASH: {Name: "bash path auto order build download", Help: "命令行", Actions: ice.MergeActions(ice.Actions{ BASH: {Name: "bash path auto order build download", Help: "命令行", Actions: ice.MergeActions(ice.Actions{
cli.ORDER: {Name: "order", Help: "加载", Hand: func(m *ice.Message, arg ...string) { cli.ORDER: {Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(code.INSTALL, cli.ORDER, m.Config(nfs.SOURCE), "_install/bin") m.Cmdy(code.INSTALL, cli.ORDER, m.Config(nfs.SOURCE), "_install/bin")
}}, }},
}, code.InstallAction(nfs.SOURCE, "http://mirrors.tencent.com/macports/distfiles/bash/5.1_1/bash-5.1.tar.gz")), Hand: func(m *ice.Message, arg ...string) { }, code.InstallAction(nfs.SOURCE, "http://mirrors.tencent.com/macports/distfiles/bash/5.1_1/bash-5.1.tar.gz")), Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(code.INSTALL, nfs.SOURCE, m.Config(nfs.SOURCE), arg) m.Cmdy(code.INSTALL, m.ConfigSimple(nfs.SOURCE), arg)
}}, }},
}} }}

View File

@ -28,7 +28,6 @@ cd ./_install
` `
chapter "应用" chapter "应用"
field "文件夹" web.chat.files
field "命令行" web.code.bash.bash field "命令行" web.code.bash.bash
field "会话流" web.code.bash.sess field "会话流" web.code.bash.sess
field "同步流" web.code.bash.sync field "同步流" web.code.bash.sync

View File

@ -4,18 +4,19 @@ import (
"strings" "strings"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/web"
) )
const CONFIGS = "configs"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
"/configs": {Name: "/configs", Help: "配置", Hand: func(m *ice.Message, arg ...string) { web.P(CONFIGS): {Hand: func(m *ice.Message, arg ...string) {
m.Cmd("web.code.git.configs", func(value ice.Maps) { if strings.Contains(m.Option(cli.RELEASE), cli.ALPINE) {
if strings.HasPrefix(value[mdb.NAME], "url") { m.Echo("sed -i 's/dl-cdn.alpinelinux.org/mirrors.tencent.com/g' /etc/apk/repositories && apk update").Echo(ice.NL)
m.Echo(`git config --global "%s" "%s"`, value[mdb.NAME], value[mdb.VALUE]) m.Echo("TZ=Asia/Shanghai; apk add tzdata && cp /usr/share/zoneinfo/${TZ} /etc/localtime && echo ${TZ} > /etc/timezone").Echo(ice.NL)
m.Echo(ice.NL) }
}
})
}}, }},
}) })
} }

View File

@ -2,29 +2,34 @@ package bash
import ( import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp"
"shylinux.com/x/icebergs/base/web" "shylinux.com/x/icebergs/base/web"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
const (
_DOWNLOAD = "_download"
)
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
"/download": {Name: "/download", Help: "下载", Hand: func(m *ice.Message, arg ...string) { web.P(web.DOWNLOAD): {Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 || arg[0] == "" { if len(arg) == 0 || arg[0] == "" {
m.Cmdy("web.chat.files").Table() m.Cmdy(FAVOR, _DOWNLOAD).Table()
return // 文件列表 } else {
m.Cmdy(web.CACHE, m.Cmd(FAVOR, _DOWNLOAD, arg[0]).Append(mdb.TEXT))
m.Render(kit.Select(ice.RENDER_DOWNLOAD, ice.RENDER_RESULT, m.Append(nfs.FILE) == ""), m.Append(mdb.TEXT))
} }
// 下载文件
m.Cmdy(web.CACHE, m.Cmd("web.chat.files", arg[0]).Append(mdb.DATA))
m.Render(kit.Select(ice.RENDER_DOWNLOAD, ice.RENDER_RESULT, m.Append(nfs.FILE) == ""), m.Append(mdb.TEXT))
}}, }},
"/upload": {Name: "/upload", Help: "上传", Hand: func(m *ice.Message, arg ...string) { web.P(web.UPLOAD): {Hand: func(m *ice.Message, arg ...string) {
msg := m.Cmd("web.chat.files", web.UPLOAD) // 上传文件 m.Optionv(ice.MSG_UPLOAD, web.UPLOAD)
for _, k := range []string{mdb.DATA, mdb.TIME, mdb.TYPE, mdb.NAME, nfs.SIZE} { up := web.Upload(m)
m.Echo("%s: %s\n", k, msg.Append(k)) m.Cmd(FAVOR, mdb.INSERT, _DOWNLOAD, mdb.TYPE, kit.Ext(up[1]), mdb.NAME, up[1], mdb.TEXT, up[0], m.OptionSimple(cli.PWD, aaa.USERNAME, tcp.HOSTNAME))
} m.Echo(up[0]).Echo(ice.NL)
}}, }},
}) })
} }

View File

@ -5,6 +5,8 @@ import (
"shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/web"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
@ -12,30 +14,34 @@ const FAVOR = "favor"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
"/favor": {Name: "/favor", Help: "收藏", Actions: ice.Actions{ FAVOR: {Name: "favor zone id auto insert", Help: "收藏夹", Actions: ice.MergeActions(ice.Actions{
mdb.EXPORT: {Name: "export zone name", Help: "导出", Hand: func(m *ice.Message, arg ...string) { mdb.INSERT: {Name: "insert zone*=demo type=shell name=1 text=pwd pwd=/home"},
m.Echo("#!/bin/sh\n\n") cli.SYSTEM: {Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(FAVOR, m.Option(mdb.ZONE), func(value ice.Maps) { if len(arg) > 0 && arg[0] == ice.RUN {
if msg := mdb.ZoneSelect(m.Spawn(), m.Option(mdb.ZONE), m.Option(mdb.ID)); nfs.ExistsFile(m, msg.Append(cli.PWD)) {
m.Option(cli.CMD_DIR, msg.Append(cli.PWD))
}
ctx.ProcessField(m, cli.SYSTEM, nil, arg...)
} else {
ctx.ProcessField(m, cli.SYSTEM, kit.Split(m.Option(mdb.TEXT)))
}
}},
web.DOWNLOAD: {Hand: func(m *ice.Message, arg ...string) { web.RenderCache(m, m.Option(mdb.TEXT)) }},
}, mdb.ZoneAction(mdb.FIELD, "time,id,type,name,text,pwd,username,hostname")), Hand: func(m *ice.Message, arg ...string) {
if mdb.ZoneSelect(m, arg...); len(arg) == 0 {
m.Action(mdb.EXPORT, mdb.IMPORT)
} else {
m.PushAction(kit.Select(cli.SYSTEM, web.DOWNLOAD, arg[0] == _DOWNLOAD))
}
}},
web.PP(FAVOR): {Actions: ice.Actions{
mdb.EXPORT: {Name: "export zone* name", Hand: func(m *ice.Message, arg ...string) {
m.Echo("#!/bin/sh\n\n").Cmdy(FAVOR, m.Option(mdb.ZONE), func(value ice.Maps) {
if m.Option(mdb.NAME) == "" || m.Option(mdb.NAME) == value[mdb.NAME] { if m.Option(mdb.NAME) == "" || m.Option(mdb.NAME) == value[mdb.NAME] {
m.Echo("# %v\n%v\n\n", value[mdb.NAME], value[mdb.TEXT]) m.Echo("# %s\n%s\n\n", value[mdb.NAME], value[mdb.TEXT])
} }
}) })
}}, }},
}, Hand: func(m *ice.Message, arg ...string) { m.Cmdy(FAVOR).Table() }}, }, Hand: func(m *ice.Message, arg ...string) { m.Cmdy(FAVOR).Table() }},
FAVOR: {Name: "favor zone id auto", Help: "收藏夹", Actions: ice.MergeActions(ice.Actions{
mdb.INSERT: {Name: "insert zone=系统命令 type=shell name=1 text=pwd pwd=/home", Help: "添加"},
cli.SYSTEM: {Name: "system", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
m.Option(cli.CMD_DIR, m.Option(cli.PWD))
ctx.ProcessCommand(m, cli.SYSTEM, kit.Split(m.Option(mdb.TEXT)), arg...)
ctx.ProcessCommandOpt(m, arg, cli.PWD)
}},
}, mdb.ZoneAction(mdb.SHORT, mdb.ZONE, mdb.FIELD, "time,id,type,name,text,pwd,username,hostname")), Hand: func(m *ice.Message, arg ...string) {
if mdb.ZoneSelect(m, arg...); len(arg) == 0 {
m.Action(mdb.CREATE, mdb.EXPORT, mdb.IMPORT)
} else {
m.PushAction(cli.SYSTEM)
m.StatusTimeCount()
}
}},
}) })
} }

View File

@ -2,7 +2,9 @@ package bash
import ( import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/tcp"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
@ -10,20 +12,14 @@ const GRANT = "grant"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
GRANT: {Name: "grant hash auto", Help: "授权", Actions: ice.MergeActions(ice.Actions{ GRANT: {Name: "grant hash auto", Help: "授权", Actions: ice.Actions{
"confirm": {Name: "confirm", Help: "同意", Hand: func(m *ice.Message, arg ...string) { mdb.MODIFY: {Help: "同意", Hand: func(m *ice.Message, arg ...string) { m.Cmd(SESS, mdb.MODIFY, GRANT, m.Option(ice.MSG_USERNAME)) }},
m.Cmd(SESS, mdb.MODIFY, GRANT, m.Option(ice.MSG_USERNAME)) mdb.REVERT: {Help: "撤销", Hand: func(m *ice.Message, arg ...string) { m.Cmd(SESS, mdb.MODIFY, GRANT, "") }},
}}, }, Hand: func(m *ice.Message, arg ...string) {
"revert": {Name: "revert", Help: "撤销", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(SESS, mdb.MODIFY, GRANT, "")
}},
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) {
if m.Cmdy(SESS, arg); len(arg) > 0 && m.Append(GRANT) == "" { if m.Cmdy(SESS, arg); len(arg) > 0 && m.Append(GRANT) == "" {
m.ProcessConfirm("授权设备") m.Echo("请授权 %s@%s 访问 %s", m.Append(aaa.USERNAME), m.Append(tcp.HOSTNAME), m.Option(ice.MSG_USERHOST))
} }
m.Tables(func(value ice.Maps) { m.Tables(func(value ice.Maps) { m.PushButton(kit.Select(mdb.REVERT, mdb.MODIFY, value[GRANT] == "")) })
m.PushButton(kit.Select("revert", "confirm", value[GRANT] == ""), mdb.REMOVE)
})
}}, }},
}) })
} }

View File

@ -14,8 +14,6 @@ import (
) )
func _run_action(m *ice.Message, cmd *ice.Command, script string, arg ...string) { func _run_action(m *ice.Message, cmd *ice.Command, script string, arg ...string) {
m.SetResult().Echo("#/bin/bash\n")
list, args := []string{}, []string{} list, args := []string{}, []string{}
kit.Fetch(cmd.Meta["_trans"], func(k string, v string) { kit.Fetch(cmd.Meta["_trans"], func(k string, v string) {
list = append(list, k) list = append(list, k)
@ -25,7 +23,7 @@ func _run_action(m *ice.Message, cmd *ice.Command, script string, arg ...string)
}) })
args = append(args, kit.Format(` ;;`)) args = append(args, kit.Format(` ;;`))
}) })
m.SetResult().Echo("#/bin/sh\n")
m.Echo(` m.Echo(`
ish_sys_dev_run_source() { ish_sys_dev_run_source() {
select action in %s; do select action in %s; do
@ -37,7 +35,6 @@ ish_sys_dev_run_source() {
done done
} }
`, kit.Join(list, ice.SP), arg[0], kit.Join(args, ice.NL)) `, kit.Join(list, ice.SP), arg[0], kit.Join(args, ice.NL))
m.Echo(` m.Echo(`
ish_sys_dev_run_action() { ish_sys_dev_run_action() {
select action in %s; do select action in %s; do
@ -50,40 +47,73 @@ ish_sys_dev_run_action() {
done done
} }
`, kit.Join(list, ice.SP), arg[0], kit.Join(args, ice.NL)) `, kit.Join(list, ice.SP), arg[0], kit.Join(args, ice.NL))
m.Echo(` m.Echo(`
ish_sys_dev_run_command() { ish_sys_dev_run_command() {
ish_sys_dev_run %s "$@" ish_sys_dev_run %s "$@"
} }
`, arg[0]) `, arg[0])
m.Echo(kit.Select("cat $1", script)) m.Echo(kit.Select("cat $1", script))
} }
func _run_command(m *ice.Message, key string, arg ...string) {
m.Search(key, func(p *ice.Context, s *ice.Context, key string, cmd *ice.Command) {
m.Echo(kit.Join(m.Cmd(key, arg).Appendv(kit.Format(kit.Value(cmd.List, kit.Keys(len(arg), mdb.NAME)))), ice.SP))
})
}
func _run_actions(m *ice.Message, key, sub string, arg ...string) (res []string) {
m.Search(key, func(p *ice.Context, s *ice.Context, key string, cmd *ice.Command) {
if sub == "" {
res = kit.SortedKey(cmd.Meta)
} else if len(arg)%2 == 0 {
kit.Fetch(kit.Value(cmd.Meta, sub), func(value ice.Map) { res = append(res, kit.Format(value[mdb.NAME])) })
kit.Fetch(arg, func(k, v string) { res[kit.IndexOf(res, k)] = "" })
} else {
msg := m.Cmd(key, mdb.INPUTS, kit.Select("", arg, -1), kit.Dict(arg))
res = msg.Appendv(kit.Select("", msg.Appendv(ice.MSG_APPEND), 0))
}
m.Echo(kit.Join(res, ice.SP))
})
return nil
}
const RUN = "run" const RUN = "run"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
"/run/": {Name: "/run/", Help: "执行", Actions: ice.Actions{ web.PP(RUN): {Actions: ice.Actions{
ctx.COMMAND: {Name: "command", Help: "命令", Hand: func(m *ice.Message, arg ...string) { "check": {Name: "check sid*", Hand: func(m *ice.Message, arg ...string) { m.Echo(m.Cmd(SESS, m.Option(SID)).Append(GRANT)) }},
"complete": {Hand: func(m *ice.Message, arg ...string) {
switch arg = kit.Split(m.Option("line")); m.Option("cword") {
case "1":
m.Echo("action ")
m.Echo(strings.Join(m.Cmd(ctx.COMMAND, mdb.SEARCH, ctx.COMMAND, ice.OptionFields(ctx.INDEX)).Appendv(ctx.INDEX), ice.SP))
default:
if kit.Int(m.Option("cword"))+1 == len(arg) {
arg = kit.Slice(arg, 0, -1)
}
if kit.Select("", arg, 2) == ctx.ACTION {
_run_actions(m, arg[1], kit.Select("", arg, 3), kit.Slice(arg, 4)...)
} else {
_run_command(m, arg[1], arg[2:]...)
}
}
}},
ctx.COMMAND: {Hand: func(m *ice.Message, arg ...string) {
m.Search(arg[0], func(_ *ice.Context, s *ice.Context, key string, cmd *ice.Command) { m.Search(arg[0], func(_ *ice.Context, s *ice.Context, key string, cmd *ice.Command) {
if p := strings.ReplaceAll(kit.Select("/app/cat.sh", cmd.Meta[ctx.DISPLAY]), ".js", ".sh"); strings.HasPrefix(p, ice.PS+ice.REQUIRE) { if p := kit.ExtChange(kit.Select("/app/cat.sh", cmd.Meta[ctx.DISPLAY]), nfs.SH); strings.HasPrefix(p, ice.PS+ice.REQUIRE) {
m.Cmdy(web.SPIDE, ice.DEV, web.SPIDE_RAW, p) m.Cmdy(web.SPIDE, ice.DEV, web.SPIDE_RAW, p)
} else { } else {
m.Cmdy(nfs.CAT, path.Join(ice.USR_INTSHELL, p)) m.Cmdy(nfs.CAT, path.Join(ice.USR_INTSHELL, p))
} }
if m.IsErrNotFound() { _run_action(m, cmd, m.Results(), arg...)
m.SetResult()
}
_run_action(m, cmd, m.Result(), arg...)
}) })
}}, }},
ice.RUN: {Name: "run", Help: "执行", Hand: func(m *ice.Message, arg ...string) { ice.RUN: {Hand: func(m *ice.Message, arg ...string) {
if !ctx.PodCmd(m, arg) && aaa.Right(m, arg) { if !ctx.PodCmd(m, arg) && aaa.Right(m, arg) {
m.Cmdy(arg) m.Cmdy(arg)
} }
if m.Result() == "" { if m.Result() != "" && !strings.HasSuffix(m.Result(), ice.NL) {
m.Table() m.Echo(ice.NL)
} }
}}, }},
}}, }},

View File

@ -10,6 +10,8 @@ import (
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/tcp" "shylinux.com/x/icebergs/base/tcp"
"shylinux.com/x/icebergs/base/web" "shylinux.com/x/icebergs/base/web"
"shylinux.com/x/icebergs/core/code"
kit "shylinux.com/x/toolkits"
) )
const ( const (
@ -25,48 +27,42 @@ func init() {
if f, _, e := m.R.FormFile(SUB); e == nil { if f, _, e := m.R.FormFile(SUB); e == nil {
defer f.Close() defer f.Close()
if b, e := ioutil.ReadAll(f); e == nil { if b, e := ioutil.ReadAll(f); e == nil {
m.Option(SUB, string(b)) // 文件参数 m.Option(SUB, string(b))
} }
} }
switch m.RenderResult(); arg[0] { switch m.RenderResult(); arg[0] {
case "/qrcode", "/sess": case web.P(cli.QRCODE), web.PP(SESS):
return // 登录入口 return
} }
if m.Warn(m.Option(SID, strings.TrimSpace(m.Option(SID))) == "", ice.ErrNotLogin, arg) { if m.Warn(m.Option(SID, strings.TrimSpace(m.Option(SID))) == "", ice.ErrNotLogin, arg) {
return return
} else if msg := m.Cmd(SESS, m.Option(SID)); msg.Append(GRANT) == "" {
aaa.SessAuth(m, ice.Maps{aaa.USERNAME: msg.Append(aaa.USERNAME), aaa.USERNICK: msg.Append(aaa.USERNAME), aaa.USERROLE: aaa.VOID}).Options(msg.AppendSimple(aaa.USERNAME, tcp.HOSTNAME, cli.RELEASE))
} else {
aaa.SessAuth(m, kit.Dict(aaa.USERNAME, msg.Append(GRANT), aaa.USERNICK, aaa.UserNick(m, msg.Append(GRANT)), aaa.USERROLE, aaa.UserRole(m, msg.Append(GRANT)))).Options(msg.AppendSimple(aaa.USERNAME, tcp.HOSTNAME, cli.RELEASE))
} }
msg := m.Cmd(SESS, m.Option(SID))
m.Option(ice.MSG_USERNAME, msg.Append(GRANT))
m.Option(ice.MSG_USERROLE, aaa.UserRole(m, msg.Append(GRANT)))
m.Option(tcp.HOSTNAME, msg.Append(tcp.HOSTNAME))
m.Auth(aaa.USERROLE, m.Option(ice.MSG_USERROLE), aaa.USERNAME, m.Option(ice.MSG_USERNAME))
if arg[0] == "/run/" {
return
}
m.Warn(m.Option(ice.MSG_USERNAME) == "", ice.ErrNotLogin, arg)
}}, }},
"/qrcode": {Name: "/qrcode", Help: "二维码", Hand: func(m *ice.Message, arg ...string) { web.P(cli.QRCODE): {Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(cli.QRCODE, m.Option(mdb.TEXT), m.Option(cli.FG), m.Option(cli.BG)) m.Cmdy(cli.QRCODE, m.Option(mdb.TEXT), m.Option(cli.FG), m.Option(cli.BG))
}}, }},
"/sess": {Name: "/sess", Help: "会话", Actions: ice.Actions{ web.PP(SESS): {Actions: ice.Actions{
aaa.LOGOUT: {Name: "logout", Help: "退出", Hand: func(m *ice.Message, arg ...string) { aaa.LOGOUT: {Hand: func(m *ice.Message, arg ...string) {
mdb.HashModify(m, mdb.HASH, m.Option(SID), mdb.STATUS, aaa.LOGOUT) if !m.Warn(m.Option(SID) == "", ice.ErrNotValid, SID) {
mdb.HashModify(m, mdb.HASH, m.Option(SID), mdb.STATUS, aaa.LOGOUT)
}
}}, }},
}, Hand: func(m *ice.Message, arg ...string) { }, Hand: func(m *ice.Message, arg ...string) {
if m.Option(SID) == "" { // 终端登录 if m.Option(SID) == "" {
m.Option(SID, mdb.HashCreate(m, mdb.STATUS, aaa.LOGIN, m.OptionSimple(aaa.USERNAME, tcp.HOSTNAME, cli.PID, cli.PWD))) m.Option(SID, mdb.HashCreate(m, mdb.STATUS, aaa.LOGIN, m.OptionSimple(aaa.USERNAME, tcp.HOSTNAME, cli.PID, cli.PWD, cli.RELEASE)))
} else { // 更新状态 } else {
mdb.HashModify(m, mdb.HASH, m.Option(SID), mdb.STATUS, aaa.LOGIN) mdb.HashModify(m, mdb.HASH, m.Option(SID), mdb.STATUS, aaa.LOGIN)
m.Echo(m.Option(SID)) m.Echo(m.Option(SID))
} }
}}, }},
SESS: {Name: "sess hash auto prunes", Help: "会话流", Actions: ice.MergeActions(ice.Actions{ SESS: {Name: "sess hash auto invite prunes", Help: "会话流", Actions: ice.MergeActions(ice.Actions{
mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) { aaa.INVITE: {Hand: func(m *ice.Message, arg ...string) {
mdb.HashPrunesValue(m, mdb.STATUS, aaa.LOGOUT) code.PublishScript(m, `export ctx_dev={{.Option "httphost"}}; ctx_temp=$(mktemp); curl -o $ctx_temp -fsSL $ctx_dev; source $ctx_temp`)
}}, }},
}, mdb.HashAction(mdb.FIELD, "time,hash,status,username,hostname,pid,pwd,grant"))}, }, mdb.HashAction(mdb.FIELD, "time,hash,status,username,hostname,release,pid,pwd,grant"))},
}) })
} }

View File

@ -8,41 +8,45 @@ import (
"shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp" "shylinux.com/x/icebergs/base/tcp"
"shylinux.com/x/icebergs/base/web"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
const SYNC = "sync" const SYNC = "sync"
func init() { func init() {
const (
HISTORY = "history"
SHELL = "shell"
)
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
"/sync": {Name: "/sync", Help: "同步", Actions: ice.Actions{ SYNC: {Name: "sync id auto page export import", Help: "同步流", Actions: ice.MergeActions(ice.Actions{
"history": {Name: "history", Help: "历史", Hand: func(m *ice.Message, arg ...string) { mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(FAVOR, mdb.INPUTS, arg) }},
cli.SYSTEM: {Hand: func(m *ice.Message, arg ...string) {
if len(arg) > 0 && arg[0] == ice.RUN {
if msg := mdb.ListSelect(m.Spawn(), m.Option(mdb.ID)); nfs.ExistsFile(m, msg.Append(cli.PWD)) {
m.Option(cli.CMD_DIR, msg.Append(cli.PWD))
}
ctx.ProcessField(m, cli.SYSTEM, nil, arg...)
} else {
ctx.ProcessField(m, cli.SYSTEM, kit.Split(m.Option(mdb.TEXT)))
}
}},
FAVOR: {Name: "favor zone=demo type name text pwd", Help: "收藏", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(FAVOR, mdb.INSERT, arg, m.OptionSimple(aaa.USERNAME, tcp.HOSTNAME))
}},
}, mdb.PageListAction(mdb.FIELD, "time,id,type,name,text,pwd,username,hostname")), Hand: func(m *ice.Message, arg ...string) {
mdb.PageListSelect(m, arg...).PushAction(cli.SYSTEM, FAVOR)
}},
web.PP(SYNC): {Actions: ice.Actions{
HISTORY: {Hand: func(m *ice.Message, arg ...string) {
ls := strings.SplitN(strings.TrimSpace(m.Option(ARG)), ice.SP, 4) ls := strings.SplitN(strings.TrimSpace(m.Option(ARG)), ice.SP, 4)
if text := strings.TrimSpace(strings.Join(ls[3:], ice.SP)); text != "" { if text := strings.TrimSpace(strings.Join(ls[3:], ice.SP)); text != "" {
m.Cmd(SYNC, mdb.INSERT, mdb.TIME, ls[1]+ice.SP+ls[2], m.Cmd(SYNC, mdb.INSERT, mdb.TIME, ls[1]+ice.SP+ls[2], mdb.TYPE, SHELL, mdb.NAME, ls[0], mdb.TEXT, text, m.OptionSimple(cli.PWD, aaa.USERNAME, tcp.HOSTNAME))
mdb.TYPE, "shell", mdb.NAME, ls[0], mdb.TEXT, text,
m.OptionSimple(cli.PWD, aaa.USERNAME, tcp.HOSTNAME, tcp.HOSTNAME))
} }
}}, }},
}}, }},
SYNC: {Name: "sync id auto page export import", Help: "同步流", Actions: ice.MergeActions(ice.Actions{
cli.SYSTEM: {Name: "system", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
m.Option(cli.CMD_DIR, m.Option(cli.PWD))
ctx.ProcessCommand(m, cli.SYSTEM, kit.Split(m.Option(mdb.TEXT)), arg...)
ctx.ProcessCommandOpt(m, arg, cli.PWD)
}},
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(FAVOR, mdb.INPUTS, arg)
}},
FAVOR: {Name: "favor zone=some@key type name text pwd", Help: "收藏", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(FAVOR, mdb.INSERT)
}},
}, mdb.ListAction(mdb.FIELD, "time,id,type,name,text,pwd,username,hostname")), Hand: func(m *ice.Message, arg ...string) {
mdb.OptionPage(m, kit.Slice(arg, 1)...)
mdb.ListSelect(m, kit.Slice(arg, 0, 1)...)
m.PushAction(cli.SYSTEM, FAVOR)
m.StatusTimeCountTotal(m.Config(mdb.COUNT))
}},
}) })
} }

View File

@ -3,51 +3,35 @@ package bash
import ( import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp" "shylinux.com/x/icebergs/base/tcp"
"shylinux.com/x/icebergs/base/web" "shylinux.com/x/icebergs/base/web"
kit "shylinux.com/x/toolkits"
) )
const (
FROM = "from"
TO = "to"
)
const TRASH = "trash" const TRASH = "trash"
func init() { func init() {
const (
FROM = "from"
TO = "to"
)
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
TRASH: {Name: "TRASH hash path auto prunes", Help: "回收站", Actions: ice.MergeActions(ice.Actions{ TRASH: {Name: "trash hash path auto", Help: "回收站", Actions: mdb.HashAction(mdb.FIELD, "time,hash,username,hostname,size,from,to")},
mdb.INSERT: {Name: "insert from to", Help: "添加", Hand: func(m *ice.Message, arg ...string) { web.PP(TRASH): {Actions: ice.MergeActions(ice.Actions{
mdb.INSERT: {Name: "insert from to", Hand: func(m *ice.Message, arg ...string) {
mdb.HashCreate(m, m.OptionSimple(aaa.USERNAME, tcp.HOSTNAME, nfs.SIZE, FROM, TO)) mdb.HashCreate(m, m.OptionSimple(aaa.USERNAME, tcp.HOSTNAME, nfs.SIZE, FROM, TO))
}}, }},
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) { mdb.REVERT: {Hand: func(m *ice.Message, arg ...string) {
if !m.Warn(m.Option(TO) == "", ice.ErrNotValid, TO) { mdb.HashSelect(m, m.Option(mdb.HASH))
mdb.HashRemove(m, m.OptionSimple(mdb.HASH)) defer mdb.HashRemove(m, m.OptionSimple(mdb.HASH))
nfs.RemoveAll(m, m.Option(TO)) m.Echo("mv %s %s", m.Append(TO), m.Append(FROM))
}
}}, }},
mdb.REVERT: {Name: "revert", Help: "恢复", Hand: func(m *ice.Message, arg ...string) { }), Hand: func(m *ice.Message, arg ...string) {
if !m.Warn(m.Option(FROM) == "" && m.Option(TO) == "", ice.ErrNotValid, FROM, TO) { mdb.HashSelectValue(m, func(key string, fields []string, value, val ice.Map) {
nfs.Rename(m, m.Option(TO), m.Option(FROM)) kit.If(value[tcp.HOSTNAME] == m.Option(tcp.HOSTNAME), func() { m.Push(key, value, fields, val) })
mdb.HashRemove(m, m.OptionSimple(mdb.HASH)) })
}
}},
mdb.PRUNES: {Name: "prunes before@date", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
mdb.HashPrunes(m, func(value ice.Map) bool {
return true
}).Tables(func(value ice.Maps) {
nfs.RemoveAll(m, value[TO])
})
}},
nfs.CAT: {Name: "cat", Help: "查看", Hand: func(m *ice.Message, arg ...string) {
m.Option(nfs.DIR_ROOT, m.Option(TO))
ctx.ProcessCommand(m, nfs.CAT, []string{}, arg...)
ctx.ProcessCommandOpt(m, arg, TO)
}},
}, mdb.HashAction(mdb.FIELD, "time,hash,username,hostname,size,from,to"), web.ApiAction("/trash")), Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelect(m, arg...).PushAction(nfs.CAT, mdb.REVERT, mdb.REMOVE)
}}, }},
}) })
} }

View File

@ -12,11 +12,11 @@ const ZSH = "zsh"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
ZSH: {Name: "zsh path auto order build download", Help: "命令行", Actions: ice.MergeActions(ice.Actions{ ZSH: {Name: "zsh path auto order build download", Help: "命令行", Actions: ice.MergeActions(ice.Actions{
cli.ORDER: {Name: "order", Help: "加载", Hand: func(m *ice.Message, arg ...string) { cli.ORDER: {Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(code.INSTALL, cli.ORDER, m.Config(nfs.SOURCE), "_install/bin") m.Cmdy(code.INSTALL, cli.ORDER, m.Config(nfs.SOURCE), "_install/bin")
}}, }},
}, code.InstallAction(nfs.SOURCE, "https://nchc.dl.sourceforge.net/project/zsh/zsh/5.8/zsh-5.8.tar.xz")), Hand: func(m *ice.Message, arg ...string) { }, code.InstallAction(nfs.SOURCE, "https://nchc.dl.sourceforge.net/project/zsh/zsh/5.8/zsh-5.8.tar.xz")), Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(code.INSTALL, nfs.SOURCE, m.Config(nfs.SOURCE), arg) m.Cmdy(code.INSTALL, m.ConfigSimple(nfs.SOURCE), arg)
}}, }},
}) })
} }

View File

@ -2,23 +2,20 @@ package git
import ( import (
"path" "path"
"strings"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/web" "shylinux.com/x/icebergs/base/web"
"shylinux.com/x/icebergs/core/code" "shylinux.com/x/icebergs/core/code"
kit "shylinux.com/x/toolkits"
) )
func _git_url(m *ice.Message, repos string) string { return web.MergeLink(m, "/x/"+path.Join(repos)+".git") } func _git_url(m *ice.Message, repos string) string {
return web.MergeLink(m, "/x/"+path.Join(repos)+".git")
}
func _git_dir(arg ...string) string { return path.Join(path.Join(arg...), ".git") } func _git_dir(arg ...string) string { return path.Join(path.Join(arg...), ".git") }
func _git_cmd(m *ice.Message, arg ...string) *ice.Message { return m.Cmd(cli.SYSTEM, GIT, arg) } func _git_cmd(m *ice.Message, arg ...string) *ice.Message { return m.Cmd(cli.SYSTEM, GIT, arg) }
func _git_cmds(m *ice.Message, arg ...string) string { func _git_cmds(m *ice.Message, arg ...string) string { return _git_cmd(m, arg...).Results() }
msg := _git_cmd(m, arg...)
return kit.Select("", strings.TrimSpace(msg.Result()), !msg.IsErr())
}
const GIT = "git" const GIT = "git"

View File

@ -2,7 +2,6 @@ package git
import ( import (
"path" "path"
"runtime"
"strings" "strings"
"time" "time"
@ -114,9 +113,8 @@ func _status_stat(m *ice.Message, files, adds, dels int) (int, int, int) {
} }
func _status_list(m *ice.Message) (files, adds, dels int, last time.Time) { func _status_list(m *ice.Message) (files, adds, dels int, last time.Time) {
ReposList(m).Tables(func(value ice.Maps) { ReposList(m).Tables(func(value ice.Maps) {
if m.Option(cli.CMD_DIR, value[nfs.PATH]); runtime.GOOS != cli.DARWIN { m.Option(cli.CMD_DIR, value[nfs.PATH])
files, adds, dels = _status_stat(m, files, adds, dels) files, adds, dels = _status_stat(m, files, adds, dels)
}
if repos, e := gogit.OpenRepository(_git_dir(value[nfs.PATH])); e == nil { if repos, e := gogit.OpenRepository(_git_dir(value[nfs.PATH])); e == nil {
if ci, e := repos.GetCommit(); e == nil && ci.Author.When.After(last) { if ci, e := repos.GetCommit(); e == nil && ci.Author.When.After(last) {
last = ci.Author.When last = ci.Author.When

View File

@ -27,24 +27,28 @@ const (
type input struct { type input struct {
ice.Zone ice.Zone
insert string `name:"insert zone=person text code weight" help:"添加"` insert string `name:"insert zone=person text code weight"`
load string `name:"load file=usr/wubi-dict/wubi86 zone=wubi86" help:"加载"` load string `name:"load file=usr/wubi-dict/wubi86 zone=wubi86"`
save string `name:"save file=usr/wubi-dict/person zone=person" help:"保存"` save string `name:"save file=usr/wubi-dict/person zone=person"`
list string `name:"list method code auto" help:"输入法"` list string `name:"list method code auto load" help:"输入法"`
} }
func (s input) Inputs(m *ice.Message, arg ...string) {
switch s.Zone.Inputs(m, arg...); arg[0] {
case nfs.FILE:
m.Cmdy(nfs.DIR, "usr/wubi-dict/", nfs.PATH)
case mdb.ZONE:
m.Push(arg[0], path.Base(m.Option(nfs.FILE)))
}
}
func (s input) Load(m *ice.Message, arg ...string) { func (s input) Load(m *ice.Message, arg ...string) {
if f, e := nfs.OpenFile(m.Message, m.Option(nfs.FILE)); !m.Warn(e) { if f, e := nfs.OpenFile(m, m.Option(nfs.FILE)); !m.Warn(e) {
defer f.Close() defer f.Close()
// 清空数据
lib := kit.Select(path.Base(m.Option(nfs.FILE)), m.Option(mdb.ZONE)) lib := kit.Select(path.Base(m.Option(nfs.FILE)), m.Option(mdb.ZONE))
m.Assert(nfs.RemoveAll(m.Message, path.Join(m.Config(mdb.STORE), lib))) m.Assert(nfs.RemoveAll(m, path.Join(m.Config(mdb.STORE), lib)))
s.Zone.Remove(m, mdb.ZONE, lib) s.Zone.Remove(m, mdb.ZONE, lib)
s.Zone.Create(m, kit.Simple(mdb.ZONE, lib, m.ConfigSimple(mdb.LIMIT, mdb.LEAST, mdb.STORE, mdb.FSIZE))...) s.Zone.Create(m, kit.Simple(mdb.ZONE, lib, m.ConfigSimple(mdb.LIMIT, mdb.LEAST, mdb.STORE, mdb.FSIZE))...)
prefix := kit.Keys(mdb.HASH, m.Result()) prefix := kit.Keys(mdb.HASH, m.Result())
// 加载词库
for bio := bufio.NewScanner(f); bio.Scan(); { for bio := bufio.NewScanner(f); bio.Scan(); {
if strings.HasPrefix(bio.Text(), "# ") { if strings.HasPrefix(bio.Text(), "# ") {
continue continue
@ -55,17 +59,14 @@ func (s input) Load(m *ice.Message, arg ...string) {
} }
mdb.Grow(m.Message, m.PrefixKey(), prefix, kit.Dict(TEXT, line[0], CODE, line[1], WEIGHT, kit.Select("999999", line, 2))) mdb.Grow(m.Message, m.PrefixKey(), prefix, kit.Dict(TEXT, line[0], CODE, line[1], WEIGHT, kit.Select("999999", line, 2)))
} }
// 保存词库
m.Conf(m.PrefixKey(), kit.Keys(prefix, kit.Keym(mdb.LIMIT)), 0) m.Conf(m.PrefixKey(), kit.Keys(prefix, kit.Keym(mdb.LIMIT)), 0)
m.Conf(m.PrefixKey(), kit.Keys(prefix, kit.Keym(mdb.LEAST)), 0) m.Conf(m.PrefixKey(), kit.Keys(prefix, kit.Keym(mdb.LEAST)), 0)
m.Echo("%s: %d", lib, mdb.Grow(m.Message, m.PrefixKey(), prefix, kit.Dict(TEXT, "成功", CODE, "z", WEIGHT, "0"))) m.Echo("%s: %d", lib, mdb.Grow(m.Message, m.PrefixKey(), prefix, kit.Dict(TEXT, "成功", CODE, "z", WEIGHT, "0")))
} }
} }
func (s input) Save(m *ice.Message, arg ...string) { func (s input) Save(m *ice.Message, arg ...string) (n int) {
if f, p, e := nfs.CreateFile(m.Message, m.Option(nfs.FILE)); m.Assert(e) { if f, p, e := nfs.CreateFile(m.Message, m.Option(nfs.FILE)); m.Assert(e) {
defer f.Close() defer f.Close()
n := 0
m.Option(mdb.CACHE_LIMIT, -2) m.Option(mdb.CACHE_LIMIT, -2)
for _, lib := range kit.Split(m.Option(mdb.ZONE)) { for _, lib := range kit.Split(m.Option(mdb.ZONE)) {
mdb.Richs(m.Message, m.PrefixKey(), "", lib, func(key string, value ice.Map) { mdb.Richs(m.Message, m.PrefixKey(), "", lib, func(key string, value ice.Map) {
@ -80,6 +81,7 @@ func (s input) Save(m *ice.Message, arg ...string) {
m.Logs(mdb.EXPORT, nfs.FILE, p, mdb.COUNT, n) m.Logs(mdb.EXPORT, nfs.FILE, p, mdb.COUNT, n)
m.Echo("%s: %d", p, n) m.Echo("%s: %d", p, n)
} }
return
} }
func (s input) List(m *ice.Message, arg ...string) { func (s input) List(m *ice.Message, arg ...string) {
if len(arg) < 2 || arg[1] == "" { if len(arg) < 2 || arg[1] == "" {
@ -90,23 +92,14 @@ func (s input) List(m *ice.Message, arg ...string) {
case WORD: case WORD:
arg[1] = "^" + arg[1] + ice.FS arg[1] = "^" + arg[1] + ice.FS
} }
// 搜索词汇
res := m.Cmdx(cli.SYSTEM, "grep", "-rn", arg[1], m.Config(mdb.STORE)) res := m.Cmdx(cli.SYSTEM, "grep", "-rn", arg[1], m.Config(mdb.STORE))
bio := csv.NewReader(bytes.NewBufferString(strings.Replace(res, ":", ",", -1))) bio := csv.NewReader(bytes.NewBufferString(strings.Replace(res, ice.DF, ice.FS, -1)))
for i := 0; i < kit.Int(10); i++ { for i := 0; i < kit.Int(10); i++ {
if line, e := bio.Read(); e != nil { if line, e := bio.Read(); e != nil {
break break
} else if len(line) < 3 { } else if len(line) > 3 {
m.Push(mdb.ID, line[3]).Push(CODE, line[2]).Push(TEXT, line[4]).Push(WEIGHT, line[6])
} else { // 输出词汇
m.Push(mdb.ID, line[3])
m.Push(CODE, line[2])
m.Push(TEXT, line[4])
m.Push(WEIGHT, line[6])
} }
} }
m.SortIntR(WEIGHT) m.StatusTimeCount().SortIntR(WEIGHT)
m.StatusTimeCount()
} }

View File

@ -1,4 +0,0 @@
section "input"
field web.code.input.wubi

View File

@ -11,31 +11,26 @@ import (
type wubi struct { type wubi struct {
input input
short string `data:"zone"`
field string `data:"time,zone,id,text,code,weight"`
store string `data:"usr/local/export/"` store string `data:"usr/local/export/"`
field string `data:"time,id,text,code,weight"`
fsize string `data:"100000"` fsize string `data:"100000"`
limit string `data:"10000"` limit string `data:"10000"`
least string `data:"1000"` least string `data:"1000"`
load string `name:"load file=usr/wubi-dict/wubi86 zone=wubi86"`
load string `name:"load file=usr/wubi-dict/wubi86 zone=wubi86" help:"加载"` save string `name:"save file=usr/wubi-dict/person zone=person"`
save string `name:"save file=usr/wubi-dict/person zone=person" help:"保存"` list string `name:"list method=word,line code auto load" help:"五笔"`
list string `name:"list method=word,line code auto" help:"五笔"`
} }
func (w wubi) Input(m *ice.Message, arg ...string) { func (w wubi) Input(m *ice.Message, arg ...string) {
if arg[0] = strings.TrimSpace(arg[0]); strings.HasPrefix(arg[0], "ice") { if arg[0] = strings.TrimSpace(arg[0]); strings.HasPrefix(arg[0], "ice") {
switch list := kit.Split(arg[0]); list[1] { switch list := kit.Split(arg[0]); list[1] {
case "add": // ice add 想你 shwq [9999 [person]] case "add": // ice add 想你 shwq [9999 [person]]
m.Cmd(w, mdb.INSERT, mdb.TEXT, list[2], cli.CODE, list[3], mdb.VALUE, kit.Select("999999", list, 4), mdb.ZONE, kit.Select("person", list, 5)) w.Insert(m, mdb.ZONE, kit.Select("person", list, 5), mdb.TEXT, list[2], cli.CODE, list[3], mdb.VALUE, kit.Select("999999", list, 4))
m.Echo(list[3] + ice.NL) m.Echo(list[3] + ice.NL)
} }
return return
} }
m.Cmd(w, WORD, arg[0], func(value ice.Maps) { m.Echo(value[mdb.TEXT] + ice.NL) })
m.Cmd(w, WORD, arg[0], func(value ice.Maps) {
m.Echo(value[mdb.TEXT] + ice.NL)
})
} }
func init() { ice.CodeCtxCmd(wubi{}) } func init() { ice.CodeCtxCmd(wubi{}) }

View File

@ -1,16 +1,18 @@
git git
ssh ssh
input
alpha
tmux
vim vim
bash bash
tmux coder
java
node
mp mp
wx wx
lark lark
wework wework
webview
chrome chrome
alpha webview
input
coder
java
node

View File

@ -16,7 +16,6 @@ func _ssh_watch(m *ice.Message, h string, output io.Writer, input io.Reader) io.
r, w := io.Pipe() r, w := io.Pipe()
bio := io.TeeReader(input, w) bio := io.TeeReader(input, w)
m.Go(func() { io.Copy(output, r) }) m.Go(func() { io.Copy(output, r) })
i, buf := 0, make([]byte, ice.MOD_BUFS) i, buf := 0, make([]byte, ice.MOD_BUFS)
m.Go(func() { m.Go(func() {
for { for {
@ -24,7 +23,6 @@ func _ssh_watch(m *ice.Message, h string, output io.Writer, input io.Reader) io.
if e != nil { if e != nil {
break break
} }
switch buf[i] { switch buf[i] {
case '\r', '\n': case '\r', '\n':
cmd := strings.TrimSpace(string(buf[:i])) cmd := strings.TrimSpace(string(buf[:i]))
@ -46,9 +44,7 @@ func init() {
psh.Index.MergeCommands(ice.Commands{ psh.Index.MergeCommands(ice.Commands{
CHANNEL: {Name: "channel hash id auto", Help: "通道", Actions: ice.MergeActions(ice.Actions{ CHANNEL: {Name: "channel hash id auto", Help: "通道", Actions: ice.MergeActions(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelectUpdate(m, mdb.FOREACH, func(value ice.Map) { mdb.HashSelectUpdate(m, mdb.FOREACH, func(value ice.Map) { kit.Value(value, mdb.STATUS, tcp.CLOSE) })
kit.Value(value, mdb.STATUS, tcp.CLOSE)
})
}}, }},
ctx.COMMAND: {Name: "command cmd=pwd", Help: "命令", Hand: func(m *ice.Message, arg ...string) { ctx.COMMAND: {Name: "command cmd=pwd", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
mdb.ZoneInsert(m, m.OptionSimple(mdb.HASH), mdb.TYPE, CMD, mdb.TEXT, m.Option(CMD)) mdb.ZoneInsert(m, m.OptionSimple(mdb.HASH), mdb.TYPE, CMD, mdb.TEXT, m.Option(CMD))
@ -57,23 +53,15 @@ func init() {
m.Sleep300ms() m.Sleep300ms()
} }
}}, }},
mdb.REPEAT: {Name: "repeat", Help: "执行", Hand: func(m *ice.Message, arg ...string) { mdb.REPEAT: {Help: "执行", Hand: func(m *ice.Message, arg ...string) { m.Cmdy("", ctx.COMMAND, CMD, m.Option(mdb.TEXT)) }},
m.Cmdy("", ctx.COMMAND, CMD, m.Option(mdb.TEXT)) }, mdb.HashAction(mdb.FIELDS, "time,hash,status,tty,count,username,hostport", mdb.FIELD, "time,id,type,text")), Hand: func(m *ice.Message, arg ...string) {
}}, if mdb.ZoneSelect(m, arg...); len(arg) == 0 {
}, mdb.HashAction(mdb.FIELD, "time,hash,status,tty,count,username,hostport")), Hand: func(m *ice.Message, arg ...string) { m.Tables(func(value ice.Maps) {
if len(arg) == 0 { // 通道列表
m.Action(mdb.PRUNES)
mdb.HashSelect(m, arg...).Tables(func(value ice.Maps) {
m.PushButton(kit.Select("", ctx.COMMAND, value[mdb.STATUS] == tcp.OPEN), mdb.REMOVE) m.PushButton(kit.Select("", ctx.COMMAND, value[mdb.STATUS] == tcp.OPEN), mdb.REMOVE)
}) }).Action(mdb.PRUNES)
return } else {
m.PushAction(mdb.REPEAT).Action(ctx.COMMAND)
} }
// 通道命令
m.Action(ctx.COMMAND)
m.Fields(len(arg[1:]), "time,id,type,text")
mdb.ZoneSelect(m, arg...)
m.PushAction(mdb.REPEAT)
}}, }},
}) })
} }

View File

@ -24,22 +24,16 @@ import (
func _ssh_open(m *ice.Message, arg ...string) { func _ssh_open(m *ice.Message, arg ...string) {
_ssh_dial(m, func(c net.Conn) { _ssh_dial(m, func(c net.Conn) {
// 保存界面
fd := int(os.Stdin.Fd()) fd := int(os.Stdin.Fd())
if oldState, err := terminal.MakeRaw(fd); err == nil { if oldState, err := terminal.MakeRaw(fd); err == nil {
defer terminal.Restore(fd, oldState) defer terminal.Restore(fd, oldState)
} }
// 设置宽高
w, h, _ := terminal.GetSize(fd) w, h, _ := terminal.GetSize(fd)
c.Write([]byte(fmt.Sprintf("#height:%d,width:%d\n", h, w))) c.Write([]byte(fmt.Sprintf("#height:%d,width:%d\n", h, w)))
for _, item := range kit.Simple(m.Optionv(ice.INIT)) {
// 初始命令
for _, item := range kit.Simple(m.Optionv("init")) {
m.Sleep300ms() m.Sleep300ms()
c.Write([]byte(item + ice.NL)) c.Write([]byte(item + ice.NL))
} }
m.Go(func() { io.Copy(c, os.Stdin) }) m.Go(func() { io.Copy(c, os.Stdin) })
io.Copy(os.Stdout, c) io.Copy(os.Stdout, c)
}, arg...) }, arg...)
@ -48,62 +42,58 @@ func _ssh_dial(m *ice.Message, cb func(net.Conn), arg ...string) {
p := kit.HomePath(".ssh", fmt.Sprintf("%s@%s:%s", m.Option(aaa.USERNAME), m.Option(tcp.HOST), m.Option(tcp.PORT))) p := kit.HomePath(".ssh", fmt.Sprintf("%s@%s:%s", m.Option(aaa.USERNAME), m.Option(tcp.HOST), m.Option(tcp.PORT)))
if nfs.ExistsFile(m, p) { if nfs.ExistsFile(m, p) {
if c, e := net.Dial("unix", p); e == nil { if c, e := net.Dial("unix", p); e == nil {
cb(c) // 会话复用 cb(c)
return return
} }
nfs.Remove(m, p) nfs.Remove(m, p)
} }
_ssh_conn(m, func(client *ssh.Client) { _ssh_conn(m, func(client *ssh.Client) {
if l, e := net.Listen("unix", p); m.Assert(e) { if l, e := net.Listen("unix", p); !m.Warn(e, ice.ErrNotValid) {
defer func() { nfs.Remove(m, p) }() defer func() { nfs.Remove(m, p) }()
defer l.Close() defer l.Close()
m.Go(func() { m.Go(func() {
for { for {
c, e := l.Accept() c, e := l.Accept()
if e != nil { if e != nil {
break break
} }
func(c net.Conn) { func(c net.Conn) {
w, h, _ := terminal.GetSize(int(os.Stdin.Fd())) w, h, _ := terminal.GetSize(int(os.Stdin.Fd()))
buf := make([]byte, ice.MOD_BUFS) buf := make([]byte, ice.MOD_BUFS)
if n, e := c.Read(buf); m.Assert(e) { if n, e := c.Read(buf); m.Assert(e) {
fmt.Sscanf(string(buf[:n]), "#height:%d,width:%d", &h, &w) fmt.Sscanf(string(buf[:n]), "#height:%d,width:%d", &h, &w)
} }
m.Go(func() { m.Go(func() {
defer c.Close() defer c.Close()
s, e := client.NewSession() s, e := client.NewSession()
if e != nil { if e != nil {
return return
} }
s.Stdin, s.Stdout, s.Stderr = c, c, c s.Stdin, s.Stdout, s.Stderr = c, c, c
s.RequestPty(kit.Env(cli.TERM), h, w, ssh.TerminalModes{ssh.ECHO: 1, ssh.TTY_OP_ISPEED: 14400, ssh.TTY_OP_OSPEED: 14400}) s.RequestPty(kit.Env(cli.TERM), h, w, ssh.TerminalModes{ssh.ECHO: 1, ssh.TTY_OP_ISPEED: 14400, ssh.TTY_OP_OSPEED: 14400})
defer s.Wait() defer s.Wait()
gdb.SignalNotify(m, 28, func() { gdb.SignalNotify(m, 28, func() {
w, h, _ := terminal.GetSize(int(os.Stdin.Fd())) w, h, _ := terminal.GetSize(int(os.Stdin.Fd()))
s.WindowChange(h, w) s.WindowChange(h, w)
}) })
s.Shell() s.Shell()
}) })
}(c) }(c)
} }
}) })
} }
if c, e := net.Dial("unix", p); e == nil { if c, e := net.Dial("unix", p); e == nil {
cb(c) // 会话连接 cb(c)
} }
}, arg...) }, arg...)
} }
func _ssh_conn(m *ice.Message, cb func(*ssh.Client), arg ...string) { func _ssh_conn(m *ice.Message, cb func(*ssh.Client), arg ...string) {
methods := []ssh.AuthMethod{} methods := []ssh.AuthMethod{}
methods = append(methods, ssh.PublicKeysCallback(func() ([]ssh.Signer, error) {
key, err := ssh.ParsePrivateKey([]byte(m.Cmdx(nfs.CAT, kit.HomePath(m.Option(PRIVATE)))))
return []ssh.Signer{key}, err
}))
methods = append(methods, ssh.PasswordCallback(func() (string, error) { return m.Option(aaa.PASSWORD), nil }))
methods = append(methods, ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) (res []string, err error) { methods = append(methods, ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) (res []string, err error) {
for _, q := range questions { for _, q := range questions {
p := strings.TrimSpace(strings.ToLower(q)) p := strings.TrimSpace(strings.ToLower(q))
@ -114,7 +104,7 @@ func _ssh_conn(m *ice.Message, cb func(*ssh.Client), arg ...string) {
fmt.Scanf("%s\n", &verify) fmt.Scanf("%s\n", &verify)
res = append(res, verify) res = append(res, verify)
} else { } else {
res = append(res, aaa.TOTP_GET(verify, 6, 30)) res = append(res, aaa.TOTP_GET(verify, 30, 6))
} }
case strings.HasSuffix(p, "password:"): case strings.HasSuffix(p, "password:"):
res = append(res, m.Option(aaa.PASSWORD)) res = append(res, m.Option(aaa.PASSWORD))
@ -123,21 +113,14 @@ func _ssh_conn(m *ice.Message, cb func(*ssh.Client), arg ...string) {
} }
return return
})) }))
methods = append(methods, ssh.PublicKeysCallback(func() ([]ssh.Signer, error) {
key, err := ssh.ParsePrivateKey([]byte(m.Cmdx(nfs.CAT, kit.HomePath(m.Option(PRIVATE)))))
return []ssh.Signer{key}, err
}))
methods = append(methods, ssh.PasswordCallback(func() (string, error) {
return m.Option(aaa.PASSWORD), nil
}))
m.Cmdy(tcp.CLIENT, tcp.DIAL, mdb.TYPE, SSH, mdb.NAME, m.Option(tcp.HOST), m.OptionSimple(tcp.HOST, tcp.PORT), arg, func(c net.Conn) { m.Cmdy(tcp.CLIENT, tcp.DIAL, mdb.TYPE, SSH, mdb.NAME, m.Option(tcp.HOST), m.OptionSimple(tcp.HOST, tcp.PORT), arg, func(c net.Conn) {
conn, chans, reqs, err := ssh.NewClientConn(c, m.Option(tcp.HOST)+ice.DF+m.Option(tcp.PORT), &ssh.ClientConfig{ conn, chans, reqs, err := ssh.NewClientConn(c, m.Option(tcp.HOST)+ice.DF+m.Option(tcp.PORT), &ssh.ClientConfig{
User: m.Option(aaa.USERNAME), Auth: methods, BannerCallback: func(message string) error { return nil }, User: m.Option(aaa.USERNAME), Auth: methods, BannerCallback: func(message string) error { return nil },
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error { return nil }, HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error { return nil },
}) })
m.Assert(err) if !m.Warn(err) {
cb(ssh.NewClient(conn, chans, reqs)) cb(ssh.NewClient(conn, chans, reqs))
}
}) })
} }
@ -147,6 +130,13 @@ const CONNECT = "connect"
func init() { func init() {
psh.Index.MergeCommands(ice.Commands{ psh.Index.MergeCommands(ice.Commands{
CONNECT: {Name: "connect name auto", Help: "连接", Actions: ice.MergeActions(ice.Actions{ CONNECT: {Name: "connect name auto", Help: "连接", Actions: ice.MergeActions(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelect(m).Tables(func(value ice.Maps) {
if value[mdb.STATUS] == tcp.OPEN {
m.Cmd("", tcp.DIAL, mdb.NAME, value[mdb.NAME], value)
}
})
}},
tcp.OPEN: {Name: "open authfile username=shy password verfiy host=shylinux.com port=22 private=.ssh/id_rsa", Help: "终端", Hand: func(m *ice.Message, arg ...string) { tcp.OPEN: {Name: "open authfile username=shy password verfiy host=shylinux.com port=22 private=.ssh/id_rsa", Help: "终端", Hand: func(m *ice.Message, arg ...string) {
defer m.Echo("exit %s@%s:%s\n", m.Option(aaa.USERNAME), m.Option(tcp.HOST), m.Option(tcp.PORT)) defer m.Echo("exit %s@%s:%s\n", m.Option(aaa.USERNAME), m.Option(tcp.HOST), m.Option(tcp.PORT))
_ssh_open(nfs.OptionLoad(m, m.Option("authfile")), arg...) _ssh_open(nfs.OptionLoad(m, m.Option("authfile")), arg...)
@ -157,20 +147,19 @@ func init() {
mdb.HashCreate(m.Spawn(), m.OptionSimple(mdb.NAME, tcp.HOST, tcp.PORT, aaa.USERNAME), mdb.STATUS, tcp.OPEN, kit.Dict(mdb.TARGET, client)) mdb.HashCreate(m.Spawn(), m.OptionSimple(mdb.NAME, tcp.HOST, tcp.PORT, aaa.USERNAME), mdb.STATUS, tcp.OPEN, kit.Dict(mdb.TARGET, client))
m.Cmd("", SESSION, m.OptionSimple(mdb.NAME)) m.Cmd("", SESSION, m.OptionSimple(mdb.NAME))
}, arg...) }, arg...)
}) }).Sleep300ms()
m.Sleep300ms()
}}, }},
SESSION: {Name: "session", Help: "会话", Hand: func(m *ice.Message, arg ...string) { SESSION: {Help: "会话", Hand: func(m *ice.Message, arg ...string) {
if c, e := _ssh_session(m, mdb.HashSelectTarget(m, m.Option(mdb.NAME), nil).(*ssh.Client)); m.Assert(e) { if c, e := _ssh_session(m, mdb.HashSelectTarget(m, m.Option(mdb.NAME), nil).(*ssh.Client)); !m.Warn(e, ice.ErrNotValid) {
defer c.Wait() defer c.Wait()
c.Shell() c.Shell()
} }
}}, }},
ctx.COMMAND: {Name: "command cmd=pwd", Help: "命令", Hand: func(m *ice.Message, arg ...string) { ctx.COMMAND: {Name: "command cmd=pwd", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
client := mdb.HashSelectTarget(m, m.Option(mdb.NAME), nil).(*ssh.Client) client := mdb.HashSelectTarget(m, m.Option(mdb.NAME), nil).(*ssh.Client)
if s, e := client.NewSession(); m.Assert(e) { if s, e := client.NewSession(); !m.Warn(e, ice.ErrNotValid) {
defer s.Close() defer s.Close()
if b, e := s.CombinedOutput(m.Option(ice.CMD)); m.Assert(e) { if b, e := s.CombinedOutput(m.Option(ice.CMD)); !m.Warn(e, ice.ErrNotValid) {
m.Echo(string(b)) m.Echo(string(b))
} }
} }

View File

@ -23,31 +23,37 @@ const (
const RSA = "rsa" const RSA = "rsa"
func init() { func init() {
const (
TITLE = "title"
BITS = "bits"
KEY = "key"
PUB = "pub"
)
aaa.Index.MergeCommands(ice.Commands{ aaa.Index.MergeCommands(ice.Commands{
RSA: {Name: "rsa hash auto", Help: "密钥", Actions: ice.MergeActions(ice.Actions{ RSA: {Name: "rsa hash auto", Help: "密钥", Actions: ice.MergeActions(ice.Actions{
mdb.CREATE: {Name: "create bits=2048,4096 title=some", Help: "创建", Hand: func(m *ice.Message, arg ...string) { mdb.CREATE: {Name: "create bits=2048,4096 title=some", Hand: func(m *ice.Message, arg ...string) {
if key, err := rsa.GenerateKey(rand.Reader, kit.Int(m.Option("bits"))); m.Assert(err) { if key, err := rsa.GenerateKey(rand.Reader, kit.Int(m.Option(BITS))); !m.Warn(err, ice.ErrNotValid) {
if pub, err := ssh.NewPublicKey(key.Public()); m.Assert(err) { if pub, err := ssh.NewPublicKey(key.Public()); !m.Warn(err, ice.ErrNotValid) {
mdb.HashCreate(m, m.OptionSimple("title"), PUBLIC, string(ssh.MarshalAuthorizedKey(pub)), mdb.HashCreate(m, m.OptionSimple(TITLE), PUBLIC, string(ssh.MarshalAuthorizedKey(pub)),
PRIVATE, string(pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)})), PRIVATE, string(pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)})),
) )
} }
} }
}}, }},
mdb.EXPORT: {Name: "export key=.ssh/id_rsa pub=.ssh/id_rsa.pub", Help: "导出", Hand: func(m *ice.Message, arg ...string) { mdb.EXPORT: {Name: "export key=.ssh/id_rsa pub=.ssh/id_rsa.pub", Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelect(m, m.Option(mdb.HASH)).Tables(func(value ice.Maps) { mdb.HashSelect(m, m.Option(mdb.HASH)).Tables(func(value ice.Maps) {
m.Cmdx(nfs.SAVE, kit.HomePath(m.Option("key")), value[PRIVATE]) m.Cmd(nfs.SAVE, kit.HomePath(m.Option(KEY)), value[PRIVATE])
m.Cmdx(nfs.SAVE, kit.HomePath(m.Option("pub")), value[PUBLIC]) m.Cmd(nfs.SAVE, kit.HomePath(m.Option(PUB)), value[PUBLIC])
}) })
}}, }},
mdb.IMPORT: {Name: "import key=.ssh/id_rsa pub=.ssh/id_rsa.pub", Help: "导入", Hand: func(m *ice.Message, arg ...string) { mdb.IMPORT: {Name: "import key=.ssh/id_rsa pub=.ssh/id_rsa.pub", Hand: func(m *ice.Message, arg ...string) {
m.Conf("", kit.Keys(mdb.HASH, path.Base(m.Option("key"))), kit.Data(mdb.TIME, m.Time(), m.Conf("", kit.Keys(mdb.HASH, path.Base(m.Option(KEY))), kit.Data(mdb.TIME, m.Time(),
"title", kit.Format("%s@%s", ice.Info.Username, ice.Info.Hostname), TITLE, kit.Format("%s@%s", ice.Info.Username, ice.Info.Hostname),
PRIVATE, m.Cmdx(nfs.CAT, kit.HomePath(m.Option("key"))), PRIVATE, m.Cmdx(nfs.CAT, kit.HomePath(m.Option(KEY))),
PUBLIC, m.Cmdx(nfs.CAT, kit.HomePath(m.Option("pub"))), PUBLIC, m.Cmdx(nfs.CAT, kit.HomePath(m.Option(PUB))),
)) ))
}}, }},
}, mdb.HashAction(mdb.SHORT, mdb.HASH, mdb.FIELD, "time,hash,title,public,private")), Hand: func(m *ice.Message, arg ...string) { }, mdb.HashAction(mdb.SHORT, PRIVATE, mdb.FIELD, "time,hash,title,public,private")), Hand: func(m *ice.Message, arg ...string) {
if mdb.HashSelect(m, arg...).PushAction(mdb.EXPORT, mdb.REMOVE); len(arg) == 0 { if mdb.HashSelect(m, arg...).PushAction(mdb.EXPORT, mdb.REMOVE); len(arg) == 0 {
m.Action(mdb.CREATE, mdb.IMPORT) m.Action(mdb.CREATE, mdb.IMPORT)
} }

View File

@ -32,20 +32,19 @@ func _ssh_config(m *ice.Message, h string) *ssh.ServerConfig {
PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
meta, err := _ssh_meta(conn), errors.New(ice.ErrNotRight) meta, err := _ssh_meta(conn), errors.New(ice.ErrNotRight)
if tcp.IsLocalHost(m, meta[tcp.HOSTPORT]) { if tcp.IsLocalHost(m, meta[tcp.HOSTPORT]) {
m.Auth(aaa.USERNAME, meta[aaa.USERNAME], tcp.HOSTPORT, meta[tcp.HOSTPORT]) m.Auth(kit.SimpleKV(kit.Fields(aaa.USERNAME, tcp.HOSTPORT), meta))
err = nil // 本机用户 err = nil
} else { } else {
mdb.ZoneSelectCB(m, h, func(value ice.Maps) { mdb.ZoneSelectCB(m, h, func(value ice.Maps) {
if !strings.HasPrefix(value[mdb.NAME], meta[aaa.USERNAME]+"@") { if !strings.HasPrefix(value[mdb.NAME], meta[aaa.USERNAME]+"@") {
return return
} }
if s, e := base64.StdEncoding.DecodeString(value[mdb.TEXT]); !m.Warn(e) { if s, e := base64.StdEncoding.DecodeString(value[mdb.TEXT]); !m.Warn(e, ice.ErrNotValid, value[mdb.TEXT]) {
if pub, e := ssh.ParsePublicKey([]byte(s)); !m.Warn(e) { if pub, e := ssh.ParsePublicKey([]byte(s)); !m.Warn(e, ice.ErrNotValid, value[mdb.TEXT]) {
if bytes.Compare(pub.Marshal(), key.Marshal()) == 0 { if bytes.Compare(pub.Marshal(), key.Marshal()) == 0 {
meta[tcp.HOSTNAME] = kit.Select("", kit.Split(value[mdb.NAME], "@"), 1) meta[tcp.HOSTNAME] = kit.Select("", kit.Split(value[mdb.NAME], "@"), 1)
m.Auth(aaa.USERNAME, meta[aaa.USERNAME], tcp.HOSTPORT, meta[tcp.HOSTPORT], tcp.HOSTNAME, meta[tcp.HOSTNAME]) m.Auth(kit.SimpleKV(kit.Fields(aaa.USERNAME, tcp.HOSTPORT, tcp.HOSTNAME), meta))
err = nil // 认证成功 err = nil
} }
} }
} }
@ -55,16 +54,14 @@ func _ssh_config(m *ice.Message, h string) *ssh.ServerConfig {
}, },
PasswordCallback: func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) { PasswordCallback: func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
meta, err := _ssh_meta(conn), errors.New(ice.ErrNotRight) meta, err := _ssh_meta(conn), errors.New(ice.ErrNotRight)
m.Debug("what %v", string(password))
if aaa.UserLogin(m, meta[aaa.USERNAME], string(password)) { if aaa.UserLogin(m, meta[aaa.USERNAME], string(password)) {
m.Auth(aaa.USERNAME, meta[aaa.USERNAME], tcp.HOSTPORT, meta[tcp.HOSTPORT], aaa.PASSWORD, strings.Repeat("*", len(string(password)))) m.Auth(kit.SimpleKV(kit.Fields(aaa.USERNAME, tcp.HOSTPORT, tcp.HOSTNAME), meta))
err = nil // 密码登录 err = nil
} }
return &ssh.Permissions{Extensions: meta}, err return &ssh.Permissions{Extensions: meta}, err
}, },
} }
if key, err := ssh.ParsePrivateKey([]byte(m.Cmdx(nfs.CAT, kit.HomePath(m.Option(PRIVATE))))); !m.Warn(err, ice.ErrNotValid, m.Option(PRIVATE)) {
if key, err := ssh.ParsePrivateKey([]byte(m.Cmdx(nfs.CAT, kit.HomePath(m.Option(PRIVATE))))); !m.Warn(err) {
config.AddHostKey(key) config.AddHostKey(key)
} }
return config return config
@ -75,15 +72,14 @@ func _ssh_accept(m *ice.Message, h string, c net.Conn) {
return return
} }
m.Go(func() { ssh.DiscardRequests(reqs) }) m.Go(func() { ssh.DiscardRequests(reqs) })
for ch := range chans { for ch := range chans {
channel, requests, err := ch.Accept() channel, requests, err := ch.Accept()
if m.Warn(err) { if m.Warn(err) {
continue continue
} }
m.Go(func() { m.Go(func() {
m.Logs(CHANNEL, tcp.HOSTPORT, c.RemoteAddr().String(), "->", c.LocalAddr().String()) m.Logs(CHANNEL, tcp.HOSTPORT, c.RemoteAddr().String()+" -> "+c.LocalAddr().String())
defer m.Logs("dischan", tcp.HOSTPORT, c.RemoteAddr().String(), "->", c.LocalAddr().String()) defer m.Logs("dischan", tcp.HOSTPORT, c.RemoteAddr().String()+" -> "+c.LocalAddr().String())
_ssh_prepare(m.Spawn(conn.Permissions.Extensions), channel, requests) _ssh_prepare(m.Spawn(conn.Permissions.Extensions), channel, requests)
}) })
} }
@ -94,47 +90,40 @@ func _ssh_prepare(m *ice.Message, channel ssh.Channel, requests <-chan *ssh.Requ
return return
} }
defer tty.Close() defer tty.Close()
list := kit.EnvSimple(cli.PATH)
list := []string{cli.PATH + "=" + kit.Env(cli.PATH)}
for request := range requests { for request := range requests {
m.Logs(REQUEST, tcp.HOSTPORT, m.Option(tcp.HOSTPORT), mdb.TYPE, request.Type) m.Logs(REQUEST, m.OptionSimple(tcp.HOSTPORT), mdb.TYPE, request.Type)
switch request.Type { switch request.Type {
case "pty-req": case "pty-req":
termLen := request.Payload[3] termLen := request.Payload[3]
termEnv := string(request.Payload[4 : termLen+4]) termEnv := string(request.Payload[4 : termLen+4])
_ssh_size(pty.Fd(), request.Payload[termLen+4:]) _ssh_size(pty.Fd(), request.Payload[termLen+4:])
list = append(list, "TERM="+termEnv) list = append(list, cli.TERM, termEnv)
case "window-change": case "window-change":
_ssh_size(pty.Fd(), request.Payload) _ssh_size(pty.Fd(), request.Payload)
case "env": case "env":
var env struct{ Name, Value string } var env struct{ Name, Value string }
if err := ssh.Unmarshal(request.Payload, &env); err != nil { if err := ssh.Unmarshal(request.Payload, &env); err != nil {
continue continue
} }
list = append(list, env.Name+"="+env.Value) list = append(list, env.Name, env.Value)
case "shell": case "shell":
_ssh_handle(m, channel, pty, tty) _ssh_handle(m, channel, pty, tty, list)
case "exec": case "exec":
defer channel.Close() defer channel.Close()
m.Optionv(cli.CMD_OUTPUT, channel) m.Options(cli.CMD_OUTPUT, channel, cli.CMD_ENV, list)
m.Cmd(cli.SYSTEM, kit.Select("sh", kit.Env(cli.SHELL)), "-c", string(request.Payload[4:request.Payload[3]+4])) m.Cmd(cli.SYSTEM, kit.Select("sh", kit.Env(cli.SHELL)), "-c", string(request.Payload[4:request.Payload[3]+4]))
return return
} }
request.Reply(true, nil) request.Reply(true, nil)
} }
} }
func _ssh_handle(m *ice.Message, channel ssh.Channel, pty, tty *os.File) { func _ssh_handle(m *ice.Message, channel ssh.Channel, pty, tty *os.File, list []string) {
h := m.Cmdx(mdb.INSERT, m.Prefix(CHANNEL), "", mdb.HASH, mdb.STATUS, tcp.OPEN, TTY, tty.Name(), m.OptionSimple(aaa.USERNAME, tcp.HOSTPORT), kit.Dict(mdb.TARGET, pty)) h := m.Cmdx(mdb.INSERT, m.Prefix(CHANNEL), "", mdb.HASH, mdb.STATUS, tcp.OPEN, TTY, tty.Name(), m.OptionSimple(aaa.USERNAME, tcp.HOSTPORT), kit.Dict(mdb.TARGET, pty))
m.Go(func() { io.Copy(channel, pty) })
p := _ssh_watch(m, h, pty, channel) p := _ssh_watch(m, h, pty, channel)
m.Go(func() { io.Copy(channel, pty) })
m.Optionv(cli.CMD_INPUT, tty)
m.Optionv(cli.CMD_OUTPUT, tty)
channel.Write([]byte(m.Config(WELCOME))) channel.Write([]byte(m.Config(WELCOME)))
m.Options(cli.CMD_INPUT, tty, cli.CMD_OUTPUT, tty)
m.Cmd(cli.DAEMON, kit.Select("sh", kit.Env(cli.SHELL)), func() { m.Cmd(cli.DAEMON, kit.Select("sh", kit.Env(cli.SHELL)), func() {
defer m.Cmd(mdb.MODIFY, m.Prefix(CHANNEL), "", mdb.HASH, mdb.HASH, h, mdb.STATUS, tcp.CLOSE) defer m.Cmd(mdb.MODIFY, m.Prefix(CHANNEL), "", mdb.HASH, mdb.HASH, h, mdb.STATUS, tcp.CLOSE)
channel.Write([]byte(m.Config(GOODBYE))) channel.Write([]byte(m.Config(GOODBYE)))
@ -161,31 +150,26 @@ func init() {
} }
}) })
}}, }},
tcp.LISTEN: {Name: "listen port=9022 private=.ssh/id_rsa authkey=.ssh/authorized_keys", Help: "添加", Hand: func(m *ice.Message, arg ...string) { tcp.LISTEN: {Name: "listen port=9022 private=.ssh/id_rsa authkey=.ssh/authorized_keys", Help: "启动", Hand: func(m *ice.Message, arg ...string) {
if mdb.HashSelect(m, m.Option(tcp.PORT)).Length() > 0 { if mdb.HashSelect(m, m.Option(tcp.PORT)).Length() > 0 {
mdb.HashModify(m, m.Option(tcp.PORT), mdb.STATUS, tcp.OPEN) mdb.HashModify(m, m.Option(tcp.PORT), mdb.STATUS, tcp.OPEN)
} else { } else {
mdb.HashCreate(m.Spawn(), m.OptionSimple(mdb.HashField(m)), mdb.STATUS, tcp.OPEN) mdb.HashCreate(m.Spawn(), m.OptionSimple(mdb.HashField(m)), mdb.STATUS, tcp.OPEN)
m.Cmd("", ctx.LOAD, m.OptionSimple(AUTHKEY)) m.Cmd("", ctx.LOAD, m.OptionSimple(AUTHKEY))
} }
m.Go(func() { m.Go(func() {
m.Cmd(tcp.SERVER, tcp.LISTEN, mdb.TYPE, SSH, mdb.NAME, tcp.PORT, m.OptionSimple(tcp.PORT), func(c net.Conn) { m.Cmd(tcp.SERVER, tcp.LISTEN, mdb.TYPE, SSH, mdb.NAME, m.Option(tcp.PORT), m.OptionSimple(tcp.PORT), func(c net.Conn) {
m.Go(func() { _ssh_accept(m, kit.Hashs(m.Option(tcp.PORT)), c) }) m.Go(func() { _ssh_accept(m, kit.Hashs(m.Option(tcp.PORT)), c) })
}) })
}) })
}}, }},
mdb.INSERT: {Name: "insert text:textarea", Help: "添加", Hand: func(m *ice.Message, arg ...string) { mdb.INSERT: {Name: "insert text:textarea", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
if ls := kit.Split(m.Option(mdb.TEXT)); len(ls) > 2 { if ls := kit.Split(m.Option(mdb.TEXT)); len(ls) > 2 {
m.Cmdy(mdb.INSERT, m.Prefix(SERVICE), kit.Keys(mdb.HASH, kit.Hashs(m.Option(tcp.PORT))), mdb.LIST, mdb.ZoneInsert(m, m.OptionSimple(tcp.PORT), mdb.TYPE, ls[0], mdb.NAME, ls[len(ls)-1], mdb.TEXT, strings.Join(ls[1:len(ls)-1], "+"))
mdb.TYPE, ls[0], mdb.NAME, ls[len(ls)-1], mdb.TEXT, strings.Join(ls[1:len(ls)-1], "+"))
} }
}}, }},
ctx.LOAD: {Name: "load authkey=.ssh/authorized_keys", Help: "加载", Hand: func(m *ice.Message, arg ...string) { ctx.LOAD: {Name: "load authkey=.ssh/authorized_keys", Help: "加载", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(nfs.CAT, kit.HomePath(m.Option(AUTHKEY)), func(pub string) { m.Cmd(nfs.CAT, kit.HomePath(m.Option(AUTHKEY)), func(pub string) { m.Cmd(SERVICE, mdb.INSERT, mdb.TEXT, pub) })
m.Cmd(SERVICE, mdb.INSERT, mdb.TEXT, pub)
})
}}, }},
ctx.SAVE: {Name: "save authkey=.ssh/authorized_keys", Help: "保存", Hand: func(m *ice.Message, arg ...string) { ctx.SAVE: {Name: "save authkey=.ssh/authorized_keys", Help: "保存", Hand: func(m *ice.Message, arg ...string) {
list := []string{} list := []string{}
@ -196,24 +180,20 @@ func init() {
m.Cmdy(nfs.SAVE, kit.HomePath(m.Option(AUTHKEY)), strings.Join(list, ice.NL)+ice.NL) m.Cmdy(nfs.SAVE, kit.HomePath(m.Option(AUTHKEY)), strings.Join(list, ice.NL)+ice.NL)
} }
}}, }},
aaa.INVITE: {Name: "invite", Help: "邀请", Hand: func(m *ice.Message, arg ...string) { aaa.INVITE: {Help: "邀请", Hand: func(m *ice.Message, arg ...string) {
m.Option(cli.HOSTNAME, web.OptionUserWeb(m).Hostname()) m.Option(cli.HOSTNAME, tcp.PublishLocalhost(m, web.OptionUserWeb(m).Hostname()))
if buf, err := kit.Render(`ssh -p {{.Option "port"}} {{.Option "user.name"}}@{{.Option "hostname"}}`, m); err == nil { if buf, err := kit.Render(`ssh -p {{.Option "port"}} {{.Option "user.name"}}@{{.Option "hostname"}}`, m); err == nil {
m.EchoScript(string(buf)) m.EchoScript(string(buf))
} }
}}, }},
}, mdb.StatusHashAction( }, mdb.StatusHashAction(
mdb.SHORT, tcp.PORT, mdb.FIELD, "time,port,status,private,authkey,count", mdb.SHORT, tcp.PORT, mdb.FIELD, "time,port,status,private,authkey,count", mdb.FIELDS, "time,id,type,name,text",
WELCOME, "welcome to contexts world\r\n", GOODBYE, "goodbye of contexts world\r\n", WELCOME, "welcome to contexts world\r\n", GOODBYE, "goodbye of contexts world\r\n",
)), Hand: func(m *ice.Message, arg ...string) { )), Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 { // 服务列表 m.Fields(len(arg), m.Config(mdb.FIELD), m.Config(mdb.FIELDS))
mdb.HashSelect(m, arg...).PushAction(aaa.INVITE, mdb.INSERT, ctx.LOAD, ctx.SAVE) if mdb.ZoneSelect(m, arg...); len(arg) == 0 {
return m.PushAction(aaa.INVITE, mdb.INSERT, ctx.LOAD, ctx.SAVE)
} }
// 公钥列表
m.Fields(len(arg[1:]), "time,id,type,name,text")
mdb.ZoneSelect(m, arg...)
}}, }},
}) })
} }

View File

@ -11,7 +11,6 @@ type Winsize struct{ Height, Width, x, y uint16 }
func _ssh_size(fd uintptr, b []byte) { func _ssh_size(fd uintptr, b []byte) {
w := binary.BigEndian.Uint32(b) w := binary.BigEndian.Uint32(b)
h := binary.BigEndian.Uint32(b[4:]) h := binary.BigEndian.Uint32(b[4:])
ws := &Winsize{Width: uint16(w), Height: uint16(h)} ws := &Winsize{Width: uint16(w), Height: uint16(h)}
syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(ws))) syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(ws)))
} }

View File

@ -20,9 +20,7 @@ func _ssh_session(m *ice.Message, client *ssh.Client) (*ssh.Session, error) {
m.Assert(e) m.Assert(e)
in, e := s.StdinPipe() in, e := s.StdinPipe()
m.Assert(e) m.Assert(e)
h := m.Cmdx(SESSION, mdb.CREATE, mdb.STATUS, tcp.OPEN, CONNECT, m.Option(mdb.NAME), kit.Dict(mdb.TARGET, in)) h := m.Cmdx(SESSION, mdb.CREATE, mdb.STATUS, tcp.OPEN, CONNECT, m.Option(mdb.NAME), kit.Dict(mdb.TARGET, in))
m.Go(func() { m.Go(func() {
buf := make([]byte, ice.MOD_BUFS) buf := make([]byte, ice.MOD_BUFS)
for { for {
@ -53,29 +51,23 @@ const SESSION = "session"
func init() { func init() {
psh.Index.MergeCommands(ice.Commands{ psh.Index.MergeCommands(ice.Commands{
SESSION: {Name: "session hash id auto", Help: "会话", Actions: ice.MergeActions(ice.Actions{ SESSION: {Name: "session hash id auto", Help: "会话", Actions: ice.MergeActions(ice.Actions{
mdb.REPEAT: {Name: "repeat", Help: "执行", Hand: func(m *ice.Message, arg ...string) { mdb.REPEAT: {Help: "执行", Hand: func(m *ice.Message, arg ...string) { m.Cmdy("", ctx.ACTION, ctx.COMMAND, CMD, m.Option(mdb.TEXT)) }},
m.Cmdy("", ctx.COMMAND, CMD, m.Option(mdb.TEXT))
}},
ctx.COMMAND: {Name: "command cmd=pwd", Help: "命令", Hand: func(m *ice.Message, arg ...string) { ctx.COMMAND: {Name: "command cmd=pwd", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
m.Cmd("", mdb.INSERT, m.OptionSimple(mdb.HASH), mdb.TYPE, CMD, mdb.TEXT, m.Option(CMD)) mdb.ZoneInsert(m, m.OptionSimple(mdb.HASH), mdb.TYPE, CMD, mdb.TEXT, m.Option(CMD))
w := mdb.HashSelectTarget(m, m.Option(mdb.HASH), nil).(io.Writer) if w, ok := mdb.HashSelectTarget(m, m.Option(mdb.HASH), nil).(io.Writer); ok {
w.Write([]byte(m.Option(CMD) + ice.NL)) w.Write([]byte(m.Option(CMD) + ice.NL))
m.Sleep300ms() m.Sleep300ms()
}
}}, }},
}, mdb.ZoneAction(mdb.FIELD, "time,hash,count,status,connect")), Hand: func(m *ice.Message, arg ...string) { }, mdb.PageZoneAction(mdb.FIELD, "time,hash,count,status,connect", mdb.FIELDS, "time,id,type,text")), Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 { m.Fields(len(kit.Slice(arg, 0, 2)), m.Config(mdb.FIELD), m.Config(mdb.FIELDS))
mdb.HashSelect(m, arg...).Tables(func(value ice.Maps) { if mdb.PageZoneSelect(m, arg...); len(arg) == 0 {
m.Tables(func(value ice.Maps) {
m.PushButton(kit.Select("", ctx.COMMAND, value[mdb.STATUS] == tcp.OPEN), mdb.REMOVE) m.PushButton(kit.Select("", ctx.COMMAND, value[mdb.STATUS] == tcp.OPEN), mdb.REMOVE)
}) })
return } else {
m.Tables(func(value ice.Maps) { m.PushButton(kit.Select("", mdb.REPEAT, value[mdb.TYPE] == CMD)) }).Action(ctx.COMMAND, mdb.PAGE)
} }
m.Action(ctx.COMMAND, mdb.PAGE)
mdb.OptionPage(m, kit.Slice(arg, 2)...)
m.Fields(len(kit.Slice(arg, 1, 2)), "time,id,type,text")
mdb.ZoneSelect(m, kit.Slice(arg, 0, 2)...).Tables(func(value ice.Maps) {
m.PushButton(kit.Select("", mdb.REPEAT, value[mdb.TYPE] == CMD))
})
}}, }},
}) })
} }

View File

@ -4,6 +4,7 @@ import (
"strings" "strings"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
@ -14,55 +15,39 @@ const (
TEXT = "text" TEXT = "text"
) )
const ( const (
SET_BUFFER = "set-buffer" SET_BUFFER = "set-buffer"
SHOW_BUFFER = "show-buffer" SHOW_BUFFER = "show-buffer"
LIST_BUFFER = "list-buffers" LIST_BUFFER = "list-buffers"
DELETE_BUFFER = "delete-buffer"
) )
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
BUFFER: {Name: "buffer name value auto", Help: "缓存", Actions: ice.Actions{ BUFFER: {Name: "buffer name value auto", Help: "缓存", Actions: ice.Actions{
mdb.MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) { mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {}},
switch arg[0] { mdb.CREATE: {Name: "create value*", Hand: func(m *ice.Message, arg ...string) { _tmux_cmd(m, SET_BUFFER, m.Option(mdb.VALUE)) }},
case mdb.TEXT: mdb.REMOVE: {Hand: func(m *ice.Message, arg ...string) { _tmux_cmd(m, DELETE_BUFFER, "-b", m.Option(mdb.NAME)) }},
_tmux_cmd(m, SET_BUFFER, "-b", m.Option(mdb.NAME), arg[1]) mdb.MODIFY: {Hand: func(m *ice.Message, arg ...string) {
} kit.If(arg[0] == mdb.VALUE, func() { _tmux_cmd(m, SET_BUFFER, "-b", m.Option(mdb.NAME), arg[1]) })
}}, }},
}, Hand: func(m *ice.Message, arg ...string) { }, Hand: func(m *ice.Message, arg ...string) {
if len(arg) > 1 && arg[1] != "" { // 设置缓存 if kit.If(len(arg) > 1 && arg[0] != "" && arg[1] != "", func() { _tmux_cmd(m, SET_BUFFER, "-b", arg[0], arg[1]) }); len(arg) > 0 && arg[0] != "" {
_tmux_cmd(m, SET_BUFFER, "-b", arg[0], arg[1]) cli.PushText(m, _tmux_cmds(m, SHOW_BUFFER, "-b", arg[0]))
}
if len(arg) > 0 { // 查看缓存
m.Echo(_tmux_cmd(m, SHOW_BUFFER, "-b", arg[0]).Result())
return return
} }
for i, v := range kit.SplitLine(_tmux_cmd(m, LIST_BUFFER).Result()) {
// 缓存列表
for i, v := range kit.Split(_tmux_cmd(m, LIST_BUFFER).Result(), ice.NL, ice.NL, ice.NL) {
ls := strings.SplitN(v, ": ", 3) ls := strings.SplitN(v, ": ", 3)
m.Push(mdb.NAME, ls[0]) if m.Push(mdb.NAME, ls[0]).Push(nfs.SIZE, ls[1]); i < 3 {
m.Push(nfs.SIZE, ls[1]) m.Push(mdb.VALUE, _tmux_cmd(m, SHOW_BUFFER, "-b", ls[0]).Result())
if i < 3 {
m.Push(mdb.TEXT, _tmux_cmd(m, SHOW_BUFFER, "-b", ls[0]).Result())
} else { } else {
m.Push(mdb.TEXT, ls[2][1:len(ls[2])-1]) m.Push(mdb.VALUE, ls[2][1:len(ls[2])-1])
} }
} }
m.StatusTimeCount().PushAction(mdb.REMOVE).Action(mdb.CREATE)
}}, }},
TEXT: {Name: "text auto save text:textarea", Help: "文本", Actions: ice.Actions{ TEXT: {Name: "text auto text:textarea", Help: "文本", Hand: func(m *ice.Message, arg ...string) {
nfs.SAVE: {Name: "save", Help: "保存", Hand: func(m *ice.Message, arg ...string) { kit.If(len(arg) > 0, func() { _tmux_cmd(m, SET_BUFFER, arg[0]) })
if len(arg) > 0 && arg[0] != "" { cli.PushText(m, _tmux_cmds(m, SHOW_BUFFER))
_tmux_cmd(m, SET_BUFFER, arg[0])
}
m.Cmdy(TEXT)
}},
}, Hand: func(m *ice.Message, arg ...string) {
text := _tmux_cmd(m, SHOW_BUFFER).Result()
if m.EchoQRCode(text).Echo(ice.NL); strings.HasPrefix(text, ice.HTTP) {
m.EchoAnchor(text)
} else {
m.EchoScript(text)
}
}}, }},
}) })
} }

View File

@ -10,7 +10,7 @@ const SCRIPT = "script"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
SCRIPT: {Name: "script name auto create export import", Help: "脚本", Actions: ice.MergeActions(ice.Actions{ SCRIPT: {Name: "script name auto create export import", Help: "脚本", Actions: ice.MergeActions(ice.Actions{
mdb.CREATE: {Name: "create type=shell,tmux,vim name=hi text:textarea=pwd", Help: "添加"}, mdb.CREATE: {Name: "create type=shell,tmux,vim name=hi text:textarea=pwd"},
}, mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,type,name,text"))}, }, mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,type,name,text"))},
}) })
} }

View File

@ -9,7 +9,6 @@ import (
"shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/web" "shylinux.com/x/icebergs/base/web"
"shylinux.com/x/icebergs/core/code"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
@ -24,12 +23,8 @@ func _tmux_key(arg ...string) string {
return "miss" return "miss"
} }
} }
func _tmux_cmd(m *ice.Message, arg ...string) *ice.Message { func _tmux_cmd(m *ice.Message, arg ...string) *ice.Message { return m.Cmd(cli.SYSTEM, TMUX, arg) }
return m.Cmd(cli.SYSTEM, TMUX, arg) func _tmux_cmds(m *ice.Message, arg ...string) string { return _tmux_cmd(m, arg...).Results() }
}
func _tmux_cmds(m *ice.Message, arg ...string) string {
return _tmux_cmd(m, arg...).Result()
}
const ( const (
FORMAT = "format" FORMAT = "format"
@ -69,24 +64,22 @@ const (
func init() { func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{ Index.Merge(&ice.Context{Configs: ice.Configs{
SESSION: {Name: SESSION, Help: "会话", Value: kit.Data( SESSION: {Value: kit.Data(
FORMAT, "#{session_id},#{session_attached},#{session_name},#{session_windows},#{session_height},#{session_width}", FORMAT, "#{session_id},#{session_attached},#{session_name},#{session_windows},#{session_height},#{session_width}",
FIELDS, "id,tag,session,windows,height,width", FIELDS, "id,tag,session,windows,height,width",
)}, )},
WINDOW: {Name: WINDOW, Help: "窗口", Value: kit.Data( WINDOW: {Value: kit.Data(
FORMAT, "#{window_id},#{window_active},#{window_name},#{window_panes},#{window_height},#{window_width}", FORMAT, "#{window_id},#{window_active},#{window_name},#{window_panes},#{window_height},#{window_width}",
FIELDS, "id,tag,window,panes,height,width", FIELDS, "id,tag,window,panes,height,width",
)}, )},
PANE: {Name: PANE, Help: "终端", Value: kit.Data( PANE: {Value: kit.Data(
FORMAT, "#{pane_id},#{pane_active},#{pane_index},#{pane_tty},#{pane_height},#{pane_width},#{pane_current_command}", FORMAT, "#{pane_id},#{pane_active},#{pane_index},#{pane_tty},#{pane_height},#{pane_width},#{pane_current_command}",
FIELDS, "id,tag,pane,tty,height,width,cmd", FIELDS, "id,tag,pane,tty,height,width,cmd",
)}, )},
}, Commands: ice.Commands{ }, Commands: ice.Commands{
SESSION: {Name: "session session window pane cmd auto", Help: "会话管理", Actions: ice.Actions{ SESSION: {Name: "session session window pane cmd auto", Help: "会话管理", Actions: ice.MergeActions(ice.Actions{
web.DREAM_CREATE: {Name: "dream.create", Help: "梦想", Hand: func(m *ice.Message, arg ...string) { web.DREAM_CREATE: {Hand: func(m *ice.Message, arg ...string) {
if m.Cmd("", m.Option(mdb.NAME)).Length() == 0 { kit.If(m.Cmd("", m.Option(mdb.NAME)).Length() == 0, func() { m.Cmd("", mdb.CREATE) })
m.Cmd("", mdb.CREATE)
}
}}, }},
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {
if m.Option(ctx.ACTION) == SCRIPT { if m.Option(ctx.ACTION) == SCRIPT {
@ -98,24 +91,18 @@ func init() {
m.Cmdy(web.DREAM).Cut("name,size,time") m.Cmdy(web.DREAM).Cut("name,size,time")
} }
}}, }},
mdb.CREATE: {Name: "create name", Help: "添加", Hand: func(m *ice.Message, arg ...string) { mdb.CREATE: {Name: "create name", Hand: func(m *ice.Message, arg ...string) {
m.Option(cli.CMD_ENV, "TMUX", "") if m.Option(cli.CMD_ENV, "TMUX", ""); m.Option(PANE) != "" {
if m.Option(PANE) != "" { // 创建终端
_tmux_cmd(m, SPLIT_WINDOW, "-t", _tmux_key(m.Option(SESSION), m.Option(WINDOW), m.Option(PANE))) _tmux_cmd(m, SPLIT_WINDOW, "-t", _tmux_key(m.Option(SESSION), m.Option(WINDOW), m.Option(PANE)))
} else if m.Option(WINDOW) != "" {
} else if m.Option(WINDOW) != "" { // 创建终端
_tmux_cmd(m, SPLIT_WINDOW, "-t", _tmux_key(m.Option(SESSION), m.Option(WINDOW))) _tmux_cmd(m, SPLIT_WINDOW, "-t", _tmux_key(m.Option(SESSION), m.Option(WINDOW)))
} else if m.Option(SESSION) != "" {
} else if m.Option(SESSION) != "" { // 创建窗口
_tmux_cmd(m, NEW_WINDOW, "-d", "-t", m.Option(SESSION), "-n", m.Option(mdb.NAME)) _tmux_cmd(m, NEW_WINDOW, "-d", "-t", m.Option(SESSION), "-n", m.Option(mdb.NAME))
} else {
} else { // 创建会话
m.Option(cli.CMD_DIR, path.Join(ice.USR_LOCAL_WORK, m.Option(mdb.NAME))) m.Option(cli.CMD_DIR, path.Join(ice.USR_LOCAL_WORK, m.Option(mdb.NAME)))
ls := kit.Split(m.Option(mdb.NAME), "-") ls := kit.Split(m.Option(mdb.NAME), "-")
name := kit.Select(ls[0], ls, 1) name := kit.Select(ls[0], ls, 1)
_tmux_cmd(m, NEW_SESSION, "-d", "-s", m.Option(mdb.NAME), "-n", name) _tmux_cmd(m, NEW_SESSION, "-d", "-s", m.Option(mdb.NAME), "-n", name)
name = _tmux_key(m.Option(mdb.NAME), name) name = _tmux_key(m.Option(mdb.NAME), name)
_tmux_cmd(m, SPLIT_WINDOW, "-t", kit.Keys(name, "1"), "-p", "40") _tmux_cmd(m, SPLIT_WINDOW, "-t", kit.Keys(name, "1"), "-p", "40")
m.Go(func() { m.Go(func() {
@ -123,103 +110,76 @@ func init() {
_tmux_cmd(m, SEND_KEYS, "-t", kit.Keys(name, "2"), "ish_miss_log", ENTER) _tmux_cmd(m, SEND_KEYS, "-t", kit.Keys(name, "2"), "ish_miss_log", ENTER)
_tmux_cmd(m, SEND_KEYS, "-t", kit.Keys(name, "1"), "vi etc/miss.sh", ENTER) _tmux_cmd(m, SEND_KEYS, "-t", kit.Keys(name, "1"), "vi etc/miss.sh", ENTER)
}) })
if m.Cmd(PANE, _tmux_key("miss", name)).Length() == 0 {
_tmux_cmd(m, LINK_WINDOW, "-s", name, "-t", "miss:") _tmux_cmd(m, LINK_WINDOW, "-s", name, "-t", "miss:")
}
} }
}}, }},
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) { mdb.REMOVE: {Hand: func(m *ice.Message, arg ...string) {
if m.Option(PANE) != "" { // 删除终端 if m.Option(PANE) != "" {
_tmux_cmd(m, KILL_PANE, "-t", _tmux_key(m.Option(SESSION), m.Option(WINDOW), m.Option(PANE))) _tmux_cmd(m, KILL_PANE, "-t", kit.Select(_tmux_key(m.Option(SESSION), m.Option(WINDOW), m.Option(PANE)), m.Option(mdb.ID)))
} else if m.Option(WINDOW) != "" {
} else if m.Option(WINDOW) != "" { // 删除窗口 _tmux_cmd(m, KILL_WINDOW, "-t", kit.Select(_tmux_key(m.Option(SESSION), m.Option(WINDOW)), m.Option(mdb.ID)))
// _tmux_cmd(m, KILL_WINDOW, "-t", _tmux_key(m.Option(SESSION), m.Option(WINDOW))) } else if m.Option(SESSION) != "" {
_tmux_cmd(m, KILL_WINDOW, "-t", _tmux_key(m.Option(SESSION), m.Option(mdb.ID)))
} else if m.Option(SESSION) != "" { // 删除会话
_tmux_cmd(m, KILL_SESSION, "-t", m.Option(SESSION)) _tmux_cmd(m, KILL_SESSION, "-t", m.Option(SESSION))
} }
}}, }},
mdb.MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) { mdb.MODIFY: {Hand: func(m *ice.Message, arg ...string) {
switch arg[0] { switch arg[0] {
case WINDOW: // 重命名窗口 case WINDOW:
_tmux_cmd(m, RENAME_WINDOW, "-t", _tmux_key(m.Option(SESSION), m.Option(WINDOW)), arg[1]) _tmux_cmd(m, RENAME_WINDOW, "-t", _tmux_key(m.Option(SESSION), m.Option(WINDOW)), arg[1])
case SESSION:
case SESSION: // 重命名会话
_tmux_cmd(m, RENAME_SESSION, "-t", m.Option(SESSION), arg[1]) _tmux_cmd(m, RENAME_SESSION, "-t", m.Option(SESSION), arg[1])
} }
}}, }},
mdb.SELECT: {Name: "select", Help: "进入", Hand: func(m *ice.Message, arg ...string) { mdb.SELECT: {Help: "切入", Hand: func(m *ice.Message, arg ...string) {
_tmux_cmd(m, SWITCH_CLIENT, "-t", m.Option(SESSION)) if _tmux_cmd(m, SWITCH_CLIENT, "-t", m.Option(SESSION)); m.Option(WINDOW) != "" {
if m.Option(WINDOW) != "" { // 切换窗口 _tmux_cmd(m, SELECT_WINDOW, "-t", kit.Select(_tmux_key(m.Option(SESSION), m.Option(WINDOW)), m.Option(mdb.ID)))
_tmux_cmd(m, SELECT_WINDOW, "-t", _tmux_key(m.Option(SESSION), m.Option(WINDOW)))
} }
if m.Option(PANE) != "" { // 切换终端 if m.Option(PANE) != "" {
_tmux_cmd(m, SELECT_PANE, "-t", _tmux_key(m.Option(SESSION), m.Option(WINDOW), m.Option(PANE))) _tmux_cmd(m, SELECT_PANE, "-t", _tmux_key(m.Option(SESSION), m.Option(WINDOW), m.Option(PANE)))
} }
}}, }},
code.XTERM: {Name: "xterm", Help: "终端", Hand: func(m *ice.Message, arg ...string) {
ctx.Process(m, code.XTERM, []string{mdb.TYPE, "tmux attach -t " + m.Option(SESSION)}, arg...)
}},
SCRIPT: {Name: "script name", Help: "脚本", Hand: func(m *ice.Message, arg ...string) { SCRIPT: {Name: "script name", Help: "脚本", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(SCRIPT, m.Option(mdb.NAME), func(value ice.Maps) { m.Cmd(SCRIPT, m.Option(mdb.NAME), func(value ice.Maps) {
switch value[mdb.TYPE] { kit.Fetch(kit.SplitLine(value[mdb.TEXT]), func(line string) {
case "shell": kit.Switch(value[mdb.TYPE],
for _, line := range kit.Split(value[mdb.TEXT], ice.NL, ice.NL, ice.NL) { "shell", func() { m.Cmd(CMD, _tmux_key(m.Option(SESSION), m.Option(WINDOW), m.Option(PANE)), line) },
m.Cmd(CMD, _tmux_key(m.Option(SESSION), m.Option(WINDOW), m.Option(PANE)), line) "vim", func() { m.Cmd(CMD, _tmux_key(m.Option(SESSION), m.Option(WINDOW), m.Option(PANE)), line) },
} "tmux", func() { _tmux_cmd(m, line) },
case "vim": )
for _, line := range kit.Split(value[mdb.TEXT], ice.NL, ice.NL, ice.NL) { })
m.Cmd(CMD, _tmux_key(m.Option(SESSION), m.Option(WINDOW), m.Option(PANE)), line) }).Sleep30ms()
}
case "tmux":
for _, line := range kit.Split(value[mdb.TEXT], ice.NL, ice.NL, ice.NL) {
_tmux_cmd(m, line)
}
}
})
m.Sleep30ms()
}}, }},
}, Hand: func(m *ice.Message, arg ...string) { }, ctx.CmdAction()), Hand: func(m *ice.Message, arg ...string) {
m.Action(SCRIPT) if m.Action(SCRIPT); len(arg) > 3 {
if len(arg) > 3 { // 执行命令
m.Cmd(CMD, _tmux_key(arg[0], arg[1], arg[2]), arg[3:]) m.Cmd(CMD, _tmux_key(arg[0], arg[1], arg[2]), arg[3:])
} }
if len(arg) > 2 { // 终端内容 if len(arg) > 2 {
m.Echo(strings.TrimSpace(m.Cmdx(VIEW, _tmux_key(arg[0], arg[1], arg[2])))) m.Echo(strings.TrimSpace(m.Cmdx(VIEW, _tmux_key(arg[0], arg[1], arg[2]))))
return return
} }
if m.Action(mdb.CREATE); len(arg) > 1 {
m.Action(mdb.CREATE)
if len(arg) > 1 { // 终端列表
m.Cmdy(PANE, _tmux_key(arg[0], arg[1])) m.Cmdy(PANE, _tmux_key(arg[0], arg[1]))
} else if len(arg) > 0 {
} else if len(arg) > 0 { // 窗口列表
m.Cmdy(WINDOW, arg[0]) m.Cmdy(WINDOW, arg[0])
} else {
} else { // 会话列表
m.Split(_tmux_cmd(m, LIST_SESSION, "-F", m.Config(FORMAT)).Result(), m.Config(FIELDS), ice.FS, ice.NL) m.Split(_tmux_cmd(m, LIST_SESSION, "-F", m.Config(FORMAT)).Result(), m.Config(FIELDS), ice.FS, ice.NL)
} }
m.Tables(func(value ice.Maps) { m.Tables(func(value ice.Maps) {
switch value["tag"] { kit.If(value["tag"] == "1", func() { m.PushButton("") }, func() { m.PushButton(mdb.SELECT, mdb.REMOVE) })
case "1": }).StatusTimeCount()
m.PushButton(code.XTERM, "")
default:
m.PushButton(code.XTERM, mdb.SELECT, mdb.REMOVE)
}
})
}}, }},
WINDOW: {Name: "windows", Help: "窗口", Hand: func(m *ice.Message, arg ...string) { WINDOW: {Hand: func(m *ice.Message, arg ...string) {
m.Split(m.Cmdx(cli.SYSTEM, TMUX, LIST_WINDOWS, "-t", kit.Select("", arg, 0), "-F", m.Config(FORMAT)), m.Config(FIELDS), ice.FS, ice.NL) m.Split(m.Cmdx(cli.SYSTEM, TMUX, LIST_WINDOWS, "-t", kit.Select("", arg, 0), "-F", m.Config(FORMAT)), m.Config(FIELDS), ice.FS, ice.NL)
}}, }},
PANE: {Name: "panes", Help: "终端", Hand: func(m *ice.Message, arg ...string) { PANE: {Hand: func(m *ice.Message, arg ...string) {
m.Split(_tmux_cmds(m, LIST_PANES, "-t", kit.Select("", arg, 0), "-F", m.Config(FORMAT)), m.Config(FIELDS), ice.FS, ice.NL) m.Split(_tmux_cmds(m, LIST_PANES, "-t", kit.Select("", arg, 0), "-F", m.Config(FORMAT)), m.Config(FIELDS), ice.FS, ice.NL)
}}, }},
VIEW: {Name: "view", Help: "内容", Hand: func(m *ice.Message, arg ...string) { VIEW: {Hand: func(m *ice.Message, arg ...string) {
m.Echo(_tmux_cmds(m, CAPTURE_PANE, "-p", "-t", kit.Select("", arg, 0))) m.Echo(_tmux_cmds(m, CAPTURE_PANE, "-p", "-t", kit.Select("", arg, 0)))
}}, }},
CMD: {Name: "cmd", Help: "命令", Hand: func(m *ice.Message, arg ...string) { CMD: {Hand: func(m *ice.Message, arg ...string) {
_tmux_cmd(m, SEND_KEYS, "-t", arg[0], strings.Join(arg[1:], ice.SP), ENTER) _tmux_cmd(m, SEND_KEYS, "-t", arg[0], strings.Join(arg[1:], ice.SP), ENTER)
}}, }},
}}) }})

View File

@ -13,14 +13,14 @@ const TMUX = "tmux"
var Index = &ice.Context{Name: TMUX, Help: "工作台", Commands: ice.Commands{ var Index = &ice.Context{Name: TMUX, Help: "工作台", Commands: ice.Commands{
TMUX: {Name: "tmux path auto start order build download", Help: "服务", Actions: ice.MergeActions(ice.Actions{ TMUX: {Name: "tmux path auto start order build download", Help: "服务", Actions: ice.MergeActions(ice.Actions{
cli.START: {Name: "start", Help: "启动", Hand: func(m *ice.Message, arg ...string) { cli.START: {Help: "启动", Hand: func(m *ice.Message, arg ...string) {
m.Optionv(code.PREPARE, func(p string) []string { m.Optionv(code.PREPARE, func(p string) []string {
return []string{"-S", kit.Path(m.Option(cli.CMD_DIR, p), "tmux.socket"), NEW_SESSION, "-d", "-n", "miss"} return []string{"-S", kit.Path(m.Option(cli.CMD_DIR, p), "tmux.socket"), NEW_SESSION, "-d", "-n", "miss"}
}) })
m.Cmdy(code.INSTALL, cli.START, m.Config(nfs.SOURCE), "bin/tmux") m.Cmdy(code.INSTALL, cli.START, m.Config(nfs.SOURCE), "bin/tmux")
}}, }},
}, code.InstallAction(nfs.SOURCE, "http://mirrors.tencent.com/macports/distfiles/tmux/tmux-3.2.tar.gz")), Hand: func(m *ice.Message, arg ...string) { }, code.InstallAction(nfs.SOURCE, "http://mirrors.tencent.com/macports/distfiles/tmux/tmux-3.2.tar.gz")), Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(code.INSTALL, nfs.SOURCE, m.Config(nfs.SOURCE), arg) m.Cmdy(code.INSTALL, m.ConfigSimple(nfs.SOURCE), arg)
}}, }},
}} }}

View File

@ -17,22 +17,18 @@ type WebView struct {
} }
func (w WebView) Menu() bool { func (w WebView) Menu() bool {
list := []string{} link, list := "", []string{}
link := ""
w.Cmd(nfs.CAT, w.Source, func(ls []string, line string) { w.Cmd(nfs.CAT, w.Source, func(ls []string, line string) {
if strings.HasPrefix(line, "# ") { if strings.HasPrefix(line, "# ") {
return return
} } else if len(ls) > 1 {
if len(ls) > 1 { link, list = ls[1], append(list, kit.Format(`<button onclick=%s()>%s</button>`, ls[0], ls[0]))
list = append(list, kit.Format(`<button onclick=%s()>%s</button>`, ls[0], ls[0]))
w.WebView.Bind(ls[0], func() { w.navigate(ls[1]) }) w.WebView.Bind(ls[0], func() { w.navigate(ls[1]) })
link = ls[1]
} }
}) })
if len(list) == 0 { if len(list) == 0 {
return false return false
} } else if len(list) == 1 {
if len(list) == 1 {
if ls := kit.Split(w.Cmdx(nfs.CAT, "etc/webview.size")); len(ls) > 1 { if ls := kit.Split(w.Cmdx(nfs.CAT, "etc/webview.size")); len(ls) > 1 {
w.WebView.SetSize(kit.Int(ls[0]), kit.Int(ls[1])+28, webview.HintNone) w.WebView.SetSize(kit.Int(ls[0]), kit.Int(ls[1])+28, webview.HintNone)
} else { } else {
@ -40,11 +36,57 @@ func (w WebView) Menu() bool {
} }
w.WebView.Navigate(link) w.WebView.Navigate(link)
return true return true
} else {
w.WebView.SetTitle(ice.CONTEXTS)
w.WebView.SetSize(200, 60*len(list), webview.HintNone)
w.WebView.Navigate(kit.Format(_menu_template, kit.Join(list, ice.NL)))
return true
} }
}
func (w WebView) Title(text string) { w.WebView.SetTitle(text) }
func (w WebView) Webview(url string) { w.WebView.Navigate(url) }
func (w WebView) Open(url string) { w.WebView.Navigate(url) }
func (w WebView) OpenUrl(url string) { w.Cmd(cli.SYSTEM, cli.OPEN, url) }
func (w WebView) OpenApp(app string) { w.Cmd(cli.SYSTEM, cli.OPEN, "-a", app) }
func (w WebView) OpenCmd(cmd string) {
w.Cmd(nfs.SAVE, kit.HomePath(".bash_temp"), cmd)
w.Cmd(cli.SYSTEM, cli.OPEN, "-a", "Terminal")
}
func (w WebView) SetSize(width, height int) {
w.Cmd(nfs.SAVE, "etc/webview.size", kit.Format("%v,%v", width, height))
}
func (w WebView) System(arg ...string) string { return w.Cmdx(cli.SYSTEM, arg) }
func (w WebView) Power() string {
ls := strings.Split(w.Cmdx(cli.SYSTEM, "pmset", "-g", "ps"), ice.NL)
for _, line := range ls[1:] {
ls := kit.Split(line, "\t ;", "\t ;")
return ls[2]
}
return ""
}
func (w WebView) Close() {
if !w.Menu() {
w.WebView.Terminate()
}
}
func (w WebView) Terminate() { w.WebView.Terminate() }
func (w WebView) navigate(url string) {
w.WebView.SetSize(1200, 800, webview.HintNone)
w.WebView.Navigate(url)
}
w.WebView.SetTitle(ice.CONTEXTS) func Run(cb func(*WebView) ice.Any) {
w.WebView.SetSize(200, 60*len(list), webview.HintNone) w := webview.New(true)
w.WebView.Navigate(kit.Format(`data:text/html, defer w.Destroy()
defer w.Run()
view := &WebView{Source: "etc/webview.txt", WebView: w, Message: ice.Pulse}
kit.Reflect(cb(view), func(name string, value ice.Any) { w.Bind(name, value) })
if !view.Menu() {
view.navigate("http://localhost:9020")
}
}
var _menu_template = `data:text/html,
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
@ -60,52 +102,4 @@ func (w WebView) Menu() bool {
</script> </script>
</head> </head>
<body>%s</body> <body>%s</body>
</html>`, kit.Join(list, ice.NL))) </html>`
return true
}
func (w WebView) Title(text string) { w.WebView.SetTitle(text) }
func (w WebView) Webview(url string) { w.WebView.Navigate(url) }
func (w WebView) Open(url string) { w.WebView.Navigate(url) }
func (w WebView) OpenUrl(url string) { w.Cmd(cli.SYSTEM, "open", url) }
func (w WebView) OpenApp(app string) { w.Cmd(cli.SYSTEM, "open", "-a", app) }
func (w WebView) OpenCmd(cmd string) {
w.Cmd(nfs.SAVE, kit.HomePath(".bash_temp"), cmd)
w.Cmd(cli.SYSTEM, "open", "-a", "Terminal")
}
func (w WebView) SetSize(width, height int) {
w.Cmd(nfs.SAVE, "etc/webview.size", kit.Format("%v,%v", width, height))
}
func (w WebView) System(arg ...string) string {
return w.Cmdx(cli.SYSTEM, arg)
}
func (w WebView) Power() string {
ls := strings.Split(w.Cmdx(cli.SYSTEM, "pmset", "-g", "ps"), ice.NL)
for _, line := range ls[1:] {
ls := kit.Split(line, "\t ;", "\t ;")
return ls[2]
}
return ""
}
func (w WebView) Terminate() { w.WebView.Terminate() }
func (w WebView) Close() {
if !w.Menu() {
w.WebView.Terminate()
}
}
func (w WebView) navigate(url string) {
w.WebView.SetSize(1200, 800, webview.HintNone)
w.WebView.Navigate(url)
}
func Run(cb func(*WebView) ice.Any) {
w := webview.New(true)
defer w.Destroy()
defer w.Run()
view := &WebView{Source: "etc/webview.txt", WebView: w, Message: ice.Pulse}
kit.Reflect(cb(view), func(name string, value ice.Any) { w.Bind(name, value) })
if !view.Menu() {
view.navigate("http://localhost:9020")
}
}