forked from x/icebergs
add complete
This commit is contained in:
parent
e4d49f4c1f
commit
5630f42efc
@ -6,4 +6,4 @@ const CLI = "cli"
|
|||||||
|
|
||||||
var Index = &ice.Context{Name: CLI, Help: "命令模块"}
|
var Index = &ice.Context{Name: CLI, Help: "命令模块"}
|
||||||
|
|
||||||
func init() { ice.Index.Register(Index, nil, RUNTIME, QRCODE, MIRROR, SYSTEM, DAEMON, FOREVER) }
|
func init() { ice.Index.Register(Index, nil, MIRRORS, RUNTIME, QRCODE, SYSTEM, DAEMON, FOREVER) }
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
func IsAlpine(m *ice.Message, arg ...string) bool {
|
func IsAlpine(m *ice.Message, arg ...string) bool {
|
||||||
if strings.Contains(m.Conf(RUNTIME, "host.OSID"), ALPINE) {
|
if strings.Contains(m.Conf(RUNTIME, "host.OSID"), ALPINE) {
|
||||||
if len(arg) > 0 {
|
if len(arg) > 0 {
|
||||||
m.Cmd(MIRROR, mdb.CREATE, "cli", arg[0], "cmd", arg[1])
|
m.Cmd(MIRRORS, mdb.CREATE, "cli", arg[0], "cmd", arg[1])
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -25,11 +25,11 @@ const (
|
|||||||
UBUNTU = "ubuntu"
|
UBUNTU = "ubuntu"
|
||||||
)
|
)
|
||||||
|
|
||||||
const MIRROR = "mirror"
|
const MIRRORS = "mirrors"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
Index.Merge(&ice.Context{Commands: map[string]*ice.Command{
|
Index.Merge(&ice.Context{Commands: map[string]*ice.Command{
|
||||||
MIRROR: {Name: "mirror cli auto", Help: "软件镜像", Action: ice.MergeAction(map[string]*ice.Action{
|
MIRRORS: {Name: "mirrors cli auto", Help: "软件镜像", Action: ice.MergeAction(map[string]*ice.Action{
|
||||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||||
m.Go(func() {
|
m.Go(func() {
|
||||||
m.Sleep("1s")
|
m.Sleep("1s")
|
||||||
@ -40,16 +40,16 @@ func init() {
|
|||||||
IsAlpine(m, "tmux", "system apk add tmux")
|
IsAlpine(m, "tmux", "system apk add tmux")
|
||||||
|
|
||||||
if IsAlpine(m, "git", "system apk add git"); !IsAlpine(m, "go", "system apk add git go") {
|
if IsAlpine(m, "git", "system apk add git"); !IsAlpine(m, "go", "system apk add git go") {
|
||||||
m.Cmd(MIRROR, mdb.CREATE, kit.SimpleKV("cli,cmd", "go", "install download https://golang.google.cn/dl/go1.15.5.linux-amd64.tar.gz usr/local"))
|
m.Cmd(MIRRORS, mdb.CREATE, kit.SimpleKV("cli,cmd", "go", "install download https://golang.google.cn/dl/go1.15.5.linux-amd64.tar.gz usr/local"))
|
||||||
}
|
}
|
||||||
|
|
||||||
IsAlpine(m, "node", "system apk add nodejs")
|
IsAlpine(m, "node", "system apk add nodejs")
|
||||||
IsAlpine(m, "java", "system apk add openjdk8")
|
|
||||||
IsAlpine(m, "javac", "system apk add openjdk8")
|
|
||||||
IsAlpine(m, "mvn", "system apk add openjdk8 maven")
|
|
||||||
IsAlpine(m, "python", "system apk add python2")
|
IsAlpine(m, "python", "system apk add python2")
|
||||||
IsAlpine(m, "python2", "system apk add python2")
|
IsAlpine(m, "python2", "system apk add python2")
|
||||||
IsAlpine(m, "python3", "system apk add python3")
|
IsAlpine(m, "python3", "system apk add python3")
|
||||||
|
IsAlpine(m, "mvn", "system apk add openjdk8 maven")
|
||||||
|
IsAlpine(m, "javac", "system apk add openjdk8")
|
||||||
|
IsAlpine(m, "java", "system apk add openjdk8")
|
||||||
})
|
})
|
||||||
}},
|
}},
|
||||||
mdb.CREATE: {Name: "create cli cmd", Help: "创建"},
|
mdb.CREATE: {Name: "create cli cmd", Help: "创建"},
|
||||||
|
@ -34,7 +34,7 @@ func _system_cmd(m *ice.Message, arg ...string) *exec.Cmd {
|
|||||||
}
|
}
|
||||||
// 自动安装
|
// 自动安装
|
||||||
if _system_find(m, arg[0]) == "" {
|
if _system_find(m, arg[0]) == "" {
|
||||||
if cmds := m.Cmd(MIRROR, arg[0]).Append("cmd"); cmds != "" {
|
if cmds := m.Cmd(MIRRORS, arg[0]).Append("cmd"); cmds != "" {
|
||||||
m.Cmd(kit.Split(cmds))
|
m.Cmd(kit.Split(cmds))
|
||||||
if file := _system_find(m, arg[0]); file != "" {
|
if file := _system_find(m, arg[0]); file != "" {
|
||||||
m.Debug("cmd: %v", file)
|
m.Debug("cmd: %v", file)
|
||||||
|
@ -88,6 +88,7 @@ func RenderCookie(msg *ice.Message, value string, arg ...string) { // name path
|
|||||||
Name: kit.Select(CookieName(msg.Option(ice.MSG_USERWEB)), arg, 0), Path: kit.Select(ice.PS, arg, 1), Expires: expire})
|
Name: kit.Select(CookieName(msg.Option(ice.MSG_USERWEB)), arg, 0), Path: kit.Select(ice.PS, arg, 1), Expires: expire})
|
||||||
}
|
}
|
||||||
func RenderRedirect(msg *ice.Message, arg ...string) {
|
func RenderRedirect(msg *ice.Message, arg ...string) {
|
||||||
|
// http.Redirect(msg.W, msg.R, kit.MergeURL(arg[0], arg[1:]), http.StatusTemporaryRedirect)
|
||||||
http.Redirect(msg.W, msg.R, kit.MergeURL(arg[0], arg[1:]), http.StatusMovedPermanently)
|
http.Redirect(msg.W, msg.R, kit.MergeURL(arg[0], arg[1:]), http.StatusMovedPermanently)
|
||||||
}
|
}
|
||||||
func RenderType(w http.ResponseWriter, name, mime string) {
|
func RenderType(w http.ResponseWriter, name, mime string) {
|
||||||
|
@ -187,7 +187,6 @@ func _serve_handle(key string, cmd *ice.Command, msg *ice.Message, w http.Respon
|
|||||||
}
|
}
|
||||||
|
|
||||||
msg.Option(ice.MSG_OUTPUT, "")
|
msg.Option(ice.MSG_OUTPUT, "")
|
||||||
msg.Option(ice.MSG_ARGS, kit.List())
|
|
||||||
if cmds, ok := _serve_login(msg, key, kit.Simple(msg.Optionv(ice.MSG_CMDS)), w, r); ok {
|
if cmds, ok := _serve_login(msg, key, kit.Simple(msg.Optionv(ice.MSG_CMDS)), w, r); ok {
|
||||||
msg.Option(ice.MSG_OPTS, msg.Optionv(ice.MSG_OPTION))
|
msg.Option(ice.MSG_OPTS, msg.Optionv(ice.MSG_OPTION))
|
||||||
msg.Target().Cmd(msg, key, cmds...) // 执行命令
|
msg.Target().Cmd(msg, key, cmds...) // 执行命令
|
||||||
@ -195,7 +194,17 @@ func _serve_handle(key string, cmd *ice.Command, msg *ice.Message, w http.Respon
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 输出响应
|
// 输出响应
|
||||||
Render(msg, msg.Option(ice.MSG_OUTPUT), msg.Optionv(ice.MSG_ARGS).([]interface{})...)
|
switch args := msg.Optionv(ice.MSG_ARGS).(type) {
|
||||||
|
case []interface{}:
|
||||||
|
msg.Debug("what %v", args)
|
||||||
|
Render(msg, msg.Option(ice.MSG_OUTPUT), args...)
|
||||||
|
case []string:
|
||||||
|
msg.Debug("what %v", args)
|
||||||
|
Render(msg, msg.Option(ice.MSG_OUTPUT), args)
|
||||||
|
default:
|
||||||
|
msg.Debug("what %v", args)
|
||||||
|
Render(msg, msg.Option(ice.MSG_OUTPUT), kit.List())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
func _serve_login(msg *ice.Message, key string, cmds []string, w http.ResponseWriter, r *http.Request) ([]string, bool) {
|
func _serve_login(msg *ice.Message, key string, cmds []string, w http.ResponseWriter, r *http.Request) ([]string, bool) {
|
||||||
aaa.SessCheck(msg, msg.Option(ice.MSG_SESSID)) // 会话认证
|
aaa.SessCheck(msg, msg.Option(ice.MSG_SESSID)) // 会话认证
|
||||||
|
117
core/chat/cmd.go
117
core/chat/cmd.go
@ -13,6 +13,67 @@ import (
|
|||||||
kit "shylinux.com/x/toolkits"
|
kit "shylinux.com/x/toolkits"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func _cmd_file(m *ice.Message, arg ...string) bool {
|
||||||
|
if mdb.HashSelect(m.Spawn(), path.Join(arg...)).Table(func(index int, value map[string]string, head []string) {
|
||||||
|
m.RenderCmd(value[mdb.NAME])
|
||||||
|
}).Length() > 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
p := path.Join(m.Config(nfs.PATH), path.Join(arg...))
|
||||||
|
if mdb.HashSelect(m.Spawn(), kit.Ext(p)).Table(func(index int, value map[string]string, head []string) {
|
||||||
|
m.RenderCmd(value[mdb.NAME], p)
|
||||||
|
}).Length() > 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
switch p := path.Join(arg...); kit.Ext(p) {
|
||||||
|
case nfs.HTML:
|
||||||
|
m.RenderResult(m.Cmdx(nfs.CAT, p))
|
||||||
|
|
||||||
|
case nfs.CSS:
|
||||||
|
|
||||||
|
case nfs.JS:
|
||||||
|
m.Display(ice.FileURI(p))
|
||||||
|
if cmd := ice.GetFileCmd(p); cmd != "" {
|
||||||
|
m.RenderCmd(cmd)
|
||||||
|
} else {
|
||||||
|
m.RenderCmd("can.info")
|
||||||
|
}
|
||||||
|
|
||||||
|
case nfs.GO:
|
||||||
|
if cmd := ice.GetFileCmd(p); cmd != "" {
|
||||||
|
m.RenderCmd(cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
case nfs.SH:
|
||||||
|
if cmd := ice.GetFileCmd(p); cmd != "" {
|
||||||
|
msg := m.Cmd(cmd, ice.OptionFields(""))
|
||||||
|
if msg.Length() > 0 {
|
||||||
|
msg.Table()
|
||||||
|
}
|
||||||
|
m.Cmdy(cli.SYSTEM, "sh", p, msg.Result())
|
||||||
|
m.RenderResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
case "txt":
|
||||||
|
m.RenderCmd("can.parse", m.Cmdx(nfs.CAT, p))
|
||||||
|
|
||||||
|
case "iml":
|
||||||
|
if m.Option(ice.MSG_USERPOD) == "" {
|
||||||
|
m.RenderRedirect(path.Join(CHAT_WEBSITE, strings.TrimPrefix(p, SRC_WEBSITE)))
|
||||||
|
m.Option(ice.MSG_ARGS, m.Option(ice.MSG_ARGS))
|
||||||
|
} else {
|
||||||
|
m.RenderRedirect(path.Join("/chat/pod", m.Option(ice.MSG_USERPOD), "website", strings.TrimPrefix(p, SRC_WEBSITE)))
|
||||||
|
m.Option(ice.MSG_ARGS, m.Option(ice.MSG_ARGS))
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
const CMD = "cmd"
|
const CMD = "cmd"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -35,46 +96,7 @@ func init() {
|
|||||||
m.RenderCmd(CMD)
|
m.RenderCmd(CMD)
|
||||||
return // 目录
|
return // 目录
|
||||||
}
|
}
|
||||||
|
if _cmd_file(m, arg...) {
|
||||||
if mdb.HashSelect(m.Spawn(), path.Join(arg...)).Table(func(index int, value map[string]string, head []string) {
|
|
||||||
m.RenderCmd(value[mdb.NAME])
|
|
||||||
}).Length() > 0 {
|
|
||||||
return // 命令
|
|
||||||
}
|
|
||||||
|
|
||||||
p := path.Join(m.Config(nfs.PATH), path.Join(arg...))
|
|
||||||
if mdb.HashSelect(m.Spawn(), kit.Ext(m.R.URL.Path)).Table(func(index int, value map[string]string, head []string) {
|
|
||||||
m.RenderCmd(value[mdb.NAME], p)
|
|
||||||
}).Length() > 0 {
|
|
||||||
return // 插件
|
|
||||||
}
|
|
||||||
|
|
||||||
switch p := path.Join(arg...); kit.Ext(p) {
|
|
||||||
case nfs.CSS:
|
|
||||||
|
|
||||||
case nfs.JS:
|
|
||||||
if cmd := ice.GetFileCmd(p); cmd != "" {
|
|
||||||
m.Display(ice.FileURI(p))
|
|
||||||
m.RenderCmd(cmd)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
case nfs.GO:
|
|
||||||
if cmd := ice.GetFileCmd(p); cmd != "" {
|
|
||||||
m.RenderCmd(cmd)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
case nfs.SH:
|
|
||||||
if cmd := ice.GetFileCmd(p); cmd != "" {
|
|
||||||
msg := m.Cmd(cmd, ice.OptionFields(""))
|
|
||||||
if msg.Length() > 0 {
|
|
||||||
msg.Table()
|
|
||||||
}
|
|
||||||
m.Cmdy(cli.SYSTEM, "sh", p, msg.Result())
|
|
||||||
m.RenderResult()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
case "iml":
|
|
||||||
m.RenderRedirect(path.Join(CHAT_WEBSITE, strings.TrimPrefix(p, SRC_WEBSITE)))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +107,7 @@ func init() {
|
|||||||
} else if m.Cmdy(ctx.COMMAND, arg[0]); m.Length() > 0 {
|
} else if m.Cmdy(ctx.COMMAND, arg[0]); m.Length() > 0 {
|
||||||
m.RenderCmd(arg[0], arg[1:]) // 本地命令
|
m.RenderCmd(arg[0], arg[1:]) // 本地命令
|
||||||
} else {
|
} else {
|
||||||
m.RenderDownload(p) // 文件
|
m.RenderDownload(path.Join(m.Config(nfs.PATH), path.Join(arg...))) // 文件
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
CMD: {Name: "cmd path auto upload up home", Help: "命令", Action: ice.MergeAction(map[string]*ice.Action{
|
CMD: {Name: "cmd path auto upload up home", Help: "命令", Action: ice.MergeAction(map[string]*ice.Action{
|
||||||
@ -106,13 +128,16 @@ func init() {
|
|||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
}, mdb.HashAction()), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
}, mdb.HashAction()), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||||
if len(arg) > 0 {
|
if msg := m.Cmd(ctx.COMMAND, arg[0]); msg.Length() > 0 {
|
||||||
m.ProcessLocation(arg[0])
|
m.RenderCmd(arg[0])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch p := path.Join(arg...); kit.Ext(p) {
|
if _cmd_file(m, arg...) {
|
||||||
case "html":
|
return
|
||||||
m.RenderResult(m.Cmdx(nfs.CAT, path.Join(ice.SRC, path.Join(arg...))))
|
}
|
||||||
|
|
||||||
|
if len(arg) > 0 {
|
||||||
|
m.ProcessLocation(arg[0])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
m.Option(nfs.DIR_ROOT, path.Join(m.Config(nfs.PATH), strings.TrimPrefix(path.Dir(m.R.URL.Path), "/cmd")))
|
m.Option(nfs.DIR_ROOT, path.Join(m.Config(nfs.PATH), strings.TrimPrefix(path.Dir(m.R.URL.Path), "/cmd")))
|
||||||
|
@ -42,7 +42,7 @@ func init() {
|
|||||||
m.RenderWebsite(arg[0], path.Join(arg[2:]...))
|
m.RenderWebsite(arg[0], path.Join(arg[2:]...))
|
||||||
|
|
||||||
} else if arg[1] == "cmd" { // 节点命令
|
} else if arg[1] == "cmd" { // 节点命令
|
||||||
m.Cmdy("/cmd/", path.Join(arg[2:]...))
|
m.Cmdy(web.SPACE, arg[0], m.Prefix(CMD), path.Join(arg[2:]...))
|
||||||
} else {
|
} else {
|
||||||
m.Cmdy(web.SPACE, m.Option(ice.MSG_USERPOD), "web.chat."+ice.PS+path.Join(arg[1:]...))
|
m.Cmdy(web.SPACE, m.Option(ice.MSG_USERPOD), "web.chat."+ice.PS+path.Join(arg[1:]...))
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,10 @@ func _website_render(m *ice.Message, w http.ResponseWriter, r *http.Request, kin
|
|||||||
r.URL.Path = "/chat/cmd/web.chat.div"
|
r.URL.Path = "/chat/cmd/web.chat.div"
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case nfs.IML, nfs.TXT:
|
case nfs.TXT:
|
||||||
|
msg.RenderCmd("can.parse", text)
|
||||||
|
|
||||||
|
case nfs.IML:
|
||||||
res, _ := _website_parse(msg, text)
|
res, _ := _website_parse(msg, text)
|
||||||
msg.RenderResult(_website_template2, kit.Format(res))
|
msg.RenderResult(_website_template2, kit.Format(res))
|
||||||
case nfs.JSON:
|
case nfs.JSON:
|
||||||
@ -194,6 +197,7 @@ func init() {
|
|||||||
Index.Merge(&ice.Context{Configs: map[string]*ice.Config{
|
Index.Merge(&ice.Context{Configs: map[string]*ice.Config{
|
||||||
WEBSITE: {Name: "website", Help: "网站", Value: kit.Data(mdb.SHORT, nfs.PATH, mdb.FIELD, "time,path,type,name,text")},
|
WEBSITE: {Name: "website", Help: "网站", Value: kit.Data(mdb.SHORT, nfs.PATH, mdb.FIELD, "time,path,type,name,text")},
|
||||||
}, Commands: map[string]*ice.Command{
|
}, Commands: map[string]*ice.Command{
|
||||||
|
"/website/": {Name: "/website/", Help: "网站", Action: ice.MergeAction(map[string]*ice.Action{}, ctx.CmdAction())},
|
||||||
WEBSITE: {Name: "website path auto create import", Help: "网站", Action: ice.MergeAction(map[string]*ice.Action{
|
WEBSITE: {Name: "website path auto create import", Help: "网站", Action: ice.MergeAction(map[string]*ice.Action{
|
||||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||||
m.Cmd(mdb.RENDER, mdb.CREATE, nfs.IML, m.PrefixKey())
|
m.Cmd(mdb.RENDER, mdb.CREATE, nfs.IML, m.PrefixKey())
|
||||||
@ -209,8 +213,10 @@ func init() {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(r.URL.Path, CHAT_WEBSITE) {
|
if strings.HasPrefix(r.URL.Path, CHAT_WEBSITE) {
|
||||||
_website_render(m, w, r, kit.Ext(r.URL.Path), m.Cmdx(nfs.CAT, strings.Replace(r.URL.Path, CHAT_WEBSITE, SRC_WEBSITE, 1)))
|
if r.Method == http.MethodGet {
|
||||||
return true
|
_website_render(m, w, r, kit.Ext(r.URL.Path), m.Cmdx(nfs.CAT, strings.Replace(r.URL.Path, CHAT_WEBSITE, SRC_WEBSITE, 1)))
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
@ -31,6 +31,32 @@ func init() {
|
|||||||
m.Option(mdb.TEXT, strings.TrimSpace(m.Option(mdb.TEXT)))
|
m.Option(mdb.TEXT, strings.TrimSpace(m.Option(mdb.TEXT)))
|
||||||
m.Cmdy(TEMPLATE, nfs.DEFS)
|
m.Cmdy(TEMPLATE, nfs.DEFS)
|
||||||
}},
|
}},
|
||||||
|
"complete": {Name: "complete", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
|
||||||
|
switch m.Option("key") {
|
||||||
|
case "ice", "*ice":
|
||||||
|
m.Push("name", "Message")
|
||||||
|
m.Push("name", "Context")
|
||||||
|
default:
|
||||||
|
if strings.HasSuffix(m.Option("pre"), " index ") {
|
||||||
|
m.OptionFields("index")
|
||||||
|
m.Cmdy(ctx.COMMAND, mdb.SEARCH, ctx.COMMAND, "", "")
|
||||||
|
} else if strings.HasSuffix(m.Option("pre"), " action ") {
|
||||||
|
m.Push("name", "auto")
|
||||||
|
} else if strings.HasSuffix(m.Option("pre"), " type ") {
|
||||||
|
m.Push("name", "menu")
|
||||||
|
} else if strings.HasSuffix(m.Option("pre"), " ") {
|
||||||
|
m.Push("name", "index")
|
||||||
|
m.Push("name", "action")
|
||||||
|
m.Push("name", "args")
|
||||||
|
m.Push("name", "type")
|
||||||
|
} else if m.Option("pre") == "" {
|
||||||
|
m.Push("name", "left")
|
||||||
|
m.Push("name", "head")
|
||||||
|
m.Push("name", "main")
|
||||||
|
m.Push("name", "foot")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}},
|
||||||
"website": {Name: "script file=hi.iml text=", Help: "网页", Hand: func(m *ice.Message, arg ...string) {
|
"website": {Name: "script file=hi.iml text=", Help: "网页", Hand: func(m *ice.Message, arg ...string) {
|
||||||
m.Option(nfs.FILE, path.Join("website", m.Option(nfs.FILE)))
|
m.Option(nfs.FILE, path.Join("website", m.Option(nfs.FILE)))
|
||||||
m.Option(mdb.TEXT, strings.TrimSpace(m.Option(mdb.TEXT)))
|
m.Option(mdb.TEXT, strings.TrimSpace(m.Option(mdb.TEXT)))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user