diff --git a/base/aaa/email.go b/base/aaa/email.go index 3aff97de..97ff47f4 100644 --- a/base/aaa/email.go +++ b/base/aaa/email.go @@ -32,8 +32,7 @@ func init() { } content := []byte(kit.JoinKV(DF, NL, "From", m.Option(USERNAME), "To", m.Option(TO), "Subject", m.Option(SUBJECT), "Content-Type", "text/html; charset=UTF-8") + NL + NL + m.Option(CONTENT)) auth := smtp.PlainAuth("", m.Option(USERNAME), m.Option(PASSWORD), kit.Split(m.Option(SERVICE), ice.DF)[0]) - m.Warn(smtp.SendMail(m.Option(SERVICE), auth, m.Option(USERNAME), kit.Split(m.Option(TO)), content)) - m.Logs(EMAIL, SEND, string(content)) + m.Logs(EMAIL, SEND, string(content)).Warn(smtp.SendMail(m.Option(SERVICE), auth, m.Option(USERNAME), kit.Split(m.Option(TO)), content)) }}, }, mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,name,service,username,password", ice.ACTION, SEND))}, }) diff --git a/base/aaa/offer.go b/base/aaa/offer.go index 23fbbde2..cbdb1975 100644 --- a/base/aaa/offer.go +++ b/base/aaa/offer.go @@ -2,7 +2,6 @@ package aaa import ( ice "shylinux.com/x/icebergs" - "shylinux.com/x/icebergs/base/gdb" "shylinux.com/x/icebergs/base/mdb" kit "shylinux.com/x/toolkits" ) @@ -17,9 +16,9 @@ func init() { Index.MergeCommands(ice.Commands{ OFFER: {Name: "offer hash auto", Help: "邀请", Actions: ice.MergeActions(ice.Actions{ INVITE: {Name: "invite email*='shylinux@163.com' subject content", Help: "邀请", Hand: func(m *ice.Message, arg ...string) { - h := mdb.HashCreate(m.Spawn(), m.OptionSimple(EMAIL, SUBJECT, CONTENT), "from", m.Option(ice.MSG_USERNAME), mdb.STATUS, INVITE) + h := mdb.HashCreate(m.Spawn(), m.OptionSimple(EMAIL, SUBJECT, CONTENT), INVITE, m.Option(ice.MSG_USERNAME), mdb.STATUS, INVITE) m.Cmd(EMAIL, SEND, m.Option(EMAIL), m.OptionDefault(SUBJECT, "welcome to contents, please continue"), - m.OptionDefault(CONTENT, ice.Render(m, ice.RENDER_ANCHOR, m.Cmdx("host", "publish", m.MergePodCmd("", "", mdb.HASH, h, gdb.DEBUG, ice.TRUE)))), + m.OptionDefault(CONTENT, ice.Render(m, ice.RENDER_ANCHOR, m.Cmdx("host", "publish", m.MergePodCmd("", "", mdb.HASH, h)))), ) }}, ACCEPT: {Help: "接受", Hand: func(m *ice.Message, arg ...string) { @@ -29,11 +28,11 @@ func init() { msg := m.Cmd("", m.Option(mdb.HASH)) if ls := kit.Split(msg.Append(EMAIL), ice.AT); !m.Warn(msg.Length() == 0 || len(ls) < 2, ice.ErrNotValid, m.Option(mdb.HASH)) { m.Cmd(USER, mdb.CREATE, USERNICK, ls[0], USERNAME, msg.Append(EMAIL), USERZONE, ls[1]) - m.ProcessOpen(kit.MergeURL2(m.Option(ice.MSG_USERWEB), ice.PS, ice.MSG_SESSID, SessCreate(m, msg.Append(EMAIL)), mdb.HASH, "", gdb.DEBUG, ice.TRUE)) + m.ProcessOpen(kit.MergeURL2(m.Option(ice.MSG_USERWEB), ice.PS, ice.MSG_SESSID, SessCreate(m, msg.Append(EMAIL)), mdb.HASH, "")) mdb.HashModify(m, m.OptionSimple(mdb.HASH), mdb.STATUS, ACCEPT) } }}, - }, mdb.HashAction(mdb.SHORT, mdb.UNIQ, mdb.FIELD, "time,hash,status,from,email,title,content"), RoleAction(ACCEPT)), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashAction(mdb.SHORT, mdb.UNIQ, mdb.FIELD, "time,hash,status,invite,email,title,content"), RoleAction(ACCEPT)), Hand: func(m *ice.Message, arg ...string) { if !m.Warn(len(arg) == 0 && m.Option(ice.MSG_USERROLE) == VOID, ice.ErrNotRight) { kit.If(mdb.HashSelect(m, arg...).FieldsIsDetail(), func() { m.PushAction(ACCEPT) }, func() { m.Action(INVITE) }) } diff --git a/base/aaa/sess.go b/base/aaa/sess.go index 837969ca..5ca970a4 100644 --- a/base/aaa/sess.go +++ b/base/aaa/sess.go @@ -50,6 +50,10 @@ func SessCheck(m *ice.Message, sessid string) bool { return sessid != "" && m.Cmdy(SESS, CHECK, sessid, logs.FileLineMeta(-1)).Option(ice.MSG_USERNAME) != "" } func SessAuth(m *ice.Message, value ice.Any, arg ...string) *ice.Message { + switch val := value.(type) { + case []string: + value = kit.Dict(USERNICK, kit.Select("", val, 0), USERNAME, kit.Select("", val, 1), USERROLE, kit.Select("", val, 2)) + } return m.Auth( USERNICK, m.Option(ice.MSG_USERNICK, kit.Value(value, USERNICK)), USERNAME, m.Option(ice.MSG_USERNAME, kit.Value(value, USERNAME)), diff --git a/base/cli/color.go b/base/cli/color.go new file mode 100644 index 00000000..caffe811 --- /dev/null +++ b/base/cli/color.go @@ -0,0 +1,78 @@ +package cli + +import ( + "fmt" + "image/color" + "math/rand" + "strconv" + "strings" + + ice "shylinux.com/x/icebergs" + kit "shylinux.com/x/toolkits" +) + +const ( + _DARK = 255 + _LIGHT = 127 +) + +var _color_map = map[string]color.Color{ + BLACK: color.RGBA{0, 0, 0, _DARK}, + RED: color.RGBA{_DARK, 0, 0, _DARK}, + GREEN: color.RGBA{0, _DARK, 0, _DARK}, + YELLOW: color.RGBA{_DARK, _DARK, 0, _DARK}, + BLUE: color.RGBA{0, 0, _DARK, _DARK}, + PURPLE: color.RGBA{_DARK, 0, _DARK, _DARK}, + CYAN: color.RGBA{0, _DARK, _DARK, _DARK}, + WHITE: color.RGBA{_DARK, _DARK, _DARK, _DARK}, +} + +func _parse_color(str string) color.Color { + if str == RANDOM { + list := kit.SortedKey(_color_map) + str = list[rand.Intn(len(list))] + } + if strings.HasPrefix(str, "#") { + kit.If(len(str) == 7, func() { str += "ff" }) + if u, e := strconv.ParseUint(str[1:], 16, 64); e == nil { + return color.RGBA{uint8((u & 0xFF000000) >> 24), uint8((u & 0x00FF0000) >> 16), uint8((u & 0x0000FF00) >> 8), uint8((u & 0x000000FF) >> 0)} + } + } + return _color_map[str] +} +func _parse_cli_color(str string) string { + res := 0 + r, g, b, _ := _parse_color(str).RGBA() + kit.If(r > _LIGHT, func() { res += 1 }) + kit.If(g > _LIGHT, func() { res += 2 }) + kit.If(b > _LIGHT, func() { res += 4 }) + return kit.Format(res) +} + +const ( + BG = "bg" + FG = "fg" + COLOR = "color" + BLACK = "black" + WHITE = "white" + BLUE = "blue" + RED = "red" + GRAY = "gray" + CYAN = "cyan" + GREEN = "green" + PURPLE = "purple" + YELLOW = "yellow" + RANDOM = "random" + GLASS = "#0000" +) + +func Color(m *ice.Message, c string, str ice.Any) string { + wrap, color := `%v`, c + kit.If(m.IsCliUA(), func() { wrap, color = "\033[3%sm%v\033[0m", _parse_cli_color(c) }) + return fmt.Sprintf(wrap, color, 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 ColorYellow(m *ice.Message, str ice.Any) string { return Color(m, YELLOW, str) } +func ParseCliColor(color string) string { return _parse_cli_color(color) } +func ParseColor(color string) color.Color { return _parse_color(color) } diff --git a/base/cli/daemon.go b/base/cli/daemon.go index 543356b0..a4997a17 100644 --- a/base/cli/daemon.go +++ b/base/cli/daemon.go @@ -4,7 +4,6 @@ import ( "io" "os/exec" "runtime" - "strings" ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/ctx" @@ -24,8 +23,8 @@ func _daemon_exec(m *ice.Message, cmd *exec.Cmd) { if w := _system_out(m, CMD_ERRPUT); w != nil { cmd.Stderr = w } - h := mdb.HashCreate(m.Spawn(), ice.CMD, kit.Join(cmd.Args, ice.SP), - STATUS, START, DIR, cmd.Dir, ENV, kit.Select("", cmd.Env), + h := mdb.HashCreate(m.Spawn(), STATUS, START, + ice.CMD, kit.Join(cmd.Args, ice.SP), DIR, cmd.Dir, ENV, kit.Select("", cmd.Env), m.OptionSimple(CMD_INPUT, CMD_OUTPUT, CMD_ERRPUT, mdb.CACHE_CLEAR_ON_EXIT), ) if e := cmd.Start(); m.Warn(e, ice.ErrNotStart, cmd.Args) { @@ -36,21 +35,14 @@ func _daemon_exec(m *ice.Message, cmd *exec.Cmd) { m.Echo("%d", cmd.Process.Pid) m.Go(func() { if e := cmd.Wait(); !m.Warn(e, ice.ErrNotStart, cmd.Args) && cmd.ProcessState != nil && cmd.ProcessState.Success() { - m.Cost(CODE, "0", ctx.ARGS, cmd.Args) mdb.HashModify(m, mdb.HASH, h, STATUS, STOP) + m.Cost(CODE, "0", ctx.ARGS, cmd.Args) } else { - mdb.HashSelectUpdate(m, h, func(value ice.Map) { - if value[STATUS] == START { - value[STATUS], value[ERROR] = ERROR, e - } - }) + mdb.HashSelectUpdate(m, h, func(value ice.Map) { kit.If(value[STATUS] == START, func() { value[STATUS], value[ERROR] = ERROR, e }) }) } - status := mdb.HashSelectField(m, h, STATUS) - switch m.Sleep300ms(); cb := m.OptionCB("").(type) { + switch status := mdb.HashSelectField(m.Sleep300ms(), h, STATUS); cb := m.OptionCB("").(type) { case func(string) bool: - if !cb(status) { - m.Cmdy(DAEMON, cmd.Path, cmd.Args) - } + kit.If(!cb(status), func() { m.Cmdy(DAEMON, cmd.Path, cmd.Args) }) case func(string): cb(status) case func(): @@ -107,20 +99,15 @@ const DAEMON = "daemon" func init() { Index.MergeCommands(ice.Commands{ DAEMON: {Name: "daemon hash auto", Help: "守护进程", Actions: ice.MergeActions(ice.Actions{ - ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) { - mdb.HashPrunesValue(m, mdb.CACHE_CLEAR_ON_EXIT, ice.TRUE) - }}, + ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) { mdb.HashPrunesValue(m, mdb.CACHE_CLEAR_ON_EXIT, ice.TRUE) }}, START: {Name: "start cmd* dir env", Hand: func(m *ice.Message, arg ...string) { m.Options(CMD_DIR, m.Option(DIR), CMD_ENV, kit.Split(m.Option(ENV), " =")) _daemon_exec(m, _system_cmd(m, kit.Split(m.Option(ice.CMD))...)) }}, - RESTART: {Hand: func(m *ice.Message, arg ...string) { - m.Cmdy("", STOP).Sleep3s().Cmdy("", START) - }}, + RESTART: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy("", STOP).Sleep3s().Cmdy("", START) }}, STOP: {Hand: func(m *ice.Message, arg ...string) { - m.OptionFields(mdb.HashField(m)) h, pid := m.Option(mdb.HASH), m.Option(PID) - mdb.HashSelect(m, m.Option(mdb.HASH)).Table(func(value ice.Maps) { + mdb.HashSelects(m, h).Table(func(value ice.Maps) { if h == "" && value[PID] != pid { return } @@ -129,23 +116,18 @@ func init() { }) }}, }, mdb.StatusHashAction(mdb.FIELD, "time,hash,status,pid,cmd,dir,env")), Hand: func(m *ice.Message, arg ...string) { - if len(arg) == 0 || !strings.Contains(arg[0], ice.PS) { - if mdb.HashSelect(m, kit.Slice(arg, 0, 1)...).Table(func(value ice.Maps) { - switch value[STATUS] { - case START: - m.PushButton(RESTART, STOP) - default: - m.PushButton(START, mdb.REMOVE) - } - }); len(arg) == 0 || m.Length() > 0 { - if len(arg) == 0 { - m.Action(START, mdb.PRUNES) - } - return + mdb.HashSelect(m, arg...).Table(func(value ice.Maps) { + switch value[STATUS] { + case START: + m.PushButton(RESTART, STOP) + default: + m.PushButton(START, mdb.REMOVE) } - } - if _daemon_exec(m, _system_cmd(m, kit.Simple(kit.Split(arg[0]), arg[1:])...)); IsSuccess(m) && m.Append(CMD_ERR) == "" { - m.SetAppend() + }) + kit.If(len(arg) == 0, func() { m.Action(START, mdb.PRUNES) }) + if len(arg) > 0 && m.Length() == 0 { + _daemon_exec(m, _system_cmd(m, kit.Simple(kit.Split(arg[0]), arg[1:])...)) + kit.If(IsSuccess(m) && m.Append(CMD_ERR) == "", func() { m.SetAppend() }) } }}, }) diff --git a/base/cli/forever.go b/base/cli/forever.go index 7ecb16d0..e7e8aa5c 100644 --- a/base/cli/forever.go +++ b/base/cli/forever.go @@ -11,17 +11,17 @@ import ( "shylinux.com/x/toolkits/logs" ) -func _path_sep() string { - return kit.Select(":", ";", strings.Contains(os.Getenv(PATH), ";")) -} +func _path_sep() string { return kit.Select(ice.DF, ";", strings.Contains(os.Getenv(PATH), ";")) } func BinPath(arg ...string) string { list := []string{} - push := func(p string) { kit.If(kit.IndexOf(list, p) == -1, func() { list = append(list, p) }) } + push := func(p string) { + kit.If(kit.IndexOf(list, p) == -1, func() { list = append(list, kit.ReplaceAll(p, "\\", ice.PS)) }) + } kit.For(arg, func(p string) { list = append(list, kit.Path(p, ice.BIN), kit.Path(p, ice.USR_PUBLISH), kit.Path(p, ice.USR_LOCAL_BIN), kit.Path(p, ice.USR_LOCAL_GO_BIN)) - for _, l := range kit.Reverse(strings.Split(ice.Pulse.Cmdx(nfs.CAT, kit.Path(p, ice.ETC_PATH)), ice.NL)) { + kit.For(kit.Reverse(strings.Split(ice.Pulse.Cmdx(nfs.CAT, kit.Path(p, ice.ETC_PATH)), ice.NL)), func(l string) { kit.If(strings.TrimSpace(l) != "" && !strings.HasPrefix(strings.TrimSpace(l), "#"), func() { push(kit.Path(p, l)) }) - } + }) }) kit.For(strings.Split(kit.Env(PATH), _path_sep()), func(p string) { push(p) }) return kit.Join(list, _path_sep()) @@ -35,22 +35,18 @@ func init() { START: {Hand: func(m *ice.Message, arg ...string) { env := []string{PATH, BinPath(""), HOME, kit.Select(kit.Path(""), os.Getenv(HOME))} kit.For(ENV_LIST, func(k string) { kit.If(kit.Env(k) != "", func() { env = append(env, k, kit.Env(k)) }) }) - for _, v := range os.Environ() { + kit.For(os.Environ(), func(v string) { if ls := kit.Split(v, ice.EQ, ice.EQ); kit.IndexOf(env, ls[0]) == -1 && len(ls) > 1 { env = append(env, ls[0], ls[1]) } - } + }) m.Options(CMD_ENV, env, CMD_INPUT, os.Stdin, CMD_OUTPUT, os.Stdout, CMD_ERRPUT, os.Stderr) - if p := kit.Env(CTX_LOG); p != "" { - m.Optionv(CMD_ERRPUT, p) - } + kit.If(kit.Env(CTX_LOG), func(p string) { m.Optionv(CMD_ERRPUT, p) }) m.Cmd(FOREVER, STOP) if bin := kit.Select(os.Args[0], ice.BIN_ICE_BIN, nfs.ExistsFile(m, ice.BIN_ICE_BIN)); len(arg) > 0 && arg[0] == ice.SPACE { - m.Cmdy(FOREVER, bin, ice.SPACE, "dial", ice.DEV, ice.OPS, arg[1:]) + m.Cmdy(FOREVER, bin, ice.SPACE, START, ice.DEV, ice.OPS, arg[1:]) } else { - if len(arg) == 0 || arg[0] != ice.DEV { - arg = append([]string{ice.DEV, ""}, arg...) - } + kit.If(len(arg) == 0 || arg[0] != ice.DEV, func() { arg = append([]string{ice.DEV, ""}, arg...) }) m.Cmdy(FOREVER, bin, ice.SERVE, START, arg) } }}, @@ -64,7 +60,7 @@ func init() { } for { if logs.Println("run %s", kit.Join(arg, ice.SP)); IsSuccess(m.Cmd(SYSTEM, arg)) { - defer logs.Println(ice.EXIT) + logs.Println(ice.EXIT) break } logs.Println() diff --git a/base/cli/mirrors.go b/base/cli/mirrors.go index 392fed3d..5b20cde6 100644 --- a/base/cli/mirrors.go +++ b/base/cli/mirrors.go @@ -30,9 +30,7 @@ func init() { CMD: {Name: "cmd cli osid", Hand: func(m *ice.Message, arg ...string) { osid := kit.Select(mdb.Conf(m, RUNTIME, kit.Keys(HOST, OSID)), m.Option(OSID)) mdb.ZoneSelectCB(m, m.Option(CLI), func(value ice.Map) { - if osid != "" && strings.Contains(osid, kit.Format(value[OSID])) { - m.Cmdy(kit.Split(kit.Format(value[CMD]))) - } + kit.If(strings.Contains(osid, kit.Format(value[OSID])), func() { m.Cmdy(kit.Split(kit.Format(value[CMD]))) }) }) }}, ALPINE: {Name: "alpine cli cmd", Hand: func(m *ice.Message, arg ...string) { IsAlpine(m, arg...) }}, @@ -44,16 +42,13 @@ var _release = "" func release(m *ice.Message) string { osid := runtime.GOOS - if osid != "linux" { + if osid != LINUX { return osid } m.Option(nfs.CAT_CONTENT, _release) _release = m.Cmdx(nfs.CAT, "/etc/os-release", kit.Dict(ice.MSG_USERROLE, aaa.ROOT), func(text string, _ int) string { if ls := kit.Split(text, ice.EQ); len(ls) > 1 { - switch ls[0] { - case "ID", "ID_LIKE": - osid = strings.TrimSpace(ls[1] + ice.SP + osid) - } + kit.Switch(ls[0], []string{"ID", "ID_LIKE"}, func() { osid = strings.TrimSpace(ls[1] + ice.SP + osid) }) } return text }) @@ -64,15 +59,19 @@ func insert(m *ice.Message, sys, cmd string, arg ...string) bool { return false } if len(arg) > 0 { - m.Go(func() { - m.Sleep300ms().Cmd(mdb.INSERT, kit.Keys(CLI, MIRRORS), "", mdb.ZONE, arg[0], OSID, sys, CMD, cmd+ice.SP+kit.Select(arg[0], arg, 1)) - }) + m.GoSleep("300ms", mdb.INSERT, kit.Keys(CLI, MIRRORS), "", mdb.ZONE, arg[0], OSID, sys, CMD, cmd+ice.SP+kit.Select(arg[0], arg, 1)) } return true } -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 IsUbuntu(m *ice.Message, arg ...string) bool { return insert(m, UBUNTU, "apt get -y", 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, "system yum install -y", arg...) +} +func IsUbuntu(m *ice.Message, arg ...string) bool { + return insert(m, UBUNTU, "system apt get -y", arg...) +} func IsSystem(m *ice.Message, arg ...string) bool { return IsAlpine(m, arg...) || IsCentos(m, arg...) || IsUbuntu(m, arg...) } diff --git a/base/cli/qrcode.go b/base/cli/qrcode.go index 7a205a9d..6da87017 100644 --- a/base/cli/qrcode.go +++ b/base/cli/qrcode.go @@ -2,70 +2,19 @@ package cli import ( "encoding/base64" - "fmt" - "image/color" - "math/rand" - "strconv" - "strings" - "shylinux.com/x/go-qrcode" ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/mdb" - "shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/tcp" + "shylinux.com/x/icebergs/misc/qrcode" kit "shylinux.com/x/toolkits" ) -var _color_map = map[string]color.Color{ - BLACK: color.RGBA{0, 0, 0, DARK}, - RED: color.RGBA{DARK, 0, 0, DARK}, - GREEN: color.RGBA{0, DARK, 0, DARK}, - YELLOW: color.RGBA{DARK, DARK, 0, DARK}, - BLUE: color.RGBA{0, 0, DARK, DARK}, - PURPLE: color.RGBA{DARK, 0, DARK, DARK}, - CYAN: color.RGBA{0, DARK, DARK, DARK}, - WHITE: color.RGBA{DARK, DARK, DARK, DARK}, -} - -func _parse_color(str string) color.Color { - if str == RANDOM { - list := kit.SortedKey(_color_map) - str = list[rand.Intn(len(list))] - } - if strings.HasPrefix(str, "#") { - if len(str) == 7 { - str += "ff" - } - if u, e := strconv.ParseUint(str[1:], 16, 64); e == nil { - return color.RGBA{ - uint8((u & 0xFF000000) >> 24), - uint8((u & 0x00FF0000) >> 16), - uint8((u & 0x0000FF00) >> 8), - uint8((u & 0x000000FF) >> 0), - } - } - } - return _color_map[str] -} -func _parse_cli_color(str string) string { - res := 0 - r, g, b, _ := _parse_color(str).RGBA() - if r > LIGHT { - res += 1 - } - if g > LIGHT { - res += 2 - } - if b > LIGHT { - res += 4 - } - return kit.Format(res) -} func _qrcode_cli(m *ice.Message, text string) { - qr, _ := qrcode.New(text, qrcode.Medium) - fg := _parse_cli_color(m.Option(FG)) - bg := _parse_cli_color(m.Option(BG)) - data := qr.Bitmap() + sc := qrcode.New(text) + fg := ParseCliColor(m.Option(FG)) + bg := ParseCliColor(m.Option(BG)) + data := sc.Bitmap() for i, row := range data { if n := len(data); i < 3 || i >= n-3 { continue @@ -81,35 +30,17 @@ func _qrcode_cli(m *ice.Message, text string) { m.Echo(text).Echo(ice.NL) } func _qrcode_web(m *ice.Message, text string) string { - qr, _ := qrcode.New(text, qrcode.Medium) - qr.ForegroundColor = _parse_color(m.Option(FG)) - qr.BackgroundColor = _parse_color(m.Option(BG)) - if data, err := qr.PNG(kit.Int(m.Option(SIZE))); m.Assert(err) { + sc := qrcode.New(text) + sc.ForegroundColor = ParseColor(m.Option(FG)) + sc.BackgroundColor = ParseColor(m.Option(BG)) + if data, err := sc.PNG(kit.Int(m.Option(SIZE))); m.Assert(err) { m.Echo(``, base64.StdEncoding.EncodeToString(data), text) } return text } const ( - BG = "bg" - FG = "fg" - DARK = 255 - LIGHT = 127 - SIZE = "size" -) -const ( - COLOR = "color" - BLACK = "black" - WHITE = "white" - BLUE = "blue" - RED = "red" - GRAY = "gray" - CYAN = "cyan" - GREEN = "green" - PURPLE = "purple" - YELLOW = "yellow" - RANDOM = "random" - GLASS = "#0000" + SIZE = "size" ) const QRCODE = "qrcode" @@ -124,7 +55,7 @@ func init() { mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { switch arg[0] { case FG, BG: - m.Push(arg[0], BLACK, WHITE, BLUE, RED, CYAN, GREEN, PURPLE, YELLOW) + m.Push(arg[0], BLACK, WHITE) } }}, }, Hand: func(m *ice.Message, arg ...string) { @@ -140,23 +71,3 @@ func init() { }}, }) } - -func Color(m *ice.Message, c string, str ice.Any) string { - wrap, color := `%v`, c - if m.IsCliUA() { - wrap, color = "\033[3%sm%v\033[0m", _parse_cli_color(c) - } - return fmt.Sprintf(wrap, color, 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 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) -} diff --git a/base/cli/runtime.go b/base/cli/runtime.go index 9b7307bc..c6cecc4b 100644 --- a/base/cli/runtime.go +++ b/base/cli/runtime.go @@ -17,10 +17,7 @@ import ( func _runtime_init(m *ice.Message) { count := kit.Int(m.Conf(RUNTIME, kit.Keys(BOOT, mdb.COUNT))) - kit.For(kit.UnMarshal(kit.Format(ice.Info.Make)), func(key string, value ice.Any) { - m.Conf(RUNTIME, kit.Keys(MAKE, strings.ToLower(key)), value) - }) - aaa.UserRoot(ice.Pulse, "", ice.Info.Make.Username, aaa.TECH, ice.DEV) + kit.For(kit.UnMarshal(kit.Format(ice.Info.Make)), func(k string, v ice.Any) { m.Conf(RUNTIME, kit.Keys(MAKE, strings.ToLower(k)), v) }) m.Conf(RUNTIME, kit.Keys(HOST, GOARCH), runtime.GOARCH) m.Conf(RUNTIME, kit.Keys(HOST, GOOS), runtime.GOOS) m.Conf(RUNTIME, kit.Keys(HOST, OSID), release(m)) @@ -28,22 +25,16 @@ func _runtime_init(m *ice.Message) { m.Conf(RUNTIME, kit.Keys(HOST, PWD), kit.Path("")) m.Conf(RUNTIME, kit.Keys(HOST, HOME), kit.HomePath("")) m.Conf(RUNTIME, kit.Keys(HOST, MAXPROCS), runtime.GOMAXPROCS(0)) - for _, k := range ENV_LIST { - switch m.Conf(RUNTIME, kit.Keys(CONF, k), kit.Env(k)); k { - case CTX_PID: - ice.Info.PidPath = kit.Env(k) - } - } + kit.For(ENV_LIST, func(k string) { + m.Conf(RUNTIME, kit.Keys(CONF, k), kit.Env(k)) + kit.If(k == CTX_PID, func() { ice.Info.PidPath = kit.Env(k) }) + }) m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME), kit.Env("HOSTNAME")) if name, e := os.Hostname(); e == nil && name != "" { m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME), name) } m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME), path.Base(kit.Path(""))) - m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME), kit.Select(kit.UserName(), kit.Env(CTX_USER))) - ice.Info.Hostname = m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME)) - ice.Info.Pathname = m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME)) - ice.Info.Username = m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME)) - aaa.UserRoot(ice.Pulse, "", ice.Info.Username, aaa.ROOT, ice.OPS) + m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME), kit.UserName()) msg := m.Cmd(nfs.DIR, _system_find(m, os.Args[0]), "time,path,size,hash") m.Conf(RUNTIME, kit.Keys(BOOT, ice.BIN), msg.Append(nfs.PATH)) m.Conf(RUNTIME, kit.Keys(BOOT, nfs.SIZE), msg.Append(nfs.SIZE)) @@ -52,6 +43,11 @@ func _runtime_init(m *ice.Message) { m.Conf(RUNTIME, kit.Keys(BOOT, mdb.COUNT), count+1) m.Conf(RUNTIME, mdb.META, "") m.Conf(RUNTIME, mdb.HASH, "") + ice.Info.Hostname = m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME)) + ice.Info.Pathname = m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME)) + ice.Info.Username = m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME)) + aaa.UserRoot(ice.Pulse, "", ice.Info.Username, aaa.ROOT, ice.OPS) + aaa.UserRoot(ice.Pulse, "", ice.Info.Make.Username, aaa.TECH, ice.DEV) } func _runtime_hostinfo(m *ice.Message) { m.Push("nCPU", strings.Count(m.Cmdx(nfs.CAT, "/proc/cpuinfo"), "processor")) @@ -94,8 +90,8 @@ const ( ) const ( PATH = "PATH" - USER = "USER" HOME = "HOME" + USER = "USER" TERM = "TERM" SHELL = "SHELL" ) @@ -104,21 +100,16 @@ const ( CTX_COM = "ctx_com" CTX_DEV = "ctx_dev" CTX_OPS = "ctx_ops" - CTX_POD = "ctx_pod" CTX_ARG = "ctx_arg" - CTX_ENV = "ctx_env" CTX_PID = "ctx_pid" CTX_LOG = "ctx_log" + CTX_POD = "ctx_pod" + CTX_ENV = "ctx_env" - CTX_USER = "ctx_user" - CTX_SHARE = "ctx_share" - CTX_RIVER = "ctx_river" CTX_DAEMON = "ctx_daemon" - - MAKE_DOMAIN = "make.domain" ) -var ENV_LIST = []string{TERM, SHELL, CTX_SHY, CTX_COM, CTX_DEV, CTX_OPS, CTX_ARG, CTX_PID, CTX_USER, CTX_SHARE, CTX_RIVER, CTX_DAEMON} +var ENV_LIST = []string{TERM, SHELL, CTX_SHY, CTX_COM, CTX_DEV, CTX_OPS, CTX_ARG, CTX_PID, CTX_DAEMON} const ( HOSTNAME = "hostname" @@ -127,11 +118,11 @@ const ( ) const ( IFCONFIG = "ifconfig" + DISKINFO = "diskinfo" HOSTINFO = "hostinfo" USERINFO = "userinfo" PROCINFO = "procinfo" PROCKILL = "prockill" - DISKINFO = "diskinfo" BOOTINFO = "bootinfo" MAXPROCS = "maxprocs" ) @@ -139,16 +130,17 @@ const RUNTIME = "runtime" func init() { Index.MergeCommands(ice.Commands{ - RUNTIME: {Name: "runtime info=bootinfo,ifconfig,hostname,hostinfo,userinfo,procinfo,diskinfo,api,cli,cmd,env,path,chain auto", Help: "运行环境", Actions: ice.MergeActions(ice.Actions{ + RUNTIME: {Name: "runtime info=bootinfo,ifconfig,diskinfo,hostinfo,userinfo,procinfo,bootinfo,api,cli,cmd,env,path,chain auto", Help: "运行环境", Actions: ice.MergeActions(ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { _runtime_init(m) }}, IFCONFIG: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy("tcp.host") }}, + DISKINFO: {Hand: func(m *ice.Message, arg ...string) { _runtime_diskinfo(m) }}, + HOSTINFO: {Hand: func(m *ice.Message, arg ...string) { _runtime_hostinfo(m) }}, HOSTNAME: {Hand: func(m *ice.Message, arg ...string) { if len(arg) > 0 { - ice.Info.Hostname = mdb.Conf(m, RUNTIME, kit.Keys(BOOT, HOSTNAME), mdb.Conf(m, RUNTIME, kit.Keys(NODE, mdb.NAME), arg[0])) + ice.Info.Hostname = mdb.Conf(m, RUNTIME, kit.Keys(NODE, mdb.NAME), mdb.Conf(m, RUNTIME, kit.Keys(BOOT, HOSTNAME), arg[0])) } m.Echo(ice.Info.Hostname) }}, - HOSTINFO: {Hand: func(m *ice.Message, arg ...string) { _runtime_hostinfo(m) }}, USERINFO: {Hand: func(m *ice.Message, arg ...string) { m.Split(m.Cmdx(SYSTEM, "who"), "user term time") }}, PROCINFO: {Hand: func(m *ice.Message, arg ...string) { msg := m.Cmd("", HOSTINFO) @@ -160,14 +152,6 @@ func init() { kit.If(len(arg) > 0, func() { runtime.GOMAXPROCS(kit.Int(mdb.Conf(m, RUNTIME, kit.Keys(HOST, MAXPROCS), arg[0]))) }) m.Echo("%d", runtime.GOMAXPROCS(0)) }}, - DISKINFO: {Hand: func(m *ice.Message, arg ...string) { _runtime_diskinfo(m) }}, - MAKE_DOMAIN: {Hand: func(m *ice.Message, arg ...string) { - if os.Getenv(CTX_DEV) == "" || os.Getenv(CTX_POD) == "" { - m.Echo(mdb.Conf(m, RUNTIME, MAKE_DOMAIN)) - } else { - m.Echo(kit.MergePOD(os.Getenv(CTX_DEV), os.Getenv(CTX_POD))) - } - }}, API: {Hand: func(m *ice.Message, arg ...string) { kit.For(ice.Info.Route, func(k, v string) { m.Push(nfs.PATH, k).Push(nfs.FILE, v) }) m.StatusTimeCount().Sort(nfs.PATH) diff --git a/base/cli/system.go b/base/cli/system.go index 0b204071..a18c09b8 100644 --- a/base/cli/system.go +++ b/base/cli/system.go @@ -18,7 +18,7 @@ import ( ) func _path_split(ps string) []string { - ps = strings.ReplaceAll(ps, "\\", ice.PS) + ps = kit.ReplaceAll(ps, "\\", ice.PS) return kit.Split(ps, ice.NL+kit.Select(ice.DF, ";", strings.Contains(ps, ";")), ice.NL) } func _system_cmd(m *ice.Message, arg ...string) *exec.Cmd { @@ -69,8 +69,7 @@ func _system_out(m *ice.Message, out string) io.Writer { } else if m.Option(out) == "" { return nil } else if f, p, e := file.CreateFile(m.Option(out)); m.Assert(e) { - m.Logs(nfs.SAVE, out, p) - m.Optionv(out, f) + m.Logs(nfs.SAVE, out, p).Optionv(out, f) return f } return nil @@ -116,14 +115,12 @@ func _system_find(m Message, bin string, dir ...string) string { if strings.HasPrefix(bin, nfs.PWD) { return bin } - if len(dir) == 0 { - dir = append(dir, _path_split(kit.Env(PATH))...) - } + kit.If(len(dir) == 0, func() { dir = append(dir, _path_split(kit.Env(PATH))...) }) for _, p := range dir { if nfs.ExistsFile(m, path.Join(p, bin)) { return kit.Path(p, bin) } - if nfs.ExistsFile(m, path.Join(p, bin)+".exe") { + if IsWindows() && nfs.ExistsFile(m, path.Join(p, bin)+".exe") { return kit.Path(p, bin) + ".exe" } } @@ -145,11 +142,11 @@ const ( CMD_OUT = "cmd_out" MAN = "man" - GREP = "grep" - OPENS = "opens" - REST = "rest" FIND = "find" + GREP = "grep" EXEC = "exec" + REST = "rest" + OPENS = "opens" ) const SYSTEM = "system" @@ -214,11 +211,10 @@ func SystemFind(m Message, bin string, dir ...string) string { if text := kit.ReadFile(ice.ETC_PATH); len(text) > 0 { dir = append(dir, strings.Split(text, ice.NL)...) } - dir = append(dir, _path_split(kit.Env(PATH))...) - return _system_find(m, bin, dir...) + return _system_find(m, bin, append(dir, _path_split(kit.Env(PATH))...)...) } -func IsSuccess(m Message) bool { return m.Append(CODE) == "" || m.Append(CODE) == "0" } func SystemExec(m *ice.Message, arg ...string) string { return strings.TrimSpace(m.Cmdx(SYSTEM, arg)) } func SystemCmds(m *ice.Message, cmds string, args ...ice.Any) string { return strings.TrimRight(m.Cmdx(SYSTEM, "sh", "-c", kit.Format(cmds, args...), ice.Option{CMD_OUTPUT, ""}), ice.NL) } +func IsSuccess(m Message) bool { return m.Append(CODE) == "" || m.Append(CODE) == "0" } diff --git a/base/ctx/ctx.go b/base/ctx/ctx.go index 8bee9bdf..74c8d082 100644 --- a/base/ctx/ctx.go +++ b/base/ctx/ctx.go @@ -6,4 +6,4 @@ const CTX = "ctx" var Index = &ice.Context{Name: CTX, Help: "标准模块"} -func init() { ice.Index.Register(Index, nil, CONTEXT, COMMAND, CONFIG, MESSAGE, OPTION) } +func init() { ice.Index.Register(Index, nil, CONTEXT, COMMAND, CONFIG) } diff --git a/base/ctx/message.go b/base/ctx/message.go deleted file mode 100644 index 92ed2b0c..00000000 --- a/base/ctx/message.go +++ /dev/null @@ -1,34 +0,0 @@ -package ctx - -import ( - "reflect" - "strings" - - ice "shylinux.com/x/icebergs" - "shylinux.com/x/icebergs/base/mdb" - "shylinux.com/x/toolkits/logs" -) - -const OPTION = "option" -const MESSAGE = "message" - -func init() { - Index.MergeCommands(ice.Commands{ - OPTION: {Name: "option", Help: "选项", Hand: func(m *ice.Message, arg ...string) { - if len(arg) > 1 { - if msg, ok := m.Optionv("message").(*ice.Message); ok { - msg.Option(arg[0], arg[1]) - } - } - }}, - MESSAGE: {Name: "message auto", Help: "消息", Hand: func(m *ice.Message, arg ...string) { - t := reflect.TypeOf(m) - for i := 0; i < t.NumMethod(); i++ { - method := t.Method(i) - p := logs.FileLine(method.Func.Interface()) - m.Push(mdb.NAME, method.Name) - m.Push(mdb.TEXT, strings.Split(p, ice.ICEBERGS+ice.PS)[1]) - } - }}, - }) -} diff --git a/base/nfs/pack.go b/base/nfs/pack.go index eca4e2a5..e9089e08 100644 --- a/base/nfs/pack.go +++ b/base/nfs/pack.go @@ -148,19 +148,19 @@ func CloseFile(m Message, p ice.Any) { } } -func CopyFile(m *ice.Message, to io.WriteCloser, from io.ReadCloser, bufs, total int, cb ice.Any) { - size, buf := 0, make([]byte, bufs) +func CopyFile(m *ice.Message, to io.WriteCloser, from io.ReadCloser, cache, total int, cb ice.Any) { + count, buf := 0, make([]byte, cache) for { n, e := from.Read(buf) to.Write(buf[0:n]) - if size += n; size > total { - total = size + if count += n; count > total { + total = count } - switch step := size * 100 / total; cb := cb.(type) { + switch value := count * 100 / total; cb := cb.(type) { case func(int, int, int): - cb(size, total, step) + cb(count, total, value) case func(int, int): - cb(size, total) + cb(count, total) case nil: default: m.ErrorNotImplement(cb) diff --git a/base/tcp/client.go b/base/tcp/client.go index e49b7a30..f087c514 100644 --- a/base/tcp/client.go +++ b/base/tcp/client.go @@ -5,6 +5,7 @@ import ( ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/mdb" + kit "shylinux.com/x/toolkits" ) type Conn struct { @@ -34,9 +35,7 @@ func _client_dial(m *ice.Message, arg ...string) { } switch cb := m.OptionCB("").(type) { case func(net.Conn): - if !m.Warn(e) { - cb(c) - } + kit.If(!m.Warn(e), func() { cb(c) }) default: m.ErrorNotImplement(cb) } diff --git a/base/tcp/host.go b/base/tcp/host.go index 9b6a1165..4494d374 100644 --- a/base/tcp/host.go +++ b/base/tcp/host.go @@ -13,10 +13,7 @@ import ( func _host_list(m *ice.Message, name string) { if ifs, e := net.Interfaces(); m.Assert(e) { for _, v := range ifs { - if name != "" && !strings.Contains(v.Name, name) { - continue - } - if len(v.HardwareAddr.String()) == 0 { + if !strings.Contains(v.Name, name) || len(v.HardwareAddr.String()) == 0 { continue } if ips, e := v.Addrs(); m.Assert(e) { diff --git a/base/web/broad.go b/base/web/broad.go index 5f18fd76..5df58ee5 100644 --- a/base/web/broad.go +++ b/base/web/broad.go @@ -40,7 +40,7 @@ func init() { BROAD: {Name: "broad hash auto", Help: "广播", Actions: ice.MergeActions(ice.Actions{ mdb.SEARCH: {Hand: func(m *ice.Message, arg ...string) { if arg[0] == mdb.FOREACH && arg[1] == "" { - host, domain := m.Cmdv(tcp.HOST, aaa.IP), OptionUserWeb(m).Hostname() + host, domain := m.Cmdv(tcp.HOST, aaa.IP), UserWeb(m).Hostname() m.Cmds("", func(value ice.Maps) { switch kit.If(value[tcp.HOST] == host, func() { value[tcp.HOST] = domain }); value[mdb.TYPE] { case "sshd": @@ -60,7 +60,3 @@ func init() { }, mdb.HashAction(mdb.SHORT, "host,port", mdb.FIELD, "time,hash,type,name,host,port", mdb.ACTION, OPEN), mdb.ClearOnExitHashAction())}, }) } -func Domain(host, port string) string { return kit.Format("http://%s:%s", host, port) } -func Script(m *ice.Message, str string, arg ...ice.Any) string { - return ice.Render(m, ice.RENDER_SCRIPT, kit.Format(str, arg...)) -} diff --git a/base/web/cache.go b/base/web/cache.go index 9d50e7d9..f5f81dfa 100644 --- a/base/web/cache.go +++ b/base/web/cache.go @@ -1,7 +1,6 @@ package web import ( - "fmt" "io" "net/http" "os" @@ -19,11 +18,11 @@ import ( func _cache_name(m *ice.Message, h string) string { return path.Join(ice.VAR_FILE, h[:2], h) } func _cache_mime(m *ice.Message, mime, name string) string { - if mime == "application/octet-stream" { + if mime == ApplicationOctet { if kit.ExtIsImage(name) { - mime = "image/" + kit.Ext(name) + mime = IMAGE + ice.PS + kit.Ext(name) } else if kit.ExtIsVideo(name) { - mime = "video/" + kit.Ext(name) + mime = VIDEO + ice.PS + kit.Ext(name) } } else if mime == "" { return kit.Ext(name) @@ -64,7 +63,7 @@ func _cache_upload(m *ice.Message, r *http.Request) (mime, name, file, size stri defer f.Close() b.Seek(0, os.SEEK_SET) if n, e := io.Copy(f, b); !m.Warn(e, ice.ErrNotValid, UPLOAD) { - m.Logs(nfs.LOAD, nfs.FILE, p, nfs.SIZE, kit.FmtSize(int64(n))) + m.Logs(nfs.SAVE, nfs.FILE, p, nfs.SIZE, kit.FmtSize(int64(n))) return h.Header.Get(ContentType), h.Filename, p, kit.Format(n) } } @@ -72,24 +71,21 @@ func _cache_upload(m *ice.Message, r *http.Request) (mime, name, file, size stri return "", "", "", "0" } func _cache_download(m *ice.Message, r *http.Response, file string, cb ice.Any) string { - if f, p, e := nfs.CreateFile(m, file); m.Assert(e) { - // if f, p, e := miss.CreateFile(file); !m.Warn(e, ice.ErrNotValid, DOWNLOAD) { + if f, p, e := miss.CreateFile(file); !m.Warn(e, ice.ErrNotValid, DOWNLOAD) { defer f.Close() last, base := 0, 10 - nfs.CopyFile(m, f, r.Body, base*ice.MOD_BUFS, kit.Int(kit.Select("100", r.Header.Get(ContentLength))), func(count, total, step int) { - if step/base != last { - m.Logs(nfs.SAVE, nfs.FILE, p, mdb.COUNT, count, mdb.TOTAL, total, mdb.VALUE, step) - switch cb := cb.(type) { - case func(int, int, int): - if cb != nil { - cb(count, total, step) - } - case nil: - default: - m.ErrorNotImplement(cb) - } + nfs.CopyFile(m, f, r.Body, base*ice.MOD_BUFS, kit.Int(kit.Select("100", r.Header.Get(ContentLength))), func(count, total, value int) { + if value/base == last { + return + } + last = value / base + switch m.Logs(nfs.SAVE, nfs.FILE, p, mdb.COUNT, count, mdb.TOTAL, total, mdb.VALUE, value); cb := cb.(type) { + case func(int, int, int): + kit.If(cb != nil, func() { cb(count, total, value) }) + case nil: + default: + m.ErrorNotImplement(cb) } - last = step / base }) return p } @@ -102,13 +98,15 @@ const ( WRITE = "write" UPLOAD = "upload" DOWNLOAD = "download" - DISPLAY = "display" + + IMAGE = "image" + VIDEO = "video" ) const CACHE = "cache" func init() { Index.MergeCommands(ice.Commands{ - CACHE: {Name: "cache hash auto write catch upload", Help: "缓存池", Actions: ice.MergeActions(ice.Actions{ + CACHE: {Name: "cache hash auto write catch upload download", Help: "缓存池", Actions: ice.MergeActions(ice.Actions{ WATCH: {Name: "watch hash* path*", Help: "释放", Hand: func(m *ice.Message, arg ...string) { _cache_watch(m, m.Option(mdb.HASH), m.Option(nfs.PATH)) }}, @@ -124,16 +122,13 @@ func init() { _cache_save(m, mime, name, "", file, size) }}, DOWNLOAD: {Name: "download type name*", Hand: func(m *ice.Message, arg ...string) { - if r, ok := m.Optionv(RESPONSE).(*http.Response); !m.Warn(!ok, ice.ErrNotValid, RESPONSE) { - file, size := _cache_catch(m, _cache_download(m, r, path.Join(ice.VAR_TMP, kit.Hashs(mdb.UNIQ)), m.OptionCB(""))) + if res, ok := m.Optionv(RESPONSE).(*http.Response); !m.Warn(!ok, ice.ErrNotValid, RESPONSE) { + file, size := _cache_catch(m, _cache_download(m, res, path.Join(ice.VAR_TMP, kit.Hashs(mdb.UNIQ)), m.OptionCB(""))) _cache_save(m, m.Option(mdb.TYPE), m.Option(mdb.NAME), "", file, size) } }}, ice.RENDER_DOWNLOAD: {Hand: func(m *ice.Message, arg ...string) { - p := kit.Select(arg[0], arg, 1) - p = kit.Select("", SHARE_LOCAL, !strings.HasPrefix(p, ice.PS) && !strings.HasPrefix(p, HTTP)) + p - args := []string{ice.POD, m.Option(ice.MSG_USERPOD), "filename", kit.Select("", arg[0], len(arg) > 1)} - m.Echo(fmt.Sprintf(`%s`, MergeURL2(m, p, args), path.Base(arg[0]), arg[0])) + m.Echo(_share_link(m, kit.Select(arg[0], arg, 1), ice.POD, m.Option(ice.MSG_USERPOD), "filename", kit.Select("", arg[0], len(arg) > 1))) }}, ice.PS: {Hand: func(m *ice.Message, arg ...string) { mdb.HashSelectDetail(m, arg[0], func(value ice.Map) { @@ -145,13 +140,13 @@ func init() { }) }}, }, mdb.HashAction(mdb.SHORT, mdb.TEXT, mdb.FIELD, "time,hash,size,type,name,text,file", ctx.ACTION, WATCH), ice.RenderAction(ice.RENDER_DOWNLOAD)), Hand: func(m *ice.Message, arg ...string) { - if mdb.HashSelect(m, arg...); len(arg) == 0 || m.R.Method == http.MethodGet { + if mdb.HashSelect(m, arg...); len(arg) == 0 || m.R != nil && m.R.Method == http.MethodGet { return } if m.Append(nfs.FILE) == "" { m.PushScript(mdb.TEXT, m.Append(mdb.TEXT)) } else { - PushDisplay(m, m.Append(mdb.TYPE), m.Append(mdb.NAME), MergeURL2(m, SHARE_CACHE+arg[0])) + PushDisplay(m, m.Append(mdb.TYPE), m.Append(mdb.NAME), MergeURL2(m, P(SHARE, CACHE, arg[0]))) } }}, }) @@ -167,13 +162,35 @@ func init() { m.Assert(len(up) > 1) m.Cmd(CACHE, m.Option(ice.MSG_UPLOAD)).Table(func(value ice.Maps) { m.Options(value) }) if m.Options(mdb.HASH, up[0], mdb.NAME, up[1]); watch { - m.Cmdy(CACHE, WATCH, m.Option(mdb.HASH), path.Join(m.Option(nfs.PATH), m.Option(mdb.NAME))) + m.Cmdy(CACHE, WATCH, m.Option(mdb.HASH), path.Join(m.Option(nfs.PATH), up[1])) } }, action.Hand) } }) ctx.Upload = Upload } +func Upload(m *ice.Message) []string { + 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) != "" { + m.Cmd(SPACE, m.Option(ice.MSG_USERPOD), SPIDE, ice.DEV, SPIDE_CACHE, http.MethodGet, tcp.PublishLocalhost(m, MergeURL2(m, PP(SHARE, CACHE, m.Append(mdb.HASH))))) + } + return kit.Simple(m.Optionv(ice.MSG_UPLOAD)) + } else { + return up + } +} +func Download(m *ice.Message, link string, cb func(count, total, value int)) *ice.Message { + return m.Cmdy(Prefix(SPIDE), ice.DEV, SPIDE_CACHE, http.MethodGet, link, cb) +} +func PushDisplay(m *ice.Message, mime, name, link string) { + if strings.HasPrefix(mime, IMAGE+ice.PS) || kit.ExtIsImage(name) { + m.PushImages(nfs.FILE, link) + } else if strings.HasPrefix(mime, VIDEO+ice.PS) || kit.ExtIsImage(name) { + m.PushVideos(nfs.FILE, link) + } else { + m.PushDownload(nfs.FILE, name, link) + } +} func RenderCache(m *ice.Message, h string) { if msg := m.Cmd(CACHE, h); msg.Append(nfs.FILE) == "" { m.RenderResult(msg.Append(mdb.TEXT)) @@ -181,25 +198,3 @@ func RenderCache(m *ice.Message, h string) { m.RenderDownload(msg.Append(mdb.FILE), msg.Append(mdb.TYPE), msg.Append(mdb.NAME)) } } -func Upload(m *ice.Message) []string { - 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) != "" { - m.Cmd(SPACE, m.Option(ice.MSG_USERPOD), SPIDE, ice.DEV, SPIDE_CACHE, http.MethodGet, tcp.PublishLocalhost(m, MergeURL2(m, path.Join(SHARE_CACHE, m.Append(mdb.HASH))))) - } - return kit.Simple(m.Optionv(ice.MSG_UPLOAD)) - } else { - return up - } -} -func Download(m *ice.Message, link string, cb func(count, total, value int)) *ice.Message { - return m.Cmdy("web.spide", ice.DEV, SPIDE_CACHE, http.MethodGet, link, cb) -} -func PushDisplay(m *ice.Message, mime, name, link string) { - if strings.HasPrefix(mime, "image/") || kit.ExtIsImage(name) { - m.PushImages(nfs.FILE, link) - } else if strings.HasPrefix(mime, "video/") || kit.ExtIsImage(name) { - m.PushVideos(nfs.FILE, link) - } else { - m.PushDownload(nfs.FILE, name, link) - } -} diff --git a/base/web/dream.go b/base/web/dream.go index 775039fc..6c94caf9 100644 --- a/base/web/dream.go +++ b/base/web/dream.go @@ -39,7 +39,7 @@ func _dream_show(m *ice.Message, name string) { return } kit.If(!strings.Contains(name, "-") || !strings.HasPrefix(name, "20"), func() { name = m.Time("20060102-") + name }) - defer m.ProcessOpen(MergePods(m, m.Option(mdb.NAME, name))) + defer m.ProcessOpen(m.MergePod(m.Option(mdb.NAME, name))) p := path.Join(ice.USR_LOCAL_WORK, name) if pid := m.Cmdx(nfs.CAT, path.Join(p, ice.Info.PidPath), kit.Dict(ice.MSG_USERROLE, aaa.TECH)); pid != "" && nfs.ExistsFile(m, "/proc/"+pid) { m.Info("already exists %v", pid) @@ -93,7 +93,7 @@ func init() { DREAM: {Name: "dream name path auto create", Help: "梦想家", Actions: ice.MergeActions(ice.Actions{ mdb.SEARCH: {Hand: func(m *ice.Message, arg ...string) { if arg[0] == mdb.FOREACH && arg[1] == "" { - m.Cmds("", func(value ice.Maps) { m.PushSearch(mdb.TEXT, MergePods(m, value[mdb.NAME]), value) }) + m.Cmds("", func(value ice.Maps) { m.PushSearch(mdb.TEXT, m.MergePod(value[mdb.NAME]), value) }) } }}, mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { @@ -136,7 +136,7 @@ func init() { DREAM_TABLES: {Hand: func(m *ice.Message, arg ...string) { kit.Switch(m.Option(mdb.TYPE), []string{SERVER, WORKER}, func() { m.PushButton(OPEN) }) }}, - OPEN: {Hand: func(m *ice.Message, arg ...string) { ctx.ProcessOpen(m, MergePods(m, m.Option(mdb.NAME), arg)) }}, + OPEN: {Hand: func(m *ice.Message, arg ...string) { ctx.ProcessOpen(m, m.MergePod(m.Option(mdb.NAME), arg)) }}, }, ctx.CmdAction(), DreamAction()), Hand: func(m *ice.Message, arg ...string) { if len(arg) == 0 { _dream_list(m) diff --git a/base/web/option.go b/base/web/option.go index ec86d4be..6aaee2cd 100644 --- a/base/web/option.go +++ b/base/web/option.go @@ -2,7 +2,6 @@ package web import ( "net/url" - "path" "strings" "time" @@ -10,48 +9,77 @@ import ( "shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/ctx" - "shylinux.com/x/icebergs/base/gdb" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/tcp" kit "shylinux.com/x/toolkits" "shylinux.com/x/toolkits/file" ) +type Message interface { + Option(key string, arg ...ice.Any) string + PrefixKey(...string) string +} + +func UserWeb(m Message) *url.URL { return kit.ParseURL(m.Option(ice.MSG_USERWEB)) } +func UserHost(m *ice.Message) string { + if u := UserWeb(m); strings.Contains(u.Host, tcp.LOCALHOST) { + return m.Option(ice.MSG_USERHOST, tcp.PublishLocalhost(m, u.Scheme+"://"+u.Host)) + } else { + return m.Option(ice.MSG_USERHOST, u.Scheme+"://"+u.Host) + } +} +func AgentIs(m Message, arg ...string) bool { + for _, k := range arg { + if strings.HasPrefix(strings.ToLower(m.Option(ice.MSG_USERUA)), k) { + return true + } + } + return false +} +func MergeURL2(m Message, url string, arg ...ice.Any) string { + if m.Option(ice.MSG_USERWEB) == "" { + return kit.MergeURL2(Domain(ice.Pulse.Cmdv(tcp.HOST, aaa.IP), ice.Pulse.Cmdv(SERVE, tcp.PORT)), url, arg...) + } + return kit.MergeURL2(m.Option(ice.MSG_USERWEB), url, arg...) +} +func MergeLink(m Message, url string, arg ...ice.Any) string { + return kit.MergeURL(strings.Split(MergeURL2(m, url), ice.QS)[0], arg...) +} +func ProcessPodCmd(m *ice.Message, pod, cmd string, arg ...ice.Any) { + m.ProcessOpen(m.MergePodCmd(pod, cmd, arg...)) +} +func ProcessIframe(m *ice.Message, name, link string, arg ...string) { + ctx.ProcessField(m, CHAT_IFRAME, func() []string { + return []string{m.Cmdx(CHAT_IFRAME, mdb.CREATE, mdb.TYPE, LINK, mdb.NAME, name, LINK, link)} + }, arg...) +} +func PushPodCmd(m *ice.Message, cmd string, arg ...string) { + kit.If(m.Length() > 0 && len(m.Appendv(ice.POD)) == 0, func() { m.Table(func(value ice.Maps) { m.Push(ice.POD, m.Option(ice.MSG_USERPOD)) }) }) + m.Cmds(SPACE, func(value ice.Maps) { + kit.Switch(value[mdb.TYPE], []string{SERVER, WORKER}, func() { + m.Cmd(SPACE, value[mdb.NAME], kit.Select(m.PrefixKey(), cmd), arg).Table(func(index int, val ice.Maps, head []string) { + val[ice.POD] = kit.Keys(value[mdb.NAME], val[ice.POD]) + m.Push("", val, head) + }) + }) + }) +} func PushNotice(m *ice.Message, arg ...ice.Any) { if m.Option(ice.MSG_DAEMON) == "" { return - } - if m.Option(ice.MSG_USERPOD) == "" { - msg := m.Spawn() - msg.Optionv(ice.MSG_OPTS, msg.Optionv(ice.MSG_OPTION, []string{})) - msg.Cmd(SPACE, m.Option(ice.MSG_DAEMON), arg) + } else if m.Option(ice.MSG_USERPOD) == "" { + m.Cmd(SPACE, m.Option(ice.MSG_DAEMON), arg, ice.Maps{ice.MSG_OPTION: "", ice.MSG_OPTS: ""}) } else { - m.Cmd(Prefix(SPIDE), ice.OPS, MergeURL2(m, SHARE_TOAST+m.Option(ice.MSG_DAEMON)), ice.ARG, kit.Format(arg)) + m.Cmd(Prefix(SPIDE), ice.OPS, MergeURL2(m, P(SHARE, TOAST, m.Option(ice.MSG_DAEMON))), ice.ARG, kit.Format(arg)) } } -func PushNoticeGrow(m *ice.Message, arg ...ice.Any) { - PushNotice(m, kit.List("grow", arg)...) -} -func PushNoticeToast(m *ice.Message, arg ...ice.Any) { - PushNotice(m, kit.List("toast", arg)...) -} -func PushNoticeRefresh(m *ice.Message, arg ...ice.Any) { - PushNotice(m, kit.List("refresh")...) +func PushNoticeGrow(m *ice.Message, arg ...ice.Any) { PushNotice(m, kit.List("grow", arg)...) } +func PushNoticeToast(m *ice.Message, arg ...ice.Any) { PushNotice(m, kit.List("toast", arg)...) } +func PushStream(m *ice.Message) *ice.Message { + m.ProcessHold() + return m.Options(cli.CMD_OUTPUT, file.NewWriteCloser(func(buf []byte) { PushNoticeGrow(m, string(buf)) }, func() { PushNoticeToast(m, "done") })) } -func ToastProcess(m *ice.Message, arg ...ice.Any) func() { - if len(arg) == 0 { - arg = kit.List("", "-1") - } - if len(arg) == 1 { - arg = append(arg, "-1") - } - Toast(m, ice.PROCESS, arg...) - return func() { Toast(m, ice.SUCCESS) } -} -func ToastRestart(m *ice.Message, arg ...ice.Any) { Toast(m, gdb.RESTART, arg...) } -func ToastFailure(m *ice.Message, arg ...ice.Any) { Toast(m, ice.FAILURE, arg...) } -func ToastSuccess(m *ice.Message, arg ...ice.Any) { Toast(m, ice.SUCCESS, arg...) } func Toast(m *ice.Message, text string, arg ...ice.Any) { // [title [duration [progress]]] if len(arg) > 1 { switch val := arg[1].(type) { @@ -63,115 +91,20 @@ func Toast(m *ice.Message, text string, arg ...ice.Any) { // [title [duration [p } PushNoticeToast(m, text, arg) } -func Toast3s(m *ice.Message, text string, arg ...ice.Any) *ice.Message { - Toast(m, text, kit.List(kit.Select("", arg, 0), kit.Select("3s", arg, 1))...) - return m -} -func Toast30s(m *ice.Message, text string, arg ...ice.Any) { - Toast(m, text, kit.List(kit.Select("", arg, 0), kit.Select("30s", arg, 1))...) +func ToastFailure(m *ice.Message, arg ...ice.Any) { Toast(m, ice.FAILURE, arg...) } +func ToastSuccess(m *ice.Message, arg ...ice.Any) { Toast(m, ice.SUCCESS, arg...) } +func ToastProcess(m *ice.Message, arg ...ice.Any) func() { + kit.If(len(arg) == 0, func() { arg = kit.List("", "-1") }) + kit.If(len(arg) == 1, func() { arg = append(arg, "-1") }) + Toast(m, ice.PROCESS, arg...) + return func() { Toast(m, ice.SUCCESS) } } func GoToast(m *ice.Message, title string, cb func(toast func(string, int, int))) { cb(func(name string, count, total int) { - if total == 0 { - total = 1 - } + kit.If(total == 0, func() { total = 1 }) Toast(m, kit.Format("%s %s/%s", name, strings.TrimSuffix(kit.FmtSize(int64(count)), "B"), strings.TrimSuffix(kit.FmtSize(int64(total)), "B")), - kit.Format("%s %d%%", title, count*100/total), - kit.Select("3000", "30000", count < total), - count*100/total, + kit.Format("%s %d%%", title, count*100/total), kit.Select("3000", "30000", count < total), count*100/total, ) }) } -func PushStream(m *ice.Message, cmds ...ice.Any) *ice.Message { - m.Option(cli.CMD_OUTPUT, file.NewWriteCloser(func(buf []byte) (int, error) { - PushNoticeGrow(m, string(buf)) - return len(buf), nil - }, func() error { PushNoticeToast(m, "done"); return nil })) - m.ProcessHold() - return m.Cmd(cmds...) -} -func PushPodCmd(m *ice.Message, cmd string, arg ...string) { - if m.Length() > 0 && len(m.Appendv(ice.POD)) == 0 { - m.Table(func(value ice.Maps) { m.Push(ice.POD, m.Option(ice.MSG_USERPOD)) }) - } - - m.Cmd(SPACE, ice.OptionFields(mdb.TYPE, mdb.NAME), func(value ice.Maps) { - switch value[mdb.TYPE] { - case SERVER, WORKER: - if value[mdb.NAME] == ice.Info.Hostname { - break - } - m.Cmd(SPACE, value[mdb.NAME], kit.Select(m.PrefixKey(), cmd), arg).Table(func(index int, val ice.Maps, head []string) { - val[ice.POD] = kit.Keys(value[mdb.NAME], val[ice.POD]) - m.Push("", val, head) - }) - } - }) -} - -type Message interface { - Option(key string, arg ...ice.Any) string - PrefixKey(...string) string -} - -func OptionAgentIs(m Message, arg ...string) bool { - for _, k := range arg { - if strings.HasPrefix(strings.ToLower(m.Option(ice.MSG_USERUA)), k) { - return true - } - } - return false -} -func OptionUserWeb(m Message) *url.URL { - return kit.ParseURL(m.Option(ice.MSG_USERWEB)) -} -func MergeURL2(m Message, url string, arg ...ice.Any) string { - if m.Option(ice.MSG_USERWEB) == "" { - return kit.MergeURL2(HTTP+"://"+ice.Pulse.Cmd(tcp.HOST).Append(aaa.IP)+":"+ice.Pulse.Cmd(SERVE).Append(tcp.PORT), url, arg...) - } - return kit.MergeURL2(m.Option(ice.MSG_USERWEB), url, arg...) -} -func MergeLink(m Message, url string, arg ...ice.Any) string { - return strings.Split(MergeURL2(m, url, arg...), ice.QS)[0] -} -func MergePod(m Message, pod string, arg ...ice.Any) string { - return kit.MergePOD(kit.Select(ice.Info.Domain, m.Option(ice.MSG_USERWEB)), pod, arg...) -} -func MergePods(m Message, pod string, arg ...ice.Any) string { - return kit.MergeURL(strings.Split(MergePod(m, pod), ice.QS)[0], arg...) -} -func MergePodCmds(m Message, pod, cmd string, arg ...ice.Any) string { - return kit.MergeURL(strings.Split(MergePodCmd(m, pod, cmd), ice.QS)[0], arg...) -} -func MergePodCmd(m Message, pod, cmd string, arg ...ice.Any) string { - p := "/chat" - p += path.Join("/pod/", kit.Keys(m.Option(ice.MSG_USERPOD), pod)) - p = kit.Select(p, "/chat", p == "/chat/pod") - p += path.Join("/cmd/", kit.Select(m.PrefixKey(), cmd)) - return kit.MergeURL2(kit.Select(ice.Info.Domain, m.Option(ice.MSG_USERWEB)), p, arg...) -} -func MergePodWebSite(m Message, pod, web string, arg ...ice.Any) string { - p := "/chat" - p += "/pod/" + kit.Keys(m.Option(ice.MSG_USERPOD), pod) - p = kit.Select(p, "/chat/", p == "/chat/pod/") - p += "/website/" + kit.Select("index.iml", web) - return kit.MergeURL2(kit.Select(ice.Info.Domain, m.Option(ice.MSG_USERWEB)), p, arg...) -} -func ProcessWebsite(m *ice.Message, pod, cmd string, arg ...ice.Any) { - m.ProcessOpen(MergePodCmd(m, pod, cmd, arg...)) -} -func ProcessIframe(m *ice.Message, name, link string, arg ...string) { - if len(arg) == 0 || arg[0] != ice.RUN { - arg = []string{m.Cmdx("web.chat.iframe", mdb.CREATE, mdb.TYPE, LINK, mdb.NAME, name, LINK, link)} - } - ctx.ProcessField(m, "web.chat.iframe", arg, arg...) -} - -func UserHost(m *ice.Message) string { - if u := OptionUserWeb(m); strings.Contains(u.Host, tcp.LOCALHOST) { - return m.Option(ice.MSG_USERHOST, tcp.PublishLocalhost(m, u.Scheme+"://"+u.Host)) - } else { - return m.Option(ice.MSG_USERHOST, u.Scheme+"://"+u.Host) - } -} diff --git a/base/web/render.go b/base/web/render.go index ba77ae9a..3d15aafe 100644 --- a/base/web/render.go +++ b/base/web/render.go @@ -141,7 +141,8 @@ func renderVersion(m *ice.Message) string { } const ( - WEBSITE = "website" + BLACK = "black" + DISPLAY = "display" RESIZE = "resize" LAYOUT = "layout" OUTPUT = "output" @@ -149,9 +150,10 @@ const ( VIEW = "view" CHAT = "chat" - CODE_VIMER = "web.code.vimer" - CODE_INNER = "web.code.inner" - CODE_XTERM = "web.code.xterm" - CHAT_FAVOR = "web.chat.favor" - WIKI_WORD = "web.wiki.word" + CODE_VIMER = "web.code.vimer" + CODE_INNER = "web.code.inner" + CODE_XTERM = "web.code.xterm" + CHAT_FAVOR = "web.chat.favor" + CHAT_IFRAME = "web.chat.iframe" + WIKI_WORD = "web.wiki.word" ) diff --git a/base/web/serve.go b/base/web/serve.go index 1fb82372..9db42bc1 100644 --- a/base/web/serve.go +++ b/base/web/serve.go @@ -143,10 +143,12 @@ const ( HTTP = "http" HTTPS = "https" DOMAIN = "domain" + ORIGIN = "origin" FORM = "form" BODY = "body" - ApplicationJSON = "Application/json" + ApplicationJSON = "Application/json" + ApplicationOctet = "application/octet-stream" ) const SERVE = "serve" @@ -182,3 +184,9 @@ func init() { } }) } +func Domain(host, port string) string { + return kit.Format("%s://%s:%s", HTTP, host, port) +} +func Script(m *ice.Message, str string, arg ...ice.Any) string { + return ice.Render(m, ice.RENDER_SCRIPT, kit.Format(str, arg...)) +} diff --git a/base/web/share.go b/base/web/share.go index 113dc9e7..260ba6bb 100644 --- a/base/web/share.go +++ b/base/web/share.go @@ -18,16 +18,15 @@ import ( "shylinux.com/x/toolkits/logs" ) -func _share_link(m *ice.Message, p string) string { - return tcp.PublishLocalhost(m, MergeLink(m, kit.Select("", SHARE_LOCAL, !strings.HasPrefix(p, ice.PS) && !strings.HasPrefix(p, HTTP))+p)) +func _share_link(m *ice.Message, p string, arg ...ice.Any) string { + return tcp.PublishLocalhost(m, MergeLink(m, kit.Select("", PP(SHARE, LOCAL), !strings.HasPrefix(p, ice.PS) && !strings.HasPrefix(p, HTTP))+p, arg...)) } func _share_cache(m *ice.Message, arg ...string) { if pod := m.Option(ice.POD); ctx.PodCmd(m, CACHE, arg[0]) { if m.Append(nfs.FILE) == "" { m.RenderResult(m.Append(mdb.TEXT)) } else { - m.Option(ice.POD, pod) - ShareLocalFile(m, m.Append(nfs.FILE)) + ShareLocalFile(m.Options(ice.POD, pod), m.Append(nfs.FILE)) } } else { if m.Cmdy(CACHE, arg[0]); m.Append(nfs.FILE) == "" { @@ -50,19 +49,16 @@ func _share_proxy(m *ice.Message) { } const ( - THEME = "theme" LOGIN = "login" RIVER = "river" STORM = "storm" FIELD = "field" - SHARE_CACHE = "/share/cache/" - SHARE_LOCAL = "/share/local/" - SHARE_PROXY = "/share/proxy/" - SHARE_TOAST = "/share/toast/" + LOCAL = "local" + PROXY = "proxy" + TOAST = "toast" - SHARE_LOCAL_AVATAR = "/share/local/avatar/" - SHARE_LOCAL_BACKGROUND = "/share/local/background/" + SHARE_LOCAL = "/share/local/" ) const SHARE = "share" @@ -82,8 +78,7 @@ func init() { } msg := m.Cmd(SHARE, m.Option(SHARE, arg[0])) if IsNotValidShare(m, msg.Append(mdb.TIME)) { - m.RenderResult(kit.Format("共享超时, 请联系 %s(%s), 重新分享 %s %s", - msg.Append(aaa.USERNICK), msg.Append(aaa.USERNAME), msg.Append(mdb.TYPE), msg.Append(mdb.NAME))) + m.RenderResult(kit.Format("共享超时, 请联系 %s(%s), 重新分享 %s %s", msg.Append(aaa.USERNICK), msg.Append(aaa.USERNAME), msg.Append(mdb.TYPE), msg.Append(mdb.NAME))) return } switch msg.Append(mdb.TYPE) { @@ -104,16 +99,16 @@ func init() { m.PushAnchor(link) } }}, - SHARE_CACHE: {Hand: func(m *ice.Message, arg ...string) { _share_cache(m, arg...) }}, - SHARE_LOCAL: {Hand: func(m *ice.Message, arg ...string) { ShareLocalFile(m, arg...) }}, - SHARE_LOCAL_AVATAR: {Hand: func(m *ice.Message, arg ...string) { - m.RenderDownload(strings.TrimPrefix(m.Cmdv(aaa.USER, m.Option(ice.MSG_USERNAME), aaa.AVATAR), SHARE_LOCAL)) + PP(SHARE, CACHE): {Hand: func(m *ice.Message, arg ...string) { _share_cache(m, arg...) }}, + PP(SHARE, LOCAL): {Hand: func(m *ice.Message, arg ...string) { ShareLocalFile(m, arg...) }}, + PP(SHARE, LOCAL, aaa.AVATAR): {Hand: func(m *ice.Message, arg ...string) { + m.RenderDownload(strings.TrimPrefix(m.Cmdv(aaa.USER, m.Option(ice.MSG_USERNAME), aaa.AVATAR), PP(SHARE, LOCAL))) }}, - SHARE_LOCAL_BACKGROUND: {Hand: func(m *ice.Message, arg ...string) { - m.RenderDownload(strings.TrimPrefix(m.Cmdv(aaa.USER, m.Option(ice.MSG_USERNAME), aaa.BACKGROUND), SHARE_LOCAL)) + PP(SHARE, LOCAL, aaa.BACKGROUND): {Hand: func(m *ice.Message, arg ...string) { + m.RenderDownload(strings.TrimPrefix(m.Cmdv(aaa.USER, m.Option(ice.MSG_USERNAME), aaa.BACKGROUND), PP(SHARE, LOCAL))) }}, - SHARE_PROXY: {Hand: func(m *ice.Message, arg ...string) { _share_proxy(m) }}, - SHARE_TOAST: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(SPACE, arg[0], kit.UnMarshal(m.Option(ice.ARG))) }}, + PP(SHARE, PROXY): {Hand: func(m *ice.Message, arg ...string) { _share_proxy(m) }}, + PP(SHARE, TOAST): {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(SPACE, arg[0], kit.UnMarshal(m.Option(ice.ARG))) }}, }) } func IsNotValidShare(m *ice.Message, time string) bool { @@ -141,7 +136,6 @@ func ShareLocalFile(m *ice.Message, arg ...string) { cache, size = s.ModTime(), s.Size() } kit.If(p == ice.BIN_ICE_BIN, func() { m.Option(ice.MSG_USERROLE, aaa.TECH) }) - m.Cmd(SPACE, m.Option(ice.POD), SPIDE, ice.DEV, SPIDE_RAW, MergeLink(m, SHARE_PROXY), - SPIDE_PART, m.OptionSimple(ice.POD), nfs.PATH, p, nfs.SIZE, size, CACHE, cache.Format(ice.MOD_TIME), UPLOAD, ice.AT+p) + m.Cmd(SPACE, m.Option(ice.POD), SPIDE, ice.DEV, SPIDE_RAW, MergeLink(m, PP(SHARE, PROXY)), SPIDE_PART, m.OptionSimple(ice.POD), nfs.PATH, p, nfs.SIZE, size, CACHE, cache.Format(ice.MOD_TIME), UPLOAD, ice.AT+p) m.RenderDownload(kit.Select(p, pp, file.ExistsFile(pp))) } diff --git a/base/web/space.go b/base/web/space.go index 58ba5dd3..0713bb46 100644 --- a/base/web/space.go +++ b/base/web/space.go @@ -16,16 +16,16 @@ import ( "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/ssh" "shylinux.com/x/icebergs/base/tcp" + "shylinux.com/x/icebergs/misc/websocket" kit "shylinux.com/x/toolkits" - "shylinux.com/x/websocket" ) func _space_qrcode(m *ice.Message, dev string) { ssh.PrintQRCode(m, m.Cmdv(SPACE, dev, cli.PWD, mdb.LINK)) } func _space_dial(m *ice.Message, dev, name string, arg ...string) { - uri := kit.ParseURL(kit.MergeURL2(strings.Replace(m.Cmdv(SPIDE, dev, CLIENT_ORIGIN), HTTP, "ws", 1), PP(SPACE), mdb.TYPE, ice.Info.NodeType, mdb.NAME, name, arg)) - args := kit.SimpleKV("type,name,host,port", uri.Scheme, dev, uri.Hostname(), uri.Port()) + u := kit.ParseURL(kit.MergeURL2(strings.Replace(m.Cmdv(SPIDE, dev, CLIENT_ORIGIN), HTTP, "ws", 1), PP(SPACE), mdb.TYPE, ice.Info.NodeType, mdb.NAME, name, arg)) + args := kit.SimpleKV("type,name,host,port", u.Scheme, dev, u.Hostname(), u.Port()) m.Go(func() { once := sync.Once{} redial := kit.Dict(mdb.Configv(m, REDIAL)) @@ -33,13 +33,13 @@ func _space_dial(m *ice.Message, dev, name string, arg ...string) { for i := 1; i < c; i++ { next := time.Duration(rand.Intn(a*(i+1))+b*i) * time.Millisecond m.Cmd(tcp.CLIENT, tcp.DIAL, args, func(c net.Conn) { - if c, _, e := websocket.NewClient(c, uri, nil, ice.MOD_BUFS, ice.MOD_BUFS); !m.Warn(e, tcp.DIAL, dev, SPACE, uri.String()) { - defer mdb.HashCreateDeferRemove(m, kit.SimpleKV("", MASTER, dev, uri.Hostname()), kit.Dict(mdb.TARGET, c))() + if c, e := websocket.NewClient(c, u); !m.Warn(e, tcp.DIAL, dev, SPACE, u.String()) { + defer mdb.HashCreateDeferRemove(m, kit.SimpleKV("", MASTER, dev, u.Hostname()), kit.Dict(mdb.TARGET, c))() kit.If(ice.Info.Colors, func() { once.Do(func() { m.Go(func() { _space_qrcode(m, dev) }) }) }) _space_handle(m.Spawn(), true, dev, c) i = 0 } - }).Cost(mdb.COUNT, i, mdb.NEXT, next, tcp.DIAL, dev, LINK, uri.String()).Sleep(next) + }).Cost(mdb.COUNT, i, mdb.NEXT, next, tcp.DIAL, dev, LINK, u.String()).Sleep(next) } }, kit.Join(kit.Simple(SPACE, name), ice.SP)) } @@ -47,7 +47,7 @@ func _space_fork(m *ice.Message) { addr := kit.Select(m.R.RemoteAddr, m.R.Header.Get(ice.MSG_USERADDR)) name := kit.ReplaceAll(kit.Select(addr, m.Option(mdb.NAME)), "[", "_", "]", "_", ice.DF, "_", ice.PT, "_") args := kit.Simple(mdb.TYPE, kit.Select(WORKER, m.Option(mdb.TYPE)), mdb.NAME, name, mdb.TEXT, kit.Select(addr, m.Option(mdb.TEXT)), m.OptionSimple(cli.DAEMON, ice.MSG_USERUA)) - if c, e := websocket.Upgrade(m.W, m.R, nil, ice.MOD_BUFS, ice.MOD_BUFS); !m.Warn(e) { + if c, e := websocket.Upgrade(m.W, m.R); !m.Warn(e) { m.Go(func() { defer mdb.HashCreateDeferRemove(m, args, kit.Dict(mdb.TARGET, c))() switch m.Option(mdb.TYPE) { @@ -164,6 +164,7 @@ func init() { } _space_dial(m, m.Option(ice.DEV), kit.Select(ice.Info.NodeName, m.Option(mdb.NAME)), arg...) }}, + cli.START: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy("", tcp.DIAL, arg) }}, mdb.REMOVE: {Hand: func(m *ice.Message, arg ...string) { defer mdb.HashModifyDeferRemove(m, m.OptionSimple(mdb.NAME), mdb.STATUS, cli.STOP)() m.Cmd("", m.Option(mdb.NAME), ice.EXIT) @@ -175,7 +176,7 @@ func init() { case MASTER: m.PushSearch(mdb.TEXT, m.Cmdv(SPIDE, value[mdb.NAME], CLIENT_ORIGIN), value) case SERVER: - m.PushSearch(mdb.TEXT, MergePods(m, value[mdb.NAME]), value) + m.PushSearch(mdb.TEXT, m.MergePod(value[mdb.NAME]), value) } }) } else if arg[0] == mdb.FOREACH && arg[1] == ssh.SHELL { @@ -192,13 +193,11 @@ func init() { case MASTER: ctx.ProcessOpen(m, m.Cmdv(SPIDE, m.Option(mdb.NAME), CLIENT_ORIGIN)) default: - ctx.ProcessOpen(m, MergePods(m, m.Option(mdb.NAME), arg)) + ctx.ProcessOpen(m, m.MergePod(m.Option(mdb.NAME), arg)) } }}, ice.PS: {Hand: func(m *ice.Message, arg ...string) { _space_fork(m) }}, - }, mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,type,name,text", ctx.ACTION, OPEN, - REDIAL, kit.Dict("a", 3000, "b", 1000, "c", 1000), - ), mdb.ClearOnExitHashAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,type,name,text", ctx.ACTION, OPEN, REDIAL, kit.Dict("a", 3000, "b", 1000, "c", 1000)), mdb.ClearOnExitHashAction()), Hand: func(m *ice.Message, arg ...string) { if len(arg) < 2 { mdb.HashSelect(m, arg...).Sort("").Table(func(value ice.Maps) { m.PushButton(kit.Select(OPEN, LOGIN, value[mdb.TYPE] == LOGIN), mdb.REMOVE) }) } else { diff --git a/base/web/spide.go b/base/web/spide.go index 2db7e397..b5407dd9 100644 --- a/base/web/spide.go +++ b/base/web/spide.go @@ -20,37 +20,24 @@ import ( kit "shylinux.com/x/toolkits" ) -func _spide_create(m *ice.Message, name, address string) { - if uri, e := url.Parse(address); !m.Warn(e != nil || address == "", ice.ErrNotValid, address) { - m.Logs(mdb.INSERT, SPIDE, name, ADDRESS, address) +func _spide_create(m *ice.Message, name, link string) { + if u, e := url.Parse(link); !m.Warn(e != nil || link == "", ice.ErrNotValid, link) { + dir, file := path.Split(u.EscapedPath()) + m.Logs(mdb.INSERT, SPIDE, name, LINK, link) mdb.HashSelectUpdate(m, mdb.HashCreate(m, CLIENT_NAME, name), func(value ice.Map) { - dir, file := path.Split(uri.EscapedPath()) - value[SPIDE_CLIENT] = kit.Dict(mdb.NAME, name, SPIDE_METHOD, http.MethodPost, "url", address, "origin", uri.Scheme+"://"+uri.Host, - tcp.PROTOCOL, uri.Scheme, tcp.HOSTNAME, uri.Hostname(), tcp.HOST, uri.Host, nfs.PATH, dir, nfs.FILE, file, "query", uri.RawQuery, - cli.TIMEOUT, "300ms", LOGHEADERS, ice.FALSE, + value[SPIDE_CLIENT] = kit.Dict(mdb.NAME, name, SPIDE_METHOD, http.MethodPost, "url", link, ORIGIN, u.Scheme+"://"+u.Host, + tcp.PROTOCOL, u.Scheme, tcp.HOSTNAME, u.Hostname(), tcp.HOST, u.Host, nfs.PATH, dir, nfs.FILE, file, cli.TIMEOUT, "3s", ) }) } } -func _spide_args(m *ice.Message, arg []string, val ...string) (string, []string) { - if kit.IndexOf(val, arg[0]) > -1 { - return arg[0], arg[1:] - } - return "", arg -} func _spide_show(m *ice.Message, name string, arg ...string) { - msg := mdb.HashSelects(m.Spawn(), name) - if len(arg) == 1 && msg.Append(arg[0]) != "" { - m.Echo(msg.Append(arg[0])) - return - } - format, arg := _spide_args(m, arg, SPIDE_RAW, SPIDE_MSG, SPIDE_CACHE, SPIDE_SAVE) file := "" - if format == SPIDE_SAVE { - file, arg = arg[0], arg[1:] - } + action, arg := _spide_args(m, arg, SPIDE_RAW, SPIDE_MSG, SPIDE_CACHE, SPIDE_SAVE) + kit.If(action == SPIDE_SAVE, func() { file, arg = arg[0], arg[1:] }) + msg := mdb.HashSelects(m.Spawn(), name) method, arg := _spide_args(m, arg, http.MethodGet, http.MethodPut, http.MethodPost, http.MethodDelete) - method = kit.Select(http.MethodPost, kit.Select(msg.Append(CLIENT_METHOD), method)) + method = kit.Select(http.MethodPost, msg.Append(CLIENT_METHOD), method) uri, arg := arg[0], arg[1:] body, head, arg := _spide_body(m, method, arg...) if c, ok := body.(io.Closer); ok { @@ -66,17 +53,13 @@ func _spide_show(m *ice.Message, name string, arg ...string) { return } defer res.Body.Close() - if mdb.Config(m, LOGHEADERS) == ice.TRUE { - for k, v := range res.Header { - m.Logs(mdb.IMPORT, k, v) - } - } m.Cost(cli.STATUS, res.Status, nfs.SIZE, res.Header.Get(ContentLength), mdb.TYPE, res.Header.Get(ContentType)) + kit.For(res.Header, func(k string, v []string) { m.Logs(mdb.IMPORT, k, v) }) mdb.HashSelectUpdate(m, name, func(value ice.Map) { - for _, v := range res.Cookies() { + kit.For(res.Cookies(), func(v *http.Cookie) { kit.Value(value, kit.Keys(SPIDE_COOKIE, v.Name), v.Value) m.Logs(mdb.IMPORT, v.Name, v.Value) - } + }) }) if m.Warn(res.StatusCode != http.StatusOK, ice.ErrNotValid, uri, cli.STATUS, res.Status) { switch res.StatusCode { @@ -84,41 +67,42 @@ func _spide_show(m *ice.Message, name string, arg ...string) { return } } - _spide_save(m, format, file, uri, res) + _spide_save(m, action, file, uri, res) +} +func _spide_args(m *ice.Message, arg []string, val ...string) (string, []string) { + if kit.IndexOf(val, arg[0]) > -1 { + return arg[0], arg[1:] + } + return "", arg } func _spide_body(m *ice.Message, method string, arg ...string) (io.Reader, ice.Maps, []string) { - head := ice.Maps{} body, ok := m.Optionv(SPIDE_BODY).(io.Reader) - if !ok && len(arg) > 0 && method != http.MethodGet { - if len(arg) == 1 { - arg = []string{SPIDE_DATA, arg[0]} - } - switch arg[0] { - case SPIDE_FORM: - arg = kit.Simple(arg, func(v string) string { return url.QueryEscape(v) }) - head[ContentType], body = ContentFORM, bytes.NewBufferString(kit.JoinKV("=", "&", arg[1:]...)) - case SPIDE_PART: - head[ContentType], body = _spide_part(m, arg...) - case SPIDE_DATA: - head[ContentType], body = ContentJSON, bytes.NewBufferString(kit.Select("{}", arg, 1)) - case SPIDE_FILE: - if f, e := nfs.OpenFile(m, arg[1]); m.Assert(e) { - m.Logs(mdb.IMPORT, nfs.FILE, arg[1]) - body = f - } - case SPIDE_JSON: - arg = arg[1:] - fallthrough - default: - data := ice.Map{} - kit.For(arg, func(k, v string) { kit.Value(data, k, v) }) - head[ContentType], body = ContentJSON, bytes.NewBufferString(kit.Format(data)) - } - arg = arg[:0] - } else { - body = bytes.NewBuffer([]byte{}) + if ok || method == http.MethodGet || len(arg) == 0 { + return body, nil, arg } - return body, head, arg + head := ice.Maps{} + switch kit.If(len(arg) == 1, func() { arg = []string{SPIDE_DATA, arg[0]} }); arg[0] { + case SPIDE_FORM: + arg = kit.Simple(arg, func(v string) string { return url.QueryEscape(v) }) + head[ContentType], body = ContentFORM, bytes.NewBufferString(kit.JoinKV("=", "&", arg[1:]...)) + case SPIDE_PART: + head[ContentType], body = _spide_part(m, arg...) + case SPIDE_FILE: + if f, e := nfs.OpenFile(m, arg[1]); m.Assert(e) { + m.Logs(nfs.LOAD, nfs.FILE, arg[1]) + body = f + } + case SPIDE_DATA: + head[ContentType], body = ApplicationJSON, bytes.NewBufferString(kit.Select("{}", arg, 1)) + case SPIDE_JSON: + arg = arg[1:] + fallthrough + default: + data := ice.Map{} + kit.For(arg, func(k, v string) { kit.Value(data, k, v) }) + head[ContentType], body = ApplicationJSON, bytes.NewBufferString(kit.Format(data)) + } + return body, head, arg[:0] } func _spide_part(m *ice.Message, arg ...string) (string, io.Reader) { buf := &bytes.Buffer{} @@ -137,13 +121,13 @@ func _spide_part(m *ice.Message, arg ...string) (string, io.Reader) { if s.Size() == size && s.ModTime().Before(cache) { continue } - m.Logs(mdb.IMPORT, "local", s.ModTime(), nfs.SIZE, s.Size(), CACHE, cache, nfs.SIZE, size) + m.Logs(nfs.FIND, LOCAL, s.ModTime(), nfs.SIZE, s.Size(), CACHE, cache, nfs.SIZE, size) } if f, e := nfs.OpenFile(m, arg[i+1][1:]); !m.Warn(e, ice.ErrNotValid, arg[i+1]) { defer f.Close() if p, e := mp.CreateFormFile(arg[i], path.Base(arg[i+1][1:])); !m.Warn(e, ice.ErrNotValid, arg[i+1]) { if n, e := io.Copy(p, f); !m.Warn(e, ice.ErrNotValid, arg[i+1]) { - m.Logs(mdb.EXPORT, nfs.FILE, arg[i+1], nfs.SIZE, n) + m.Logs(nfs.LOAD, nfs.FILE, arg[i+1], nfs.SIZE, n) } } } @@ -155,10 +139,6 @@ func _spide_part(m *ice.Message, arg ...string) (string, io.Reader) { } func _spide_head(m *ice.Message, req *http.Request, head ice.Maps, value ice.Map) { m.Logs(req.Method, req.URL.String()) - kit.For(value[SPIDE_HEADER], func(k string, v string) { - req.Header.Set(k, v) - m.Logs("Header", k, v) - }) kit.For(value[SPIDE_COOKIE], func(k string, v string) { req.AddCookie(&http.Cookie{Name: k, Value: v}) m.Logs("Cookie", k, v) @@ -167,6 +147,10 @@ func _spide_head(m *ice.Message, req *http.Request, head ice.Maps, value ice.Map req.AddCookie(&http.Cookie{Name: k, Value: v}) m.Logs("Cookie", k, v) }) + kit.For(value[SPIDE_HEADER], func(k string, v string) { + req.Header.Set(k, v) + m.Logs("Header", k, v) + }) kit.For(kit.Simple(m.Optionv(SPIDE_HEADER)), func(k, v string) { req.Header.Set(k, v) m.Logs("Header", k, v) @@ -175,18 +159,16 @@ func _spide_head(m *ice.Message, req *http.Request, head ice.Maps, value ice.Map req.Header.Set(k, v) m.Logs("Header", k, v) }) - if req.Method == http.MethodPost { - m.Logs(kit.Select(ice.AUTO, req.Header.Get(ContentLength)), req.Header.Get(ContentType)) - } + kit.If(req.Method == http.MethodPost, func() { m.Logs(kit.Select(ice.AUTO, req.Header.Get(ContentLength)), req.Header.Get(ContentType)) }) } func _spide_send(m *ice.Message, name string, req *http.Request, timeout string) (*http.Response, error) { client := mdb.HashSelectTarget(m, name, func() ice.Any { return &http.Client{Timeout: kit.Duration(timeout)} }).(*http.Client) return client.Do(req) } -func _spide_save(m *ice.Message, format, file, uri string, res *http.Response) { - switch format { +func _spide_save(m *ice.Message, action, file, uri string, res *http.Response) { + switch action { case SPIDE_RAW: - if b, _ := ioutil.ReadAll(res.Body); strings.HasPrefix(res.Header.Get(ContentType), ContentJSON) { + if b, _ := ioutil.ReadAll(res.Body); strings.HasPrefix(res.Header.Get(ContentType), ApplicationJSON) { m.Echo(kit.Formats(kit.UnMarshal(string(b)))) } else { m.Echo(string(b)) @@ -222,9 +204,9 @@ const ( SPIDE_BODY = "body" SPIDE_FORM = "form" SPIDE_PART = "part" - SPIDE_JSON = "json" - SPIDE_DATA = "data" SPIDE_FILE = "file" + SPIDE_DATA = "data" + SPIDE_JSON = "json" SPIDE_RES = "content_data" Bearer = "Bearer" @@ -236,7 +218,6 @@ const ( Accept = "Accept" ContentFORM = "application/x-www-form-urlencoded" - ContentJSON = "application/json" ContentPNG = "image/png" ContentHTML = "text/html" ContentCSS = "text/css" @@ -244,26 +225,23 @@ const ( const ( SPIDE_CLIENT = "client" SPIDE_METHOD = "method" - SPIDE_HEADER = "header" SPIDE_COOKIE = "cookie" + SPIDE_HEADER = "header" + CLIENT_NAME = "client.name" + CLIENT_METHOD = "client.method" + CLIENT_TIMEOUT = "client.timeout" CLIENT_PROTOCOL = "client.protocol" CLIENT_HOSTNAME = "client.hostname" - CLIENT_TIMEOUT = "client.timeout" + CLIENT_ORIGIN = "client.origin" + CLIENT_URL = "client.url" - CLIENT_NAME = "client.name" - CLIENT_METHOD = "client.method" - CLIENT_ORIGIN = "client.origin" - CLIENT_URL = "client.url" - - OPEN = "open" - FULL = "full" - LINK = "link" - MERGE = "merge" - ADDRESS = "address" - REQUEST = "request" - RESPONSE = "response" - LOGHEADERS = "logheaders" + OPEN = "open" + FULL = "full" + LINK = "link" + MERGE = "merge" + REQUEST = "request" + RESPONSE = "response" ) const SPIDE = "spide" @@ -277,24 +255,17 @@ func init() { m.Cmd("", mdb.CREATE, ice.COM, kit.Select("https://contexts.com.cn", conf[cli.CTX_COM])) m.Cmd("", mdb.CREATE, ice.SHY, kit.Select(kit.Select("https://shylinux.com", ice.Info.Make.Remote), conf[cli.CTX_SHY])) }}, - mdb.CREATE: {Name: "create name address", Hand: func(m *ice.Message, arg ...string) { _spide_create(m, m.Option(mdb.NAME), m.Option(ADDRESS)) }}, mdb.SEARCH: {Hand: func(m *ice.Message, arg ...string) { if arg[0] == mdb.FOREACH && arg[1] == "" { m.PushSearch(mdb.TYPE, LINK, mdb.NAME, ice.DEV, mdb.TEXT, mdb.HashSelectField(m, ice.COM, CLIENT_ORIGIN)) m.PushSearch(mdb.TYPE, LINK, mdb.NAME, ice.SHY, mdb.TEXT, mdb.HashSelectField(m, ice.SHY, CLIENT_ORIGIN)) } }}, - tcp.CLIENT: {Hand: func(m *ice.Message, arg ...string) { - msg := m.Cmd("", kit.Select(ice.DEV, arg, 0)) - ls := kit.Split(msg.Append(kit.Keys(SPIDE_CLIENT, tcp.HOST)), ice.DF) - m.Push(tcp.HOST, ls[0]).Push(tcp.PORT, kit.Select(kit.Select("443", "80", msg.Append(CLIENT_PROTOCOL) == HTTP), ls, 1)) - m.Push(DOMAIN, msg.Append(CLIENT_PROTOCOL)+"://"+msg.Append(CLIENT_HOSTNAME)+kit.Select("", arg, 1)) - m.Push(tcp.PROTOCOL, msg.Append(CLIENT_PROTOCOL)).Push(tcp.HOSTNAME, msg.Append(CLIENT_HOSTNAME)) - }}, + mdb.CREATE: {Name: "create name link", Hand: func(m *ice.Message, arg ...string) { _spide_create(m, m.Option(mdb.NAME), m.Option(LINK)) }}, MERGE: {Hand: func(m *ice.Message, arg ...string) { m.Echo(kit.MergeURL2(m.Cmdv("", arg[0], CLIENT_URL), arg[1], arg[2:])) }}, - }, mdb.HashAction(mdb.SHORT, CLIENT_NAME, mdb.FIELD, "time,client.name,client.url", LOGHEADERS, ice.FALSE), mdb.ClearOnExitHashAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashAction(mdb.SHORT, CLIENT_NAME, mdb.FIELD, "time,client.name,client.url"), mdb.ClearOnExitHashAction()), Hand: func(m *ice.Message, arg ...string) { if len(arg) < 2 || arg[0] == "" || (len(arg) > 3 && arg[3] == "") { mdb.HashSelect(m, kit.Slice(arg, 0, 1)...).Sort(CLIENT_NAME) } else { @@ -329,5 +300,5 @@ func SpideDelete(m *ice.Message, arg ...ice.Any) ice.Any { return kit.UnMarshal(m.Cmdx(http.MethodDelete, arg)) } func SpideSave(m *ice.Message, file, link string, cb func(int, int, int)) *ice.Message { - return m.Cmd("web.spide", ice.DEV, SPIDE_SAVE, file, http.MethodGet, link, cb) + return m.Cmd(Prefix(SPIDE), ice.DEV, SPIDE_SAVE, file, http.MethodGet, link, cb) } diff --git a/base/web/web.go b/base/web/web.go index 5e468102..bd4d9dab 100644 --- a/base/web/web.go +++ b/base/web/web.go @@ -56,25 +56,22 @@ func (f *Frame) Start(m *ice.Message, arg ...string) { default: m.Cmd(tcp.SERVER, tcp.LISTEN, mdb.TYPE, HTTP, m.OptionSimple(mdb.NAME, tcp.HOST, tcp.PORT), func(l net.Listener) { defer mdb.HashCreateDeferRemove(m, m.OptionSimple(mdb.NAME, tcp.PROTO), arg, cli.STATUS, tcp.START)() - gdb.EventDeferEvent(m, SERVE_START, arg) + gdb.Event(m, SERVE_START, arg) m.Warn(f.Server.Serve(l)) }) } } func (f *Frame) Close(m *ice.Message, arg ...string) {} func (f *Frame) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if _serve_main(f.Message, w, r) { - f.ServeMux.ServeHTTP(w, r) - } + kit.If(_serve_main(f.Message, w, r), func() { f.ServeMux.ServeHTTP(w, r) }) } const WEB = "web" var Index = &ice.Context{Name: WEB, Help: "网络模块"} -func init() { - ice.Index.Register(Index, &Frame{}, BROAD, SERVE, SPACE, DREAM, SHARE, CACHE, SPIDE) -} +func init() { ice.Index.Register(Index, &Frame{}, BROAD, SERVE, SPACE, DREAM, CACHE, SPIDE, SHARE) } + 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) } diff --git a/base/yac/matrix.go b/base/yac/matrix.go index 557ba862..c9e329a5 100644 --- a/base/yac/matrix.go +++ b/base/yac/matrix.go @@ -7,7 +7,6 @@ import ( "strings" ice "shylinux.com/x/icebergs" - "shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/lex" "shylinux.com/x/icebergs/base/mdb" kit "shylinux.com/x/toolkits" @@ -292,15 +291,15 @@ func (mat *Matrix) show(m *ice.Message) { } key, value := kit.Format("%v", mat.name(mat.hand, j)), []string{} if node := mat.mat[i][j]; node != nil { - if node.star > 0 { - value = append(value, cli.ColorYellow(m, mat.name(mat.hand, node.star))) - } - if node.next > 0 { - value = append(value, cli.ColorGreen(m, node.next)) - } - if node.hash > 0 { - value = append(value, cli.ColorRed(m, mat.name(mat.hand, node.hash))) - } + // if node.star > 0 { + // value = append(value, cli.ColorYellow(m, mat.name(mat.hand, node.star))) + // } + // if node.next > 0 { + // value = append(value, cli.ColorGreen(m, node.next)) + // } + // if node.hash > 0 { + // value = append(value, cli.ColorRed(m, mat.name(mat.hand, node.hash))) + // } } m.Push(key, strings.Join(value, ",")) } diff --git a/core/chat/cmd.go b/core/chat/cmd.go index 81d8150d..b54bb58e 100644 --- a/core/chat/cmd.go +++ b/core/chat/cmd.go @@ -15,10 +15,6 @@ import ( func _cmd_file(m *ice.Message, arg ...string) bool { switch p := path.Join(arg...); kit.Ext(p) { - case nfs.ZML: - web.RenderCmd(m, CAN_PARSE, m.Cmdx(nfs.CAT, p)) - case nfs.IML: - m.RenderRedirect(web.MergePodWebSite(m, "", strings.TrimPrefix(p, SRC_WEBSITE))) case nfs.SHY: web.RenderCmd(m, "web.wiki.word", p) case nfs.GO: diff --git a/core/chat/grant.go b/core/chat/grant.go index c145992b..1f3fa173 100644 --- a/core/chat/grant.go +++ b/core/chat/grant.go @@ -18,7 +18,7 @@ func init() { GRANT: {Name: "grant space auto", Help: "授权", Actions: ice.MergeActions(ice.Actions{ web.SPACE_LOGIN: {Hand: func(m *ice.Message, arg ...string) { m.Go(func() { - link := tcp.PublishLocalhost(m, web.MergePodCmd(m, "", "", web.SPACE, m.Option(mdb.NAME))) + link := tcp.PublishLocalhost(m, m.MergePodCmd("", "", web.SPACE, m.Option(mdb.NAME))) m.Sleep300ms(web.SPACE, m.Option(mdb.NAME), cli.PWD, m.Option(mdb.NAME), link, m.Cmdx(cli.QRCODE, link)) }) }}, diff --git a/core/chat/iframe.go b/core/chat/iframe.go index 7ab3ec55..15887532 100644 --- a/core/chat/iframe.go +++ b/core/chat/iframe.go @@ -23,7 +23,7 @@ func init() { } switch arg[0] { case mdb.NAME: - m.Push(arg[0], web.OptionUserWeb(m).Host) + m.Push(arg[0], web.UserWeb(m).Host) case mdb.TEXT: m.Push(arg[0], m.Option(ice.MSG_USERWEB)) } diff --git a/core/chat/keyboard.go b/core/chat/keyboard.go index 6c22ba8d..af61ad00 100644 --- a/core/chat/keyboard.go +++ b/core/chat/keyboard.go @@ -29,7 +29,7 @@ func KeyboardAction() ice.Actions { return ice.Actions{ KEYBOARD: {Hand: func(m *ice.Message, arg ...string) { hash := m.Cmdx("web.chat.keyboard", mdb.CREATE, web.SPACE, m.Option(ice.MSG_DAEMON), ctx.INDEX, m.Option(ctx.INDEX), "input", "") - link := tcp.PublishLocalhost(m, web.MergePodCmd(m, "", "web.chat.keyboard", mdb.HASH, hash)) + link := tcp.PublishLocalhost(m, m.MergePodCmd("", "web.chat.keyboard", mdb.HASH, hash)) m.Push(mdb.NAME, link).PushQRCode(mdb.TEXT, link) }}, } diff --git a/core/chat/pod.go b/core/chat/pod.go index 0aeb5315..13631c00 100644 --- a/core/chat/pod.go +++ b/core/chat/pod.go @@ -18,7 +18,7 @@ const POD = "pod" func init() { Index.MergeCommands(ice.Commands{ POD: {Name: "pod", Help: "节点", Actions: ice.MergeActions(ctx.CmdAction(), web.ApiAction(), aaa.WhiteAction()), Hand: func(m *ice.Message, arg ...string) { - if web.OptionAgentIs(m, "curl", "wget") { + if web.AgentIs(m, "curl", "wget") { m.Cmdy(web.SHARE_LOCAL, ice.BIN_ICE_BIN, kit.Dict(ice.POD, kit.Select("", arg, 0), ice.MSG_USERROLE, aaa.TECH)) return } @@ -31,8 +31,6 @@ func init() { web.RenderMain(m) } else if arg[1] == CMD { web.RenderPodCmd(m, arg[0], arg[2], arg[3:]) - } else if arg[1] == WEBSITE { - RenderWebsite(m, arg[0], path.Join(arg[2:]...)) } }}, }) diff --git a/core/chat/theme.go b/core/chat/theme.go index 025968da..e6575eb1 100644 --- a/core/chat/theme.go +++ b/core/chat/theme.go @@ -5,7 +5,6 @@ import ( 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/nfs" "shylinux.com/x/icebergs/base/web" @@ -95,7 +94,7 @@ func init() { m.RenderDownload(p) return } - m.Cmdy("", kit.TrimExt(kit.Select(cli.BLACK, arg, 0), nfs.CSS)).RenderResult().W.Header()[web.ContentType] = kit.Simple(web.ContentCSS) + m.Cmdy("", kit.TrimExt(kit.Select(web.BLACK, arg, 0), nfs.CSS)).RenderResult().W.Header()[web.ContentType] = kit.Simple(web.ContentCSS) }}, }) } diff --git a/core/chat/website.go b/core/chat/website.go index 023e7b31..5c2cd9a8 100644 --- a/core/chat/website.go +++ b/core/chat/website.go @@ -1,251 +1 @@ package chat - -import ( - "net/http" - "path" - "strings" - - ice "shylinux.com/x/icebergs" - "shylinux.com/x/icebergs/base/aaa" - "shylinux.com/x/icebergs/base/ctx" - "shylinux.com/x/icebergs/base/lex" - "shylinux.com/x/icebergs/base/mdb" - "shylinux.com/x/icebergs/base/nfs" - "shylinux.com/x/icebergs/base/web" - kit "shylinux.com/x/toolkits" -) - -func _website_url(m *ice.Message, file string) string { - return strings.Split(web.MergePodWebSite(m, "", file), "?")[0] -} -func _website_parse(m *ice.Message, text string, args ...string) (ice.Map, bool) { - if text == "" { - return nil, false - } - - const ( - HEADER = "Header" - RIVER = "River" - FOOTER = "Footer" - - ORDER = "order" - TITLE = "title" - MENUS = "menus" - ) - - river, storm, last := kit.Dict( - HEADER, kit.Dict(MENUS, kit.List(), ctx.STYLE, kit.Dict(ctx.DISPLAY, "none")), - RIVER, kit.Dict(MENUS, kit.List(), ctx.ACTION, kit.List("")), - FOOTER, kit.Dict(MENUS, kit.List(), ctx.STYLE, kit.Dict(ctx.DISPLAY, "none")), - args, - ), kit.Dict(), kit.Dict() - - nriver, nstorm, prefix := 0, 0, "" - m.Cmd(lex.SPLIT, "", mdb.KEY, mdb.NAME, kit.Dict(nfs.CAT_CONTENT, text), func(deep int, ls []string) { - if deep == 1 { - switch ls[0] { - case HEADER, RIVER, FOOTER: - for i := 1; i < len(ls); i += 2 { - kit.Value(river, kit.Keys(ls[0], ls[i]), ls[i+1]) - } - return - } - } - - data := kit.Dict() - switch kit.Ext(ls[0]) { - case nfs.JS: - ls[0], data[ctx.DISPLAY] = kit.Select(ice.CAN_PLUGIN, ctx.GetFileCmd(ls[0])), ctx.FileURI(ls[0]) - case nfs.GO: - ls[0] = ctx.GetFileCmd(ls[0]) - case nfs.SHY: - ls[0], data[ctx.ARGS] = "web.wiki.word", ls[0] - case nfs.SH: - ls[0], data[ctx.ARGS] = "web.code.sh.sh", ls[0] - case nfs.PY: - ls[0], data[ctx.ARGS] = "web.code.sh.py", ls[0] - case "~": - prefix, ls = ls[1], ls[1:] - fallthrough - case "-": - for _, v := range ls[1:] { - last[mdb.LIST] = append(last[mdb.LIST].([]ice.Any), kit.Dict(mdb.INDEX, kit.Keys(prefix, v))) - } - return - } - - if ls[0] == "" { - return - } else if len(ls) == 1 && deep > 2 { - ls = append(ls, m.Cmd(ctx.COMMAND, ls[0]).Append(mdb.HELP)) - } else if len(ls) == 1 { - ls = append(ls, ls[0]) - } else if ls[1] == "" { - ls[1] = ls[0] - } - - for i := 2; i < len(ls); i += 2 { - switch ls[i] { - case ctx.ARGS: - data[ls[i]] = kit.Split(ls[i+1]) - case ctx.DISPLAY: - // data[ls[i]] = ice.Display(ls[i+1])[ctx.DISPLAY] - case ctx.STYLE, ctx.ACTION, TITLE, MENUS: - data[ls[i]] = kit.UnMarshal(ls[i+1]) - default: - data[ls[i]] = ls[i+1] - } - } - - switch deep { - case 1: - if nriver++; ls[0] == ice.AUTO { - ls[0] = kit.Format(nriver) - } - nstorm, storm = 0, kit.Dict() - river[ls[0]] = kit.Dict(mdb.NAME, ls[1], STORM, storm, data, ORDER, len(river)) - case 2: - if nstorm++; ls[0] == ice.AUTO { - ls[0] = kit.Format(nstorm) - } - last = kit.Dict(mdb.NAME, ls[1], mdb.LIST, kit.List(), data, ORDER, len(storm)) - storm[ls[0]] = last - prefix = "" - default: - last[mdb.LIST] = append(last[mdb.LIST].([]ice.Any), kit.Dict(mdb.NAME, kit.Select(ls[0], data[mdb.NAME]), mdb.HELP, ls[1], mdb.INDEX, ls[0], data)) - } - }) - return river, true -} -func _website_render(m *ice.Message, w http.ResponseWriter, r *http.Request, kind, text, name string) bool { - msg := m.Spawn(w, r) - switch kind { - case nfs.ZML: - web.RenderCmd(msg, CAN_PARSE, text, name) - case nfs.IML: - res, _ := _website_parse(msg, text) - msg.RenderResult(_website_template2, kit.Format(res)) - case nfs.SHY: - if r.Method == http.MethodGet { - web.RenderCmd(msg, msg.Prefix(DIV), text) - } else { - r.URL.Path = "/chat/cmd/web.chat.div" - return false - } - case nfs.JS: - msg.RenderResult(_website_template, text) - case nfs.JSON: - msg.RenderResult(_website_template2, kit.Format(kit.UnMarshal(text))) - case nfs.HTML: - msg.RenderResult(text) - case nfs.SVG: - msg.RenderResult(`%s`, msg.Cmdx(nfs.CAT, text)) - default: - msg.RenderDownload(text) - } - web.Render(msg, msg.Option(ice.MSG_OUTPUT), msg.Optionv(ice.MSG_ARGS).([]ice.Any)...) - return true -} - -const ( - CAN_PARSE = "can.parse" - SRC_WEBSITE = "src/website/" - CHAT_WEBSITE = "/chat/website/" -) -const WEBSITE = "website" - -func init() { - Index.MergeCommands(ice.Commands{ - WEBSITE: {Name: "website path auto create import", Help: "网站", Actions: ice.MergeActions(ice.Actions{ - ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { - m.Cmd(mdb.RENDER, mdb.CREATE, nfs.IML, m.PrefixKey()) - m.Cmd(mdb.ENGINE, mdb.CREATE, nfs.IML, m.PrefixKey()) - }}, - lex.PARSE: {Hand: func(m *ice.Message, arg ...string) { - switch kit.Ext(arg[0]) { - case nfs.ZML: - web.RenderCmd(m, CAN_PARSE, m.Cmdx(nfs.CAT, path.Join(SRC_WEBSITE, arg[0]))) - case nfs.IML: - if res, ok := _website_parse(m, m.Cmdx(nfs.CAT, path.Join(SRC_WEBSITE, arg[0])), arg[1:]...); ok { - m.Echo(_website_template2, kit.Format(res)) - } - default: - if text := m.CmdAppend("", path.Join(ice.PS, arg[0]), mdb.TEXT); text != "" { - if res, ok := _website_parse(m, text, arg[1:]...); ok { - m.Echo(_website_template2, kit.Format(res)) - } - } - } - }}, - mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { - switch m.Option(ctx.ACTION) { - case mdb.CREATE: - mdb.HashInputs(m, arg) - return - } - switch arg[0] { - case nfs.PATH: - m.Cmdy(nfs.DIR, arg[1:]).ProcessAgain() - } - }}, - mdb.CREATE: {Name: "create path type=zml,iml,json,js,html name text"}, - mdb.IMPORT: {Name: "import path=src/website/", Hand: func(m *ice.Message, arg ...string) { - m.Cmd(nfs.DIR, kit.Dict(nfs.DIR_ROOT, m.Option(nfs.PATH)), func(p string) { - switch name := strings.TrimPrefix(p, m.Option(nfs.PATH)); kit.Ext(p) { - case nfs.HTML, nfs.JS, nfs.JSON, nfs.ZML, nfs.IML, nfs.TXT: - m.Cmd("", mdb.CREATE, nfs.PATH, path.Join(ice.PS, name), mdb.TYPE, kit.Ext(p), mdb.NAME, name, mdb.TEXT, m.Cmdx(nfs.CAT, p)) - default: - m.Cmd("", mdb.CREATE, nfs.PATH, path.Join(ice.PS, name), mdb.TYPE, kit.Ext(p), mdb.NAME, name, mdb.TEXT, p) - } - }) - }}, - mdb.RENDER: {Hand: func(m *ice.Message, arg ...string) { - m.EchoIFrame(_website_url(m, strings.TrimPrefix(path.Join(arg[2], arg[1]), SRC_WEBSITE))) - }}, - mdb.ENGINE: {Hand: func(m *ice.Message, arg ...string) { - if res, ok := _website_parse(m, m.Cmdx(nfs.CAT, path.Join(arg[2], arg[1]))); ok { - ctx.DisplayStoryJSON(m.Echo(kit.Formats(res))) - } else { - m.Echo(_website_url(m, strings.TrimPrefix(path.Join(arg[2], arg[1]), SRC_WEBSITE))) - } - }}, - }, mdb.HashAction(mdb.SHORT, nfs.PATH, mdb.FIELD, "time,path,type,name,text"), ctx.CmdAction(), web.ApiAction(), aaa.WhiteAction()), Hand: func(m *ice.Message, arg ...string) { - mdb.HashSelect(m, arg...).Table(func(value ice.Maps) { m.PushAnchor(web.MergePodWebSite(m, "", value[nfs.PATH])) }) - }}, - }) -} - -func RenderWebsite(m *ice.Message, pod string, dir string, arg ...string) *ice.Message { - return m.Echo(m.Cmdx(web.Space(m, pod), "web.chat.website", lex.PARSE, dir, arg)).RenderResult() -} - -var _website_template = ` - - - - volcanos - - - - - - - - - -` -var _website_template2 = ` - - - - volcanos - - - - - - - - - -` diff --git a/core/code/autogen.go b/core/code/autogen.go index 2228454f..c95047eb 100644 --- a/core/code/autogen.go +++ b/core/code/autogen.go @@ -82,7 +82,7 @@ func _autogen_git(m *ice.Message, arg ...string) ice.Map { ) } func _autogen_mod(m *ice.Message, file string) (mod string) { - host := web.OptionUserWeb(m).Hostname() + host := web.UserWeb(m).Hostname() if host == "" { host = path.Base(kit.Path("")) } else { diff --git a/core/code/case.go b/core/code/case.go index a8509494..d6e26687 100644 --- a/core/code/case.go +++ b/core/code/case.go @@ -44,7 +44,7 @@ func init() { m.Echo(ice.OK) }}, ice.RUN: {Hand: func(m *ice.Message, arg ...string) { - m.Option(web.SPIDE_HEADER, web.ContentType, web.ContentJSON, web.UserAgent, "Mozilla/5.0") + m.Option(web.SPIDE_HEADER, web.ContentType, web.ApplicationJSON, web.UserAgent, "Mozilla/5.0") m.Cmdy(web.SPIDE, m.Option(ice.DEV), web.SPIDE_RAW, m.Option(ice.CMD), m.Option(cli.API), web.SPIDE_DATA, m.Option(ice.ARG)).ProcessInner() m.StatusTime(nfs.SCRIPT, `curl "`+kit.MergeURL2(m.Cmd(web.SPIDE, m.Option(ice.DEV)).Append(web.CLIENT_ORIGIN), m.Option(cli.API))+`" -H "Content-Type: application/json"`+` -d '`+m.Option(ice.ARG)+`'`) }}, diff --git a/core/code/install.go b/core/code/install.go index 938d6fa3..cc5d0c32 100644 --- a/core/code/install.go +++ b/core/code/install.go @@ -162,7 +162,6 @@ func init() { web.DOWNLOAD: {Name: "download link* path", Hand: func(m *ice.Message, arg ...string) { _install_download(m) }}, cli.BUILD: {Name: "build link*", Hand: func(m *ice.Message, arg ...string) { web.PushStream(m) - defer m.ProcessHold() if err := _install_build(m, arg...); m.Warn(err != "", err) { web.ToastFailure(m, cli.BUILD, err) } else { diff --git a/core/code/oauth.go b/core/code/oauth.go index 5224ffd6..f329d823 100644 --- a/core/code/oauth.go +++ b/core/code/oauth.go @@ -23,7 +23,7 @@ func init() { API_GITHUB = "https://api.github.com/" ) _oauth_header := func(m *ice.Message, arg ...string) *ice.Message { - m.Option(web.SPIDE_HEADER, web.Accept, web.ContentJSON, web.Authorization, "token "+kit.Select(m.Option(ACCESS_TOKEN), arg, 0)) + m.Option(web.SPIDE_HEADER, web.Accept, web.ApplicationJSON, web.Authorization, "token "+kit.Select(m.Option(ACCESS_TOKEN), arg, 0)) return m } Index.MergeCommands(ice.Commands{ diff --git a/core/code/pprof.go b/core/code/pprof.go index a1d9186c..bc92f497 100644 --- a/core/code/pprof.go +++ b/core/code/pprof.go @@ -49,7 +49,7 @@ func init() { m.Echo(m.Option(mdb.TEXT)).ProcessInner() }}, web.SERVE: {Help: "展示", Hand: func(m *ice.Message, arg ...string) { - u := web.OptionUserWeb(m) + u := web.UserWeb(m) p := u.Hostname() + ice.DF + m.Cmdx(tcp.PORT, aaa.RIGHT) m.Cmd(cli.DAEMON, mdb.Configv(m, PPROF), "-http="+p, m.Option(BINNARY), m.Option(nfs.FILE)) m.Sleep3s().ProcessOpen(kit.Format("http://%s/ui/top", p)) diff --git a/core/code/upgrade.go b/core/code/upgrade.go index d7d3b1af..3ffe6980 100644 --- a/core/code/upgrade.go +++ b/core/code/upgrade.go @@ -48,7 +48,7 @@ func init() { }) if web.ToastSuccess(m); m.Option(ice.EXIT) == ice.TRUE { m.Cmd("", cli.RESTART) - web.ToastRestart(m) + web.Toast(m, cli.RESTART) } }}, }}) diff --git a/core/code/vimer.go b/core/code/vimer.go index 0fcfbcc1..244d0746 100644 --- a/core/code/vimer.go +++ b/core/code/vimer.go @@ -64,7 +64,7 @@ func init() { m.PushSearch(mdb.TYPE, nfs.FILE, mdb.NAME, "main", mdb.TEXT, ice.SRC_MAIN_SH) m.PushSearch(mdb.TYPE, nfs.FILE, mdb.NAME, "main", mdb.TEXT, ice.SRC_MAIN_JS) m.PushSearch(mdb.TYPE, web.LINK, mdb.NAME, "admin", mdb.TEXT, kit.MergeURL(web.UserHost(m)+ice.PS, log.DEBUG, ice.TRUE)) - m.PushSearch(mdb.TYPE, web.LINK, mdb.NAME, m.CommandKey(), mdb.TEXT, web.MergePodCmds(m, "", "", log.DEBUG, ice.TRUE)) + m.PushSearch(mdb.TYPE, web.LINK, mdb.NAME, m.CommandKey(), mdb.TEXT, m.MergePodCmd("", "", log.DEBUG, ice.TRUE)) } }}, mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { diff --git a/core/code/xterm.go b/core/code/xterm.go index 4a27d1f8..9d840a72 100644 --- a/core/code/xterm.go +++ b/core/code/xterm.go @@ -2,12 +2,9 @@ package code import ( "encoding/base64" - "os" - "os/exec" "path" "strings" - pty "shylinux.com/x/creackpty" ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/ctx" @@ -16,51 +13,33 @@ import ( "shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/ssh" "shylinux.com/x/icebergs/base/web" + "shylinux.com/x/icebergs/misc/xterm" kit "shylinux.com/x/toolkits" ) -type _xterm struct { - *exec.Cmd - *os.File -} - -func (s _xterm) Setsize(rows, cols string) error { - return pty.Setsize(s.File, &pty.Winsize{Rows: uint16(kit.Int(rows)), Cols: uint16(kit.Int(cols))}) -} -func (s _xterm) Writeln(data string, arg ...ice.Any) { - s.Write(kit.Format(data, arg...) + ice.NL) -} -func (s _xterm) Write(data string) (int, error) { - return s.File.Write([]byte(data)) -} -func (s _xterm) Close() error { - return s.Cmd.Process.Kill() -} -func _xterm_get(m *ice.Message, h string) _xterm { +func _xterm_get(m *ice.Message, h string) xterm.XTerm { h = kit.Select(m.Option(mdb.HASH), h) m.Assert(h != "") mdb.HashModify(m, mdb.TIME, m.Time(), web.VIEW, m.Option(ice.MSG_DAEMON)) return mdb.HashSelectTarget(m, h, func(value ice.Maps) ice.Any { text := strings.Split(value[mdb.TEXT], ice.NL) ls := kit.Split(strings.Split(kit.Select(nfs.SH, value[mdb.TYPE]), " # ")[0]) - cmd := exec.Command(cli.SystemFind(m, ls[0]), ls[1:]...) - cmd.Dir = nfs.MkdirAll(m, kit.Path(value[nfs.PATH])) - cmd.Env = append(cmd.Env, os.Environ()...) - cmd.Env = append(cmd.Env, "TERM=xterm") - tty, err := pty.Start(cmd) - m.Assert(err) + term, e := xterm.Command(m, value[nfs.PATH], cli.SystemFind(m, ls[0]), ls[1:]...) + if m.Warn(e) { + return + } m.Go(func() { - defer tty.Close() + defer term.Close() defer mdb.HashRemove(m, mdb.HASH, h) - m.Log(cli.START, strings.Join(cmd.Args, ice.SP)) + m.Log("start", strings.Join(term.Args, ice.SP)) buf := make([]byte, ice.MOD_BUFS) for { - if n, e := tty.Read(buf); !m.Warn(e) && e == nil { + if n, e := term.Read(buf); !m.Warn(e) && e == nil { if _xterm_echo(m, h, string(buf[:n])); len(text) > 0 { if cmd := text[0]; text[0] != "" { m.Go(func() { m.Sleep30ms() - tty.Write([]byte(cmd + ice.NL)) + term.Write(cmd + ice.NL) }) } text = text[1:] @@ -71,8 +50,8 @@ func _xterm_get(m *ice.Message, h string) _xterm { } } }) - return _xterm{cmd, tty} - }).(_xterm) + return term + }).(xterm.XTerm) } func _xterm_echo(m *ice.Message, h string, str string) { m.Options(ice.MSG_DAEMON, mdb.HashSelectField(m, h, web.VIEW)) @@ -90,7 +69,7 @@ func init() { XTERM: {Name: "xterm hash auto", Help: "命令行", Actions: ice.MergeActions(ice.Actions{ mdb.SEARCH: {Hand: func(m *ice.Message, arg ...string) { if arg[0] == mdb.FOREACH && arg[1] == "" { - m.PushSearch(mdb.TYPE, web.LINK, mdb.NAME, m.CommandKey(), mdb.TEXT, web.MergePodCmds(m, "", "", log.DEBUG, ice.TRUE)) + m.PushSearch(mdb.TYPE, web.LINK, mdb.NAME, m.CommandKey(), mdb.TEXT, m.MergePodCmd("", "", log.DEBUG, ice.TRUE)) } }}, mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { @@ -126,7 +105,7 @@ func init() { } }}, web.OUTPUT: {Help: "全屏", Hand: func(m *ice.Message, arg ...string) { - web.ProcessWebsite(m, "", "", m.OptionSimple(mdb.HASH), ctx.STYLE, web.OUTPUT) + web.ProcessPodCmd(m, "", "", m.OptionSimple(mdb.HASH), ctx.STYLE, web.OUTPUT) }}, web.DREAM_CREATE: {Hand: func(m *ice.Message, arg ...string) { m.Cmd("", mdb.CREATE, mdb.TYPE, BASH, m.OptionSimple(mdb.NAME), nfs.PATH, path.Join(ice.USR_LOCAL_WORK, m.Option(mdb.NAME))) diff --git a/core/code/zml.go b/core/code/zml.go index 3419a5b6..e85e2534 100644 --- a/core/code/zml.go +++ b/core/code/zml.go @@ -1,110 +1 @@ package code - -import ( - "path" - "strings" - - ice "shylinux.com/x/icebergs" - "shylinux.com/x/icebergs/base/ctx" - "shylinux.com/x/icebergs/base/mdb" - "shylinux.com/x/icebergs/base/nfs" - "shylinux.com/x/icebergs/base/web" - kit "shylinux.com/x/toolkits" -) - -func _website_url(m *ice.Message, file string) string { - return strings.Split(web.MergePodWebSite(m, "", file), "?")[0] -} - -const ZML = nfs.ZML - -func init() { - const ( - SRC_WEBSITE = "src/website/" - ) - Index.MergeCommands(ice.Commands{ - ZML: {Name: "zml", Help: "网页", Actions: ice.MergeActions(ice.Actions{ - mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {}}, - TEMPLATE: {Hand: func(m *ice.Message, arg ...string) { - switch kit.Ext(m.Option(mdb.FILE)) { - case ZML: - m.Echo(` -{ - username - 系统 - 命令 index cli.system - 共享 index cli.qrcode - 代码 - 趋势 index web.code.git.trend args icebergs action auto - 状态 index web.code.git.status args icebergs - 脚本 - 终端 index hi/hi.sh - 文档 index hi/hi.shy - 数据 index hi/hi.py - 后端 index hi/hi.go - 前端 index hi/hi.js -} -`) - case nfs.IML: - m.Echo(` -系统 - 命令 - cli.system - 环境 - cli.runtime -开发 - 模块 - hi/hi.go - 脚本 - hi/hi.sh - hi/hi.shy - hi/hi.py - hi/hi.go - hi/hi.js -`) - } - }}, - COMPLETE: {Hand: func(m *ice.Message, arg ...string) { - if len(arg) > 0 && arg[0] == mdb.FOREACH { - switch m.Option(ctx.ACTION) { - case web.WEBSITE: - m.Cmdy(nfs.DIR, nfs.PWD, kit.Dict(nfs.DIR_ROOT, SRC_WEBSITE), nfs.PATH) - } - return - } - - switch kit.Select("", kit.Slice(kit.Split(m.Option(mdb.TEXT), "\t \n`"), -1), 0) { - case mdb.TYPE: - m.Push(mdb.NAME, "menu") - - case ctx.INDEX: - m.Cmdy(ctx.COMMAND, mdb.SEARCH, ctx.COMMAND, "", "", ice.OptionFields("index,name,text")) - - case ctx.ACTION: - m.Push(mdb.NAME, "auto") - m.Push(mdb.NAME, "push") - m.Push(mdb.NAME, "open") - - default: - if strings.HasSuffix(m.Option(mdb.TEXT), ice.SP) { - m.Push(mdb.NAME, "index") - m.Push(mdb.NAME, "action") - m.Push(mdb.NAME, "args") - m.Push(mdb.NAME, "type") - } else if m.Option(mdb.TEXT) == "" { - m.Push(mdb.NAME, "head") - m.Push(mdb.NAME, "left") - m.Push(mdb.NAME, "main") - m.Push(mdb.NAME, "foot") - } - } - }}, - mdb.RENDER: {Hand: func(m *ice.Message, arg ...string) { - m.EchoIFrame(_website_url(m, strings.TrimPrefix(path.Join(arg[2], arg[1]), SRC_WEBSITE))) - }}, - mdb.ENGINE: {Hand: func(m *ice.Message, arg ...string) { - m.Echo(_website_url(m, strings.TrimPrefix(path.Join(arg[2], arg[1]), SRC_WEBSITE))) - }}, - }, PlugAction())}, - }) -} diff --git a/core/mall/goods.go b/core/mall/goods.go index 1dddd07e..8d610612 100644 --- a/core/mall/goods.go +++ b/core/mall/goods.go @@ -5,7 +5,6 @@ import ( "shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/web" - kit "shylinux.com/x/toolkits" ) const ( @@ -28,10 +27,10 @@ func init() { m.PushAction("copy", mdb.MODIFY, mdb.REMOVE) ctx.DisplayLocal(m, "") } else { - for _, p := range kit.Split(m.Append("image")) { - m.EchoImages(web.MergeURL2(m, web.SHARE_CACHE+p)) - } - m.PushAction("play", "stop", "copy", mdb.MODIFY, mdb.REMOVE) + // for _, p := range kit.Split(m.Append("image")) { + // m.EchoImages(web.MergeURL2(m, web.SHARE_CACHE+p)) + // } + // m.PushAction("play", "stop", "copy", mdb.MODIFY, mdb.REMOVE) } }}, }) diff --git a/misc/git/status.go b/misc/git/status.go index 5529dd38..c8d26565 100644 --- a/misc/git/status.go +++ b/misc/git/status.go @@ -86,13 +86,14 @@ func _status_each(m *ice.Message, title string, cmds ...string) { ReposList(m).Table(func(value ice.Maps) { toast(value[REPOS], count, total) if msg := m.Cmd(cmds, kit.Dict(cli.CMD_DIR, value[nfs.PATH])); !cli.IsSuccess(msg) { - web.Toast3s(m, msg.Append(cli.CMD_ERR)+msg.Append(cli.CMD_OUT), "error: "+value[REPOS]).Sleep3s() + web.Toast(m, msg.Append(cli.CMD_ERR)+msg.Append(cli.CMD_OUT), "error: "+value[REPOS], "", "3s") + m.Sleep3s() list = append(list, value[REPOS]) } count++ }) if len(list) > 0 { - web.Toast30s(m, strings.Join(list, ice.NL), ice.FAILURE) + web.Toast(m, strings.Join(list, ice.NL), ice.FAILURE, "30s") } else { toast(ice.SUCCESS, count, total) } diff --git a/misc/lark/msg.go b/misc/lark/msg.go index 36069bd8..836af8a3 100644 --- a/misc/lark/msg.go +++ b/misc/lark/msg.go @@ -13,12 +13,12 @@ import ( ) func _lark_get(m *ice.Message, appid string, arg ...ice.Any) (*ice.Message, ice.Any) { - m.Option(web.SPIDE_HEADER, "Authorization", "Bearer "+m.Cmdx(APP, TOKEN, appid), web.ContentType, web.ContentJSON) + m.Option(web.SPIDE_HEADER, "Authorization", "Bearer "+m.Cmdx(APP, TOKEN, appid), web.ContentType, web.ApplicationJSON) msg := m.Cmd(web.SPIDE, LARK, http.MethodGet, arg) return msg, msg.Optionv(web.SPIDE_RES) } func _lark_post(m *ice.Message, appid string, arg ...ice.Any) *ice.Message { - m.Option(web.SPIDE_HEADER, "Authorization", "Bearer "+m.Cmdx(APP, TOKEN, appid), web.ContentType, web.ContentJSON) + m.Option(web.SPIDE_HEADER, "Authorization", "Bearer "+m.Cmdx(APP, TOKEN, appid), web.ContentType, web.ApplicationJSON) return m.Cmd(web.SPIDE, LARK, arg) } func _lark_parse(m *ice.Message) { diff --git a/misc/qrcode/qrcode.go b/misc/qrcode/qrcode.go new file mode 100644 index 00000000..0c2e940f --- /dev/null +++ b/misc/qrcode/qrcode.go @@ -0,0 +1,14 @@ +package qrcode + +import ( + "shylinux.com/x/go-qrcode" +) + +type QRCode struct { + *qrcode.QRCode +} + +func New(text string) *QRCode { + qr, _ := qrcode.New(text, qrcode.Medium) + return &QRCode{qr} +} diff --git a/misc/ssh/service.go b/misc/ssh/service.go index 8af57859..335e0797 100644 --- a/misc/ssh/service.go +++ b/misc/ssh/service.go @@ -188,7 +188,7 @@ func init() { } }}, aaa.INVITE: {Help: "邀请", Hand: func(m *ice.Message, arg ...string) { - m.Option(cli.HOSTNAME, tcp.PublishLocalhost(m, web.OptionUserWeb(m).Hostname())) + m.Option(cli.HOSTNAME, tcp.PublishLocalhost(m, web.UserWeb(m).Hostname())) if buf, err := kit.Render(`ssh -p {{.Option "port"}} {{.Option "user.name"}}@{{.Option "hostname"}}`, m); err == nil { m.EchoScript(string(buf)) } diff --git a/misc/tmux/buffer.go b/misc/tmux/buffer.go index d02d63d9..80e3e2c0 100644 --- a/misc/tmux/buffer.go +++ b/misc/tmux/buffer.go @@ -32,7 +32,7 @@ func init() { }}, }, Hand: func(m *ice.Message, arg ...string) { 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] != "" { - cli.PushText(m, _tmux_cmds(m, SHOW_BUFFER, "-b", arg[0])) + PushText(m, _tmux_cmds(m, SHOW_BUFFER, "-b", arg[0])) return } for i, v := range kit.SplitLine(_tmux_cmd(m, LIST_BUFFER).Result()) { @@ -47,7 +47,15 @@ func init() { }}, TEXT: {Name: "text auto text:textarea", Help: "文本", Hand: func(m *ice.Message, arg ...string) { kit.If(len(arg) > 0, func() { _tmux_cmd(m, SET_BUFFER, arg[0]) }) - cli.PushText(m, _tmux_cmds(m, SHOW_BUFFER)) + PushText(m, _tmux_cmds(m, SHOW_BUFFER)) }}, }) } +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(cli.QRCODE, text) + m.PushAnchor(text) + } + m.Echo(text) +} diff --git a/misc/vim/tags.go b/misc/vim/tags.go index 1b2a9ebf..913d983a 100644 --- a/misc/vim/tags.go +++ b/misc/vim/tags.go @@ -65,10 +65,10 @@ func init() { Qrcode(m, args[1]) case wiki.FIELD: m.Option(ice.MSG_USERWEB, m.Cmdx(web.SPACE, web.DOMAIN)) - Qrcode(m, web.MergePodCmd(m, "", kit.Select(args[1], args, 2))) + Qrcode(m, m.MergePodCmd("", kit.Select(args[1], args, 2))) default: m.Option(ice.MSG_USERWEB, m.Cmdx(web.SPACE, web.DOMAIN)) - Qrcode(m, web.MergePodCmd(m, "", args[0])) + Qrcode(m, m.MergePodCmd("", args[0])) } }}, nfs.SOURCE: {Hand: func(m *ice.Message, arg ...string) { diff --git a/misc/websocket/websocket.go b/misc/websocket/websocket.go new file mode 100644 index 00000000..256abb93 --- /dev/null +++ b/misc/websocket/websocket.go @@ -0,0 +1,21 @@ +package websocket + +import ( + "net" + "net/http" + "net/url" + + ice "shylinux.com/x/icebergs" + "shylinux.com/x/websocket" +) + +type Conn struct{ *websocket.Conn } + +func Upgrade(w http.ResponseWriter, r *http.Request) (*Conn, error) { + conn, e := websocket.Upgrade(w, r, nil, ice.MOD_BUFS, ice.MOD_BUFS) + return &Conn{conn}, e +} +func NewClient(c net.Conn, u *url.URL) (*Conn, error) { + conn, _, e := websocket.NewClient(c, u, nil, ice.MOD_BUFS, ice.MOD_BUFS) + return &Conn{conn}, e +} diff --git a/misc/xterm/xterm.go b/misc/xterm/xterm.go new file mode 100644 index 00000000..dbcd82c0 --- /dev/null +++ b/misc/xterm/xterm.go @@ -0,0 +1,37 @@ +package xterm + +import ( + "os" + "os/exec" + + pty "shylinux.com/x/creackpty" + ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/nfs" + kit "shylinux.com/x/toolkits" +) + +type XTerm struct { + *exec.Cmd + *os.File +} + +func (s XTerm) Setsize(rows, cols string) error { + return pty.Setsize(s.File, &pty.Winsize{Rows: uint16(kit.Int(rows)), Cols: uint16(kit.Int(cols))}) +} +func (s XTerm) Writeln(data string, arg ...ice.Any) { + s.Write(kit.Format(data, arg...) + ice.NL) +} +func (s XTerm) Write(data string) (int, error) { + return s.File.Write([]byte(data)) +} +func (s XTerm) Close() error { + return s.Cmd.Process.Kill() +} +func Command(m *ice.Message, dir string, cli string, arg ...string) (XTerm, error) { + cmd := exec.Command(cli, arg...) + cmd.Dir = nfs.MkdirAll(m, kit.Path(dir)) + cmd.Env = append(cmd.Env, os.Environ()...) + cmd.Env = append(cmd.Env, "TERM=xterm") + tty, err := pty.Start(cmd) + return XTerm{cmd, tty}, err +} diff --git a/option.go b/option.go index efdba1a6..c9c4ffb5 100644 --- a/option.go +++ b/option.go @@ -38,6 +38,11 @@ func (m *Message) OptionCB(key string, cb ...Any) Any { return m.Optionv(kit.Keycb(kit.Select(m.CommandKey(), key))) } +func (m *Message) MergePod(pod string, arg ...Any) string { + ls := []string{"chat"} + kit.If(kit.Keys(m.Option(MSG_USERPOD), pod), func(p string) { ls = append(ls, POD, p) }) + return kit.MergeURL2(strings.Split(kit.Select(Info.Domain, m.Option(MSG_USERWEB)), QS)[0], PS+kit.Join(ls, PS), arg...) +} func (m *Message) MergePodCmd(pod, cmd string, arg ...Any) string { ls := []string{"chat"} kit.If(kit.Keys(m.Option(MSG_USERPOD), pod), func(p string) { ls = append(ls, POD, p) })