mirror of
https://shylinux.com/x/ContextOS
synced 2025-04-25 16:58:06 +08:00
del honor
This commit is contained in:
parent
49e374d4ff
commit
99bfd420bd
6
go.mod
6
go.mod
@ -15,7 +15,7 @@ replace (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
shylinux.com/x/ice v1.4.5
|
shylinux.com/x/ice v1.4.6
|
||||||
shylinux.com/x/icebergs v1.8.5
|
shylinux.com/x/icebergs v1.8.6
|
||||||
shylinux.com/x/toolkits v1.0.0
|
shylinux.com/x/toolkits v1.0.1
|
||||||
)
|
)
|
||||||
|
18
go.sum
18
go.sum
@ -2,18 +2,12 @@ shylinux.com/x/go-git/v5 v5.6.7 h1:WD5QSco7m3QooPCgdvQ6/GyGIFPun8C+hex5N41LYlk=
|
|||||||
shylinux.com/x/go-git/v5 v5.6.7/go.mod h1:Qb0lA+uIrofZg8NQerhYcJHgGWixFqvS6p3aJ/L5Nlk=
|
shylinux.com/x/go-git/v5 v5.6.7/go.mod h1:Qb0lA+uIrofZg8NQerhYcJHgGWixFqvS6p3aJ/L5Nlk=
|
||||||
shylinux.com/x/go-qrcode v0.0.3 h1:RMo+Vidbgq3HatLBj7DDXcTbTLFUwzis5K7TqBkD38U=
|
shylinux.com/x/go-qrcode v0.0.3 h1:RMo+Vidbgq3HatLBj7DDXcTbTLFUwzis5K7TqBkD38U=
|
||||||
shylinux.com/x/go-qrcode v0.0.3/go.mod h1:KAbtU+KwiiABMZ/CJ0zh9PI2AX82Uf9rRYcQ4ODm4po=
|
shylinux.com/x/go-qrcode v0.0.3/go.mod h1:KAbtU+KwiiABMZ/CJ0zh9PI2AX82Uf9rRYcQ4ODm4po=
|
||||||
shylinux.com/x/ice v1.4.4 h1:ycQ3MJ0vdzoieAKrXaAS9BPuuWKpunIIDc82ZvQDUhY=
|
shylinux.com/x/ice v1.4.6 h1:9bZ1MIht3J20mIpPWwrbMLOfZqnfBjX2lsDQSUU1w2c=
|
||||||
shylinux.com/x/ice v1.4.4/go.mod h1:L6Ey1W3XMAZLvlVAXTaiurrCD0OR/5QfxXEDot3mbHw=
|
shylinux.com/x/ice v1.4.6/go.mod h1:or84ZamFWv4uln4CnzJHlBMl/O11RPwecm4WlE6IXUc=
|
||||||
shylinux.com/x/ice v1.4.5 h1:y+L7PK3Lf/N/clOHd0tD0QUh7xHDWLLYIHXEovz40pw=
|
shylinux.com/x/icebergs v1.8.6 h1:/LhsXE9S384BQdutgDqo9X3HETq41LWDmO8zRwOesos=
|
||||||
shylinux.com/x/ice v1.4.5/go.mod h1:gGMjGWvuvr8vRTPZI3DqSkvdtX3eOEKss2QIP4sH5TE=
|
shylinux.com/x/icebergs v1.8.6/go.mod h1:4E+FVUqqnCfeQr8Dsh9T2jOl9tEWaXFS+5R1GFwky2g=
|
||||||
shylinux.com/x/icebergs v1.8.4 h1:ak7ZteykXBCWjhSwFyC2JjASfigZrpm9BtN9mn/6E5M=
|
|
||||||
shylinux.com/x/icebergs v1.8.4/go.mod h1:9iX2Tg2y4THWiW6+BBUgFt5vMCoFWDtiIPw4lfMP+rI=
|
|
||||||
shylinux.com/x/icebergs v1.8.5 h1:z0aNKY8rGQivpv8L/OWpG8AIr07ndN7j9kF+WTM072s=
|
|
||||||
shylinux.com/x/icebergs v1.8.5/go.mod h1:Ob8PHoRK4MQXzj4dqWaSQGdwHo5yhuOAaGgGM9eXaoY=
|
|
||||||
shylinux.com/x/toolkits v0.7.10/go.mod h1:CHDJarGlDkg60kVsvMLYL/a5hAnRLEOShiEsMOuEp0Q=
|
shylinux.com/x/toolkits v0.7.10/go.mod h1:CHDJarGlDkg60kVsvMLYL/a5hAnRLEOShiEsMOuEp0Q=
|
||||||
shylinux.com/x/toolkits v0.8.4 h1:EEF+49x9a0gvtth15RZR1e+eutRFFf4F77QDjXN6DDM=
|
shylinux.com/x/toolkits v1.0.1 h1:qG0Do0mDxObMwNa8KqCIT8RAn+7T2dWXTYGeAQX4o6c=
|
||||||
shylinux.com/x/toolkits v0.8.4/go.mod h1:CHDJarGlDkg60kVsvMLYL/a5hAnRLEOShiEsMOuEp0Q=
|
shylinux.com/x/toolkits v1.0.1/go.mod h1:CHDJarGlDkg60kVsvMLYL/a5hAnRLEOShiEsMOuEp0Q=
|
||||||
shylinux.com/x/toolkits v1.0.0 h1:6QaJtX7KMSGXEtN04GcQqTxS1PcrMMgKbp+qYv+yowU=
|
|
||||||
shylinux.com/x/toolkits v1.0.0/go.mod h1:CHDJarGlDkg60kVsvMLYL/a5hAnRLEOShiEsMOuEp0Q=
|
|
||||||
shylinux.com/x/websocket v0.0.3 h1:edhLwCp0Mv1ITXqIwbVWdXdX2+vui/jRnS25K89k68I=
|
shylinux.com/x/websocket v0.0.3 h1:edhLwCp0Mv1ITXqIwbVWdXdX2+vui/jRnS25K89k68I=
|
||||||
shylinux.com/x/websocket v0.0.3/go.mod h1:3UGWkjTu3ie5NAZen7J+uLPBrO7DFeKloj6Jxo13Oiw=
|
shylinux.com/x/websocket v0.0.3/go.mod h1:3UGWkjTu3ie5NAZen7J+uLPBrO7DFeKloj6Jxo13Oiw=
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,11 +0,0 @@
|
|||||||
package cli
|
|
||||||
|
|
||||||
var version = struct {
|
|
||||||
init []string
|
|
||||||
time string
|
|
||||||
host string
|
|
||||||
self int
|
|
||||||
}{
|
|
||||||
[]string{"2017-11-01 01:02:03", "2019-07-13 18:02:21"},
|
|
||||||
`2019-11-29 12:39:40`, `mac`, 658,
|
|
||||||
}
|
|
@ -1,240 +0,0 @@
|
|||||||
package ctx
|
|
||||||
|
|
||||||
import (
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"bytes"
|
|
||||||
"io"
|
|
||||||
"path"
|
|
||||||
"strings"
|
|
||||||
"toolkit"
|
|
||||||
)
|
|
||||||
|
|
||||||
func index(name string, arg ...interface{}) interface{} {
|
|
||||||
if len(arg) == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
switch m := arg[0].(type) {
|
|
||||||
case *Message:
|
|
||||||
if len(arg) == 1 {
|
|
||||||
return m.Meta[name]
|
|
||||||
}
|
|
||||||
|
|
||||||
switch value := arg[1].(type) {
|
|
||||||
case int:
|
|
||||||
if 0 <= value && value < len(m.Meta[name]) {
|
|
||||||
return m.Meta[name][value]
|
|
||||||
}
|
|
||||||
case string:
|
|
||||||
if len(arg) == 2 {
|
|
||||||
if name == "option" {
|
|
||||||
return m.Optionv(value)
|
|
||||||
} else {
|
|
||||||
return m.Append(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch val := arg[2].(type) {
|
|
||||||
case int:
|
|
||||||
switch list := m.Optionv(value).(type) {
|
|
||||||
case []string:
|
|
||||||
if 0 <= val && val < len(list) {
|
|
||||||
return list[val]
|
|
||||||
}
|
|
||||||
case []interface{}:
|
|
||||||
if 0 <= val && val < len(list) {
|
|
||||||
return list[val]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case map[string][]string:
|
|
||||||
if len(arg) == 1 {
|
|
||||||
return m[name]
|
|
||||||
}
|
|
||||||
|
|
||||||
switch value := arg[1].(type) {
|
|
||||||
case int:
|
|
||||||
return m[name][value]
|
|
||||||
case string:
|
|
||||||
if len(arg) == 2 {
|
|
||||||
return m[value]
|
|
||||||
}
|
|
||||||
switch val := arg[2].(type) {
|
|
||||||
case int:
|
|
||||||
return m[value][val]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case []string:
|
|
||||||
if len(arg) == 1 {
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
switch value := arg[1].(type) {
|
|
||||||
case int:
|
|
||||||
return m[value]
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
var CGI = template.FuncMap{
|
|
||||||
"options": func(arg ...interface{}) string {
|
|
||||||
switch value := index("option", arg...).(type) {
|
|
||||||
case string:
|
|
||||||
return value
|
|
||||||
case []string:
|
|
||||||
return strings.Join(value, "")
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
},
|
|
||||||
"option": func(arg ...interface{}) interface{} {
|
|
||||||
return index("option", arg...)
|
|
||||||
},
|
|
||||||
"conf": func(arg ...interface{}) interface{} {
|
|
||||||
switch m := arg[0].(type) {
|
|
||||||
case *Message:
|
|
||||||
switch c := arg[1].(type) {
|
|
||||||
case string:
|
|
||||||
if len(arg) == 2 {
|
|
||||||
return m.Confv(c)
|
|
||||||
}
|
|
||||||
if len(arg) == 3 {
|
|
||||||
return m.Confv(c, arg[2])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
"cmd": func(arg ...interface{}) interface{} {
|
|
||||||
switch m := arg[0].(type) {
|
|
||||||
case *Message:
|
|
||||||
switch c := arg[1].(type) {
|
|
||||||
case string:
|
|
||||||
return m.Cmd(c, arg[2:])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
"appends": func(arg ...interface{}) interface{} {
|
|
||||||
switch value := index("append", arg...).(type) {
|
|
||||||
case string:
|
|
||||||
return value
|
|
||||||
case []string:
|
|
||||||
return strings.Join(value, "")
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
},
|
|
||||||
"append": func(arg ...interface{}) interface{} {
|
|
||||||
switch m := arg[0].(type) {
|
|
||||||
case *Message:
|
|
||||||
if len(arg) == 1 {
|
|
||||||
return m.Meta["append"]
|
|
||||||
}
|
|
||||||
if len(arg) > 1 {
|
|
||||||
switch c := arg[1].(type) {
|
|
||||||
case string:
|
|
||||||
if len(arg) > 2 {
|
|
||||||
switch i := arg[2].(type) {
|
|
||||||
case int:
|
|
||||||
return kit.Select("", m.Meta[c], i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m.Meta[c]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
"trans": func(arg ...interface{}) interface{} {
|
|
||||||
switch m := arg[0].(type) {
|
|
||||||
case *Message:
|
|
||||||
list := [][]string{m.Meta["append"]}
|
|
||||||
m.Table(func(index int, value map[string]string) {
|
|
||||||
line := []string{}
|
|
||||||
for _, k := range m.Meta["append"] {
|
|
||||||
line = append(line, value[k])
|
|
||||||
}
|
|
||||||
list = append(list, line)
|
|
||||||
})
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
"result": func(arg ...interface{}) interface{} {
|
|
||||||
switch m := arg[0].(type) {
|
|
||||||
case *Message:
|
|
||||||
return m.Meta["result"]
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
"results": func(arg ...interface{}) interface{} {
|
|
||||||
switch m := arg[0].(type) {
|
|
||||||
case *Message:
|
|
||||||
return strings.Join(m.Meta["result"], "")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func LocalCGI(m *Message, c *Context) *template.FuncMap {
|
|
||||||
cgi := template.FuncMap{
|
|
||||||
"format": func(arg ...interface{}) interface{} {
|
|
||||||
switch msg := arg[0].(type) {
|
|
||||||
case *Message:
|
|
||||||
buffer := bytes.NewBuffer([]byte{})
|
|
||||||
tmpl := m.Optionv("tmpl").(*template.Template)
|
|
||||||
m.Assert(tmpl.ExecuteTemplate(buffer, kit.Select("table", arg, 1), msg))
|
|
||||||
return string(buffer.Bytes())
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for k, v := range c.Commands {
|
|
||||||
if strings.HasPrefix(k, "/") || strings.HasPrefix(k, "_") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
func(k string, v *Command) {
|
|
||||||
cgi[k] = func(arg ...interface{}) (res interface{}) {
|
|
||||||
m.TryCatch(m.Spawn(), true, func(msg *Message) {
|
|
||||||
|
|
||||||
v.Hand(msg, c, k, msg.Form(v, kit.Trans(arg))...)
|
|
||||||
|
|
||||||
buffer := bytes.NewBuffer([]byte{})
|
|
||||||
m.Assert(m.Optionv("tmpl").(*template.Template).ExecuteTemplate(buffer,
|
|
||||||
kit.Select(kit.Select("code", "table", len(msg.Meta["append"]) > 0), msg.Option("render")), msg))
|
|
||||||
res = string(buffer.Bytes())
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}(k, v)
|
|
||||||
}
|
|
||||||
for k, v := range CGI {
|
|
||||||
cgi[k] = v
|
|
||||||
}
|
|
||||||
return &cgi
|
|
||||||
}
|
|
||||||
func ExecuteFile(m *Message, w io.Writer, p string) error {
|
|
||||||
tmpl := template.New("render").Funcs(CGI)
|
|
||||||
tmpl.ParseGlob(p)
|
|
||||||
return tmpl.ExecuteTemplate(w, path.Base(p), m)
|
|
||||||
}
|
|
||||||
func ExecuteStr(m *Message, w io.Writer, p string) error {
|
|
||||||
tmpl := template.New("render").Funcs(CGI)
|
|
||||||
tmpl, _ = tmpl.Parse(p)
|
|
||||||
return tmpl.Execute(w, m)
|
|
||||||
}
|
|
||||||
func Execute(m *Message, p string) string {
|
|
||||||
m.Log("fuck", "waht %v", path.Join(m.Conf("route", "template_dir"), "/*.tmpl"))
|
|
||||||
t := template.Must(template.New("render").Funcs(CGI).ParseGlob(path.Join(m.Conf("route", "template_dir"), "/*.tmpl")))
|
|
||||||
for _, v := range t.Templates() {
|
|
||||||
m.Log("fuck", "waht %v", v.Name())
|
|
||||||
}
|
|
||||||
buf := bytes.NewBuffer(make([]byte, 0, 1024))
|
|
||||||
t.ExecuteTemplate(buf, p, m)
|
|
||||||
m.Log("fuck", "waht %v", p)
|
|
||||||
m.Log("fuck", "waht %v", buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
@ -1,574 +0,0 @@
|
|||||||
package ctx
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
"toolkit"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *Context) Register(s *Context, x Server, args ...interface{}) *Context {
|
|
||||||
name, force := s.Name, false
|
|
||||||
if len(args) > 0 {
|
|
||||||
switch arg := args[0].(type) {
|
|
||||||
case bool:
|
|
||||||
force = arg
|
|
||||||
case string:
|
|
||||||
force = true
|
|
||||||
name, s.Name = arg, arg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.contexts == nil {
|
|
||||||
c.contexts = make(map[string]*Context)
|
|
||||||
}
|
|
||||||
if x, ok := c.contexts[name]; ok && !force {
|
|
||||||
panic(errors.New(c.Name + "上下文中已存在模块:" + x.Name))
|
|
||||||
}
|
|
||||||
|
|
||||||
c.contexts[name] = s
|
|
||||||
s.context = c
|
|
||||||
s.Server = x
|
|
||||||
s.root = c.root
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
func (c *Context) Plugin(s *Context, args []string) string {
|
|
||||||
c.Register(s, nil)
|
|
||||||
m := Pulse.Spawn(s)
|
|
||||||
// m := &Message{code: 0, time: time.Now(), source: s, target: s, Meta: map[string][]string{}}
|
|
||||||
// kit.DisableLog = true
|
|
||||||
m.Option("log.disable", false)
|
|
||||||
m.Option("bio.modal", "action")
|
|
||||||
|
|
||||||
if len(args) == 0 {
|
|
||||||
m.Echo("%s: %s\n\n", s.Name, s.Help)
|
|
||||||
m.Echo("命令列表:\n")
|
|
||||||
for k, v := range s.Commands {
|
|
||||||
if !strings.HasPrefix(k, "_") {
|
|
||||||
m.Echo("--%s: %s\n %v\n\n", k, v.Name, v.Help)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Echo("配置列表:\n")
|
|
||||||
for k, v := range s.Configs {
|
|
||||||
if !strings.HasPrefix(k, "_") {
|
|
||||||
m.Echo("--%s(%v): %s\n", k, kit.Formats(v.Value), v.Help)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if Index.Begin(Pulse, args...); Index.Start(Pulse, args...) {
|
|
||||||
}
|
|
||||||
m.Cmd(args)
|
|
||||||
}
|
|
||||||
for _, v := range m.Meta["result"] {
|
|
||||||
fmt.Printf(v)
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
func (c *Context) Spawn(m *Message, name string, help string) *Context {
|
|
||||||
s := &Context{Name: name, Help: help, root: c.root, context: c, message: m,
|
|
||||||
Caches: map[string]*Cache{},
|
|
||||||
Configs: map[string]*Config{},
|
|
||||||
Commands: map[string]*Command{},
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.target = s; c.Server != nil {
|
|
||||||
c.Register(s, c.Server.Spawn(m, s, m.Meta["detail"]...))
|
|
||||||
} else {
|
|
||||||
c.Register(s, nil)
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
func (c *Context) Begin(m *Message, arg ...string) *Context {
|
|
||||||
if len(arg) > 0 {
|
|
||||||
m.Set("detail", arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
module := c.Name
|
|
||||||
if c.context != nil && c.context.Caches != nil && c.context.Caches["module"] != nil {
|
|
||||||
module = c.context.Caches["module"].Value + "." + c.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Caches["module"] = &Cache{Name: "module", Value: module, Help: "模块域名"}
|
|
||||||
c.Caches["status"] = &Cache{Name: "status(begin/start/close)", Value: "begin", Help: "模块状态, begin: 初始完成, start: 正在运行, close: 运行结束"}
|
|
||||||
c.Caches["stream"] = &Cache{Name: "stream", Value: "", Help: "模块数据"}
|
|
||||||
|
|
||||||
c.message = m
|
|
||||||
c.requests = append(c.requests, m)
|
|
||||||
m.source.sessions = append(m.source.sessions, m)
|
|
||||||
c.exit = make(chan bool, 3)
|
|
||||||
|
|
||||||
if c.Server != nil {
|
|
||||||
c.Server.Begin(m, m.Meta["detail"]...)
|
|
||||||
}
|
|
||||||
m.root.Capi("ncontext", 1)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
func (c *Context) Start(m *Message, arg ...string) bool {
|
|
||||||
sync := false
|
|
||||||
if len(arg) > 0 && arg[0] == "sync" {
|
|
||||||
sync, arg = true, arg[1:]
|
|
||||||
}
|
|
||||||
if len(arg) > 0 {
|
|
||||||
m.Set("detail", arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.requests = append(c.requests, m)
|
|
||||||
m.source.sessions = append(m.source.sessions, m)
|
|
||||||
|
|
||||||
if m.Hand = true; m.Cap("status") == "start" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Gos(m, func(m *Message) {
|
|
||||||
m.Log(m.Cap("status", "start"), "%d server %v %v", m.Capi("nserver", 1), m.Meta["detail"], m.Meta["option"])
|
|
||||||
|
|
||||||
c.message = m
|
|
||||||
if c.exit <- false; c.Server == nil || c.Server.Start(m, m.Meta["detail"]...) {
|
|
||||||
c.Close(m, m.Meta["detail"]...)
|
|
||||||
c.exit <- true
|
|
||||||
}
|
|
||||||
}, func(m *Message) {
|
|
||||||
c.Close(m, m.Meta["detail"]...)
|
|
||||||
c.exit <- true
|
|
||||||
})
|
|
||||||
|
|
||||||
if sync {
|
|
||||||
for !<-c.exit {
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return <-c.exit
|
|
||||||
}
|
|
||||||
func (c *Context) Close(m *Message, arg ...string) bool {
|
|
||||||
if len(c.requests) == 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.target == c {
|
|
||||||
for i := len(c.requests) - 1; i >= 0; i-- {
|
|
||||||
if msg := c.requests[i]; msg.code == m.code {
|
|
||||||
if c.Server == nil || c.Server.Close(m, arg...) {
|
|
||||||
msg.Free()
|
|
||||||
for j := i; j < len(c.requests)-1; j++ {
|
|
||||||
c.requests[j] = c.requests[j+1]
|
|
||||||
}
|
|
||||||
c.requests = c.requests[:len(c.requests)-1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(c.requests) > 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.Cap("status") == "start" {
|
|
||||||
m.Log(m.Cap("status", "close"), "%d server %v", m.root.Capi("nserver", -1), arg)
|
|
||||||
for _, msg := range c.sessions {
|
|
||||||
if msg.Cap("status") != "close" {
|
|
||||||
msg.target.Close(msg, arg...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.context != nil {
|
|
||||||
m.Log("close", "%d context %v", m.root.Capi("ncontext", -1), arg)
|
|
||||||
delete(c.context.contexts, c.Name)
|
|
||||||
c.exit <- true
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) TryCatch(msg *Message, safe bool, hand ...func(msg *Message)) *Message {
|
|
||||||
defer func() {
|
|
||||||
switch e := recover(); e {
|
|
||||||
case io.EOF:
|
|
||||||
case nil:
|
|
||||||
default:
|
|
||||||
m.Log("bench", "chain: %s", msg.Format("chain"))
|
|
||||||
m.Log("bench", "catch: %s", e)
|
|
||||||
m.Log("bench", "stack: %s", msg.Format("stack"))
|
|
||||||
|
|
||||||
if m.Log("error", "catch: %s", e); len(hand) > 1 {
|
|
||||||
m.TryCatch(msg, safe, hand[1:]...)
|
|
||||||
} else if !safe {
|
|
||||||
m.Assert(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if len(hand) > 0 {
|
|
||||||
hand[0](msg)
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func (m *Message) Assert(e interface{}, msg ...string) bool {
|
|
||||||
switch v := e.(type) {
|
|
||||||
case nil:
|
|
||||||
return true
|
|
||||||
case *Message:
|
|
||||||
if v.Result(0) != "error: " {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
e = errors.New(strings.Join(v.Meta["result"], ""))
|
|
||||||
default:
|
|
||||||
if kit.Right(v) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch e.(type) {
|
|
||||||
case error:
|
|
||||||
default:
|
|
||||||
e = errors.New(kit.Format(msg))
|
|
||||||
}
|
|
||||||
|
|
||||||
kit.Log("error", "%v", e)
|
|
||||||
panic(e)
|
|
||||||
}
|
|
||||||
func (m *Message) GoLoop(msg *Message, hand ...func(msg *Message)) *Message {
|
|
||||||
m.Gos(msg, func(msg *Message) {
|
|
||||||
for {
|
|
||||||
hand[0](msg)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func (m *Message) Gos(msg *Message, hand ...func(msg *Message)) *Message {
|
|
||||||
go func() {
|
|
||||||
msg.Option("ctx.routine", m.Capi("ngo", 1))
|
|
||||||
m.TryCatch(msg, true, hand...)
|
|
||||||
}()
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) Spawn(arg ...interface{}) *Message {
|
|
||||||
temp := false
|
|
||||||
c := m.target
|
|
||||||
for i := 0; i < len(arg); i++ {
|
|
||||||
switch v := arg[i].(type) {
|
|
||||||
case *Context:
|
|
||||||
c = v
|
|
||||||
case *Message:
|
|
||||||
c = v.target
|
|
||||||
case string:
|
|
||||||
temp = kit.Right(v)
|
|
||||||
case bool:
|
|
||||||
temp = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
msg := &Message{
|
|
||||||
time: time.Now(),
|
|
||||||
code: -1,
|
|
||||||
source: m.target,
|
|
||||||
target: c,
|
|
||||||
message: m,
|
|
||||||
root: m.root,
|
|
||||||
}
|
|
||||||
|
|
||||||
if temp {
|
|
||||||
return msg
|
|
||||||
}
|
|
||||||
|
|
||||||
msg.code = m.Capi("nmessage", 1)
|
|
||||||
m.messages = append(m.messages, msg)
|
|
||||||
return msg
|
|
||||||
}
|
|
||||||
func (m *Message) Sess(key string, arg ...interface{}) *Message {
|
|
||||||
if key == "" {
|
|
||||||
return m.Spawn()
|
|
||||||
}
|
|
||||||
|
|
||||||
spawn := true
|
|
||||||
if len(arg) > 0 {
|
|
||||||
switch v := arg[0].(type) {
|
|
||||||
case bool:
|
|
||||||
spawn, arg = v, arg[1:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(arg) > 0 {
|
|
||||||
if m.Sessions == nil {
|
|
||||||
m.Sessions = make(map[string]*Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch value := arg[0].(type) {
|
|
||||||
case *Message:
|
|
||||||
m.Sessions[key] = value
|
|
||||||
return m.Sessions[key]
|
|
||||||
case *Context:
|
|
||||||
m.Sessions[key] = m.Spawn(value)
|
|
||||||
return m.Sessions[key]
|
|
||||||
case string:
|
|
||||||
root := len(arg) < 3 || kit.Right(arg[2])
|
|
||||||
|
|
||||||
method := "find"
|
|
||||||
if len(arg) > 1 {
|
|
||||||
method = kit.Format(arg[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
switch method {
|
|
||||||
case "find":
|
|
||||||
m.Sessions[key] = m.Find(value, root)
|
|
||||||
case "search":
|
|
||||||
m.Sessions[key] = m.Search(value, root)[0]
|
|
||||||
}
|
|
||||||
return m.Sessions[key]
|
|
||||||
case nil:
|
|
||||||
delete(m.Sessions, key)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
temp := false
|
|
||||||
if len(arg) > 0 {
|
|
||||||
switch v := arg[0].(type) {
|
|
||||||
case bool:
|
|
||||||
temp, arg = v, arg[1:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for msg := m; msg != nil; msg = msg.message {
|
|
||||||
if x, ok := msg.Sessions[key]; ok {
|
|
||||||
if spawn {
|
|
||||||
x = m.Spawn(x.target, temp)
|
|
||||||
x.callback = func(sub *Message) *Message { return sub }
|
|
||||||
}
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (m *Message) Form(x *Command, arg []string) []string {
|
|
||||||
form, ok := m.Optionv("ctx.form").(map[string]int)
|
|
||||||
if !ok {
|
|
||||||
return arg
|
|
||||||
}
|
|
||||||
for _, form := range []map[string]int{form, x.Form} {
|
|
||||||
|
|
||||||
if args := []string{}; form != nil {
|
|
||||||
for i := 0; i < len(arg); i++ {
|
|
||||||
if n, ok := form[arg[i]]; ok {
|
|
||||||
if n < 0 {
|
|
||||||
n += len(arg) - i
|
|
||||||
}
|
|
||||||
for j := i + 1; j <= i+n && j < len(arg); j++ {
|
|
||||||
if _, ok := form[arg[j]]; ok {
|
|
||||||
n = j - i - 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if i+1+n > len(arg) {
|
|
||||||
m.Add("option", arg[i], arg[i+1:])
|
|
||||||
} else {
|
|
||||||
m.Add("option", arg[i], arg[i+1:i+1+n])
|
|
||||||
}
|
|
||||||
i += n
|
|
||||||
} else {
|
|
||||||
args = append(args, arg[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
arg = args
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return arg
|
|
||||||
}
|
|
||||||
func (m *Message) Call(cb func(msg *Message) (sub *Message), arg ...interface{}) *Message {
|
|
||||||
if m == nil {
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
if m.callback = cb; len(arg) > 0 && kit.Format(arg[0]) == "skip" {
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
if len(arg) > 0 || len(m.Meta["detail"]) > 0 {
|
|
||||||
m.Log("call", m.Format("detail", "option"))
|
|
||||||
m.Cmd(arg...)
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func (m *Message) Back(ms ...*Message) *Message {
|
|
||||||
if m.callback == nil {
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(ms) == 0 {
|
|
||||||
ms = append(ms, m.Spawn(m.source).Copy(m, "append").Copy(m, "result"))
|
|
||||||
}
|
|
||||||
|
|
||||||
ns := []*Message{}
|
|
||||||
|
|
||||||
for _, msg := range ms {
|
|
||||||
if msg.Hand {
|
|
||||||
m.Log("back", msg.Format("ship", "result", "append"))
|
|
||||||
} else {
|
|
||||||
m.Log("back", msg.Format("ship", "detail", "option"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if sub := m.callback(msg); sub != nil && m.message != nil && m.message != m {
|
|
||||||
ns = append(ns, sub)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(ns) > 0 {
|
|
||||||
m.message.Back(ns...)
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func (m *Message) CallBack(sync bool, cb func(msg *Message) (sub *Message), arg ...interface{}) *Message {
|
|
||||||
if !sync {
|
|
||||||
return m.Call(cb, arg...)
|
|
||||||
}
|
|
||||||
|
|
||||||
wait := make(chan *Message, 10)
|
|
||||||
m.Call(func(sub *Message) *Message {
|
|
||||||
msg := cb(sub)
|
|
||||||
wait <- m
|
|
||||||
return msg
|
|
||||||
}, arg...)
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-time.After(kit.Duration(m.Confx("call_timeout"))):
|
|
||||||
m.Log("sync", m.Format("timeout", "detail", "option"))
|
|
||||||
m.Echo("time out %v", m.Confx("call_timeout"))
|
|
||||||
case <-wait:
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func (m *Message) Free(cbs ...func(msg *Message) (done bool)) *Message {
|
|
||||||
if len(cbs) == 0 {
|
|
||||||
for i := len(m.freeback) - 1; i >= 0; i-- {
|
|
||||||
m.Log("free", "%d/%d", i, len(m.freeback)-1)
|
|
||||||
if !m.freeback[i](m) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
m.freeback = m.freeback[:i]
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
m.freeback = append(m.freeback, cbs...)
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) Match(key string, spawn bool, hand func(m *Message, s *Context, c *Context, key string) bool) *Message {
|
|
||||||
if m == nil {
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
context := []*Context{m.target}
|
|
||||||
for _, v := range kit.Trans(m.Optionv("ctx.chain")) {
|
|
||||||
if msg := m.Sess(v, false); msg != nil && msg.target != nil {
|
|
||||||
if msg.target != m.target && msg.target != m.source {
|
|
||||||
context = append(context, msg.target)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
context = append(context, m.source)
|
|
||||||
|
|
||||||
for _, s := range context {
|
|
||||||
for c := s; c != nil; c = c.context {
|
|
||||||
if hand(m, s, c, key) {
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func (m *Message) Magic(begin string, chain interface{}, args ...interface{}) interface{} {
|
|
||||||
auth := []string{"bench", "session", "user", "role", "componet", "command"}
|
|
||||||
key := []string{"bench", "sessid", "username", "role", "componet", "command"}
|
|
||||||
aaa := m.Sess("aaa", false)
|
|
||||||
for i, v := range auth {
|
|
||||||
if v == begin {
|
|
||||||
h := m.Option(key[i])
|
|
||||||
if v == "user" {
|
|
||||||
h, _ = kit.Hash("username", m.Option("username"))
|
|
||||||
}
|
|
||||||
|
|
||||||
data := aaa.Confv("auth", []string{h, "data"})
|
|
||||||
|
|
||||||
if kit.Format(chain) == "" {
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) > 0 {
|
|
||||||
value := kit.Chain(data, chain, args[0])
|
|
||||||
aaa.Conf("auth", []string{m.Option(key[i]), "data"}, value)
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
value := kit.Chain(data, chain)
|
|
||||||
if value != nil {
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
if i < len(auth)-1 {
|
|
||||||
begin = auth[i+1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (m *Message) Parse(arg interface{}) string {
|
|
||||||
switch str := arg.(type) {
|
|
||||||
case string:
|
|
||||||
if len(str) > 1 && str[0] == '$' {
|
|
||||||
return m.Cap(str[1:])
|
|
||||||
}
|
|
||||||
if len(str) > 1 && str[0] == '@' {
|
|
||||||
if v := m.Option(str[1:]); v != "" {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
if v := kit.Format(m.Magic("bench", str[1:])); v != "" {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
v := m.Conf(str[1:])
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
func (m *Message) Goshy(input []string, index int, stack *kit.Stack, cb func(*Message)) bool {
|
|
||||||
m.Optionv("bio.msg", m)
|
|
||||||
if stack == nil {
|
|
||||||
stack = &kit.Stack{}
|
|
||||||
stack.Push("source", true, 0)
|
|
||||||
}
|
|
||||||
m.Optionv("bio.stack", stack)
|
|
||||||
m.Optionv("bio.input", input)
|
|
||||||
|
|
||||||
for i := index; i < len(input); i++ {
|
|
||||||
line := input[i]
|
|
||||||
m.Optioni("stack.pos", i)
|
|
||||||
|
|
||||||
// 执行语句
|
|
||||||
msg := m.Sess("yac").Cmd("parse", line+"\n")
|
|
||||||
if cb != nil {
|
|
||||||
cb(msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 切换模块
|
|
||||||
if v := msg.Optionv("bio.ctx"); v != nil {
|
|
||||||
m.Optionv("bio.ctx", v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 跳转语句
|
|
||||||
if msg.Appends("bio.pos0") {
|
|
||||||
i = int(msg.Appendi("bio.pos0")) - 1
|
|
||||||
msg.Append("bio.pos0", "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 结束脚本
|
|
||||||
if msg.Appends("bio.end") {
|
|
||||||
m.Copy(msg, "append").Copy(msg, "result")
|
|
||||||
msg.Appends("bio.end", "")
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,686 +0,0 @@
|
|||||||
package ctx
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/csv"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
|
||||||
"runtime"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
"toolkit"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (m *Message) Log(action string, str string, arg ...interface{}) *Message {
|
|
||||||
if action == "error" {
|
|
||||||
kit.Log("error", fmt.Sprintf("chain: %s", m.Format("chain")))
|
|
||||||
kit.Log("error", fmt.Sprintf("%s %s %s", m.Format(), action, fmt.Sprintf(str, arg...)))
|
|
||||||
kit.Log("error", fmt.Sprintf("stack: %s", m.Format("stack")))
|
|
||||||
}
|
|
||||||
|
|
||||||
// if m.Options("log.disable") {
|
|
||||||
// return m
|
|
||||||
// }
|
|
||||||
|
|
||||||
if l := m.Sess("log", false); l != nil {
|
|
||||||
if log, ok := l.target.Server.(LOGGER); ok {
|
|
||||||
if action == "error" {
|
|
||||||
log.Log(m, "error", "chain: %s", m.Format("chain"))
|
|
||||||
}
|
|
||||||
if log.Log(m, action, str, arg...); action == "error" {
|
|
||||||
log.Log(m, "error", "stack: %s", m.Format("stack"))
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(os.Stderr, str, arg...)
|
|
||||||
}
|
|
||||||
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func (m *Message) Gdb(arg ...interface{}) interface{} {
|
|
||||||
// if !m.Options("log.enable") {
|
|
||||||
// return ""
|
|
||||||
// }
|
|
||||||
|
|
||||||
if g := m.Sess("gdb", false); g != nil {
|
|
||||||
if gdb, ok := g.target.Server.(DEBUG); ok {
|
|
||||||
return gdb.Wait(m, arg...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
func (m *Message) Show(str string, args ...interface{}) *Message {
|
|
||||||
res := fmt.Sprintf(str, args...)
|
|
||||||
|
|
||||||
if m.Option("bio.modal") == "action" {
|
|
||||||
fmt.Fprintf(os.Stderr, res)
|
|
||||||
} else if kit.STDIO != nil {
|
|
||||||
kit.STDIO.Show(res)
|
|
||||||
} else {
|
|
||||||
m.Log("info", "show: %v", res)
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func (m *Message) Format(arg ...interface{}) string {
|
|
||||||
if len(arg) == 0 {
|
|
||||||
arg = append(arg, "time", "ship")
|
|
||||||
}
|
|
||||||
|
|
||||||
meta := []string{}
|
|
||||||
for _, v := range arg {
|
|
||||||
switch kit.Format(v) {
|
|
||||||
case "cost":
|
|
||||||
meta = append(meta, kit.FmtTime(time.Now().Sub(m.time).Nanoseconds()))
|
|
||||||
|
|
||||||
case "summary":
|
|
||||||
msg := arg[1].(*Message)
|
|
||||||
ms := make([]*Message, 0, 1024)
|
|
||||||
ms = append(ms, msg.message, msg)
|
|
||||||
|
|
||||||
for i := 0; i < len(ms); i++ {
|
|
||||||
msg := ms[i]
|
|
||||||
if m.Add("append", "index", i); msg == nil {
|
|
||||||
m.Add("append", "message", "")
|
|
||||||
m.Add("append", "time", "")
|
|
||||||
m.Add("append", "code", "")
|
|
||||||
m.Add("append", "source", "")
|
|
||||||
m.Add("append", "target", "")
|
|
||||||
m.Add("append", "details", "")
|
|
||||||
m.Add("append", "options", "")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if msg.message != nil {
|
|
||||||
m.Add("append", "message", msg.message.code)
|
|
||||||
} else {
|
|
||||||
m.Add("append", "message", "")
|
|
||||||
}
|
|
||||||
m.Add("append", "time", msg.time.Format("15:04:05"))
|
|
||||||
m.Add("append", "code", msg.code)
|
|
||||||
m.Add("append", "source", msg.source.Name)
|
|
||||||
m.Add("append", "target", msg.target.Name)
|
|
||||||
m.Add("append", "details", fmt.Sprintf("%v", msg.Meta["detail"]))
|
|
||||||
m.Add("append", "options", fmt.Sprintf("%v", msg.Meta["option"]))
|
|
||||||
|
|
||||||
if i == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(ms) < 30 && len(arg) > 2 && arg[2] == "deep" {
|
|
||||||
ms = append(ms, ms[i].messages...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Table()
|
|
||||||
case "time":
|
|
||||||
meta = append(meta, m.Time())
|
|
||||||
case "mill":
|
|
||||||
meta = append(meta, fmt.Sprintf("%d", int64(m.time.UnixNano())/1000%1000000))
|
|
||||||
case "code":
|
|
||||||
meta = append(meta, kit.Format(m.code))
|
|
||||||
case "ship":
|
|
||||||
meta = append(meta, fmt.Sprintf("%s:%d(%s->%s)", m.Option("ctx.routine"), m.code, m.source.Name, m.target.Name))
|
|
||||||
case "source":
|
|
||||||
target := m.target
|
|
||||||
m.target = m.source
|
|
||||||
meta = append(meta, m.Cap("module"))
|
|
||||||
m.target = target
|
|
||||||
case "target":
|
|
||||||
meta = append(meta, m.Cap("module"))
|
|
||||||
|
|
||||||
case "detail":
|
|
||||||
meta = append(meta, fmt.Sprintf("%v", m.Meta["detail"]))
|
|
||||||
case "option":
|
|
||||||
meta = append(meta, fmt.Sprintf("%v", m.Meta["option"]))
|
|
||||||
case "append":
|
|
||||||
meta = append(meta, fmt.Sprintf("%v", m.Meta["append"]))
|
|
||||||
case "result":
|
|
||||||
meta = append(meta, fmt.Sprintf("%v", m.Meta["result"]))
|
|
||||||
|
|
||||||
case "full":
|
|
||||||
case "chain":
|
|
||||||
ms := []*Message{}
|
|
||||||
if v == "full" {
|
|
||||||
ms = append(ms, m)
|
|
||||||
} else {
|
|
||||||
for msg := m; msg != nil; msg = msg.message {
|
|
||||||
ms = append(ms, msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
meta = append(meta, "\n")
|
|
||||||
for i := len(ms) - 1; i >= 0; i-- {
|
|
||||||
msg := ms[i]
|
|
||||||
|
|
||||||
meta = append(meta, fmt.Sprintf("%s", msg.Format("time", "ship")))
|
|
||||||
if len(msg.Meta["detail"]) > 0 {
|
|
||||||
meta = append(meta, fmt.Sprintf("detail:%d %v", len(msg.Meta["detail"]), msg.Meta["detail"]))
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(msg.Meta["option"]) > 0 {
|
|
||||||
meta = append(meta, fmt.Sprintf("option:%d %v\n", len(msg.Meta["option"]), msg.Meta["option"]))
|
|
||||||
for _, k := range msg.Meta["option"] {
|
|
||||||
if v, ok := msg.Meta[k]; ok {
|
|
||||||
meta = append(meta, fmt.Sprintf(" %s: %d %v\n", k, len(v), v))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
meta = append(meta, "\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(msg.Meta["append"]) > 0 {
|
|
||||||
meta = append(meta, fmt.Sprintf(" append:%d %v\n", len(msg.Meta["append"]), msg.Meta["append"]))
|
|
||||||
for _, k := range msg.Meta["append"] {
|
|
||||||
if v, ok := msg.Meta[k]; ok {
|
|
||||||
meta = append(meta, fmt.Sprintf(" %s: %d %v\n", k, len(v), v))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(msg.Meta["result"]) > 0 {
|
|
||||||
meta = append(meta, fmt.Sprintf(" result:%d %v\n", len(msg.Meta["result"]), msg.Meta["result"]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case "stack":
|
|
||||||
pc := make([]uintptr, 100)
|
|
||||||
pc = pc[:runtime.Callers(5, pc)]
|
|
||||||
frames := runtime.CallersFrames(pc)
|
|
||||||
|
|
||||||
for {
|
|
||||||
frame, more := frames.Next()
|
|
||||||
file := strings.Split(frame.File, "/")
|
|
||||||
name := strings.Split(frame.Function, "/")
|
|
||||||
meta = append(meta, fmt.Sprintf("\n%s:%d\t%s", file[len(file)-1], frame.Line, name[len(name)-1]))
|
|
||||||
if !more {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
meta = append(meta, kit.Format(v))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return strings.Join(meta, " ")
|
|
||||||
}
|
|
||||||
func (m *Message) Short(arg ...string) {
|
|
||||||
for _, k := range arg {
|
|
||||||
if v := m.Option(k); v != "" && len(v) != 32 {
|
|
||||||
m.Option(k, m.Cmdx("aaa.short", v))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func (m *Message) Err(str string, arg ...interface{}) {
|
|
||||||
m.Echo("").Echo("error: ").Echo(str, arg...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) Start(name string, help string, arg ...string) bool {
|
|
||||||
return m.Set("detail", arg).target.Spawn(m, name, help).Begin(m).Start(m)
|
|
||||||
}
|
|
||||||
func (m *Message) Wait() bool {
|
|
||||||
if m.target.exit != nil {
|
|
||||||
return <-m.target.exit
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
func (m *Message) Find(name string, root ...bool) *Message {
|
|
||||||
if name == "" {
|
|
||||||
return m.Spawn()
|
|
||||||
}
|
|
||||||
target := m.target.root
|
|
||||||
if len(root) > 0 && !root[0] {
|
|
||||||
target = m.target
|
|
||||||
}
|
|
||||||
|
|
||||||
cs := target.contexts
|
|
||||||
for _, v := range strings.Split(name, ".") {
|
|
||||||
if x, ok := cs[v]; ok {
|
|
||||||
target, cs = x, x.contexts
|
|
||||||
} else if target.Name == v {
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(root) > 1 && root[1] {
|
|
||||||
m.target = target
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.Spawn(target)
|
|
||||||
}
|
|
||||||
func (m *Message) Search(key string, root ...bool) []*Message {
|
|
||||||
reg, e := regexp.Compile(key)
|
|
||||||
m.Assert(e)
|
|
||||||
|
|
||||||
target := m.target
|
|
||||||
if target == nil {
|
|
||||||
return []*Message{nil}
|
|
||||||
}
|
|
||||||
if len(root) > 0 && root[0] {
|
|
||||||
target = m.target.root
|
|
||||||
}
|
|
||||||
|
|
||||||
cs := make([]*Context, 0, 3)
|
|
||||||
target.Travel(m, func(m *Message, i int) bool {
|
|
||||||
if reg.MatchString(m.target.Name) || reg.FindString(m.target.Help) != "" {
|
|
||||||
cs = append(cs, m.target)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
|
|
||||||
ms := make([]*Message, len(cs))
|
|
||||||
for i := 0; i < len(cs); i++ {
|
|
||||||
ms[i] = m.Spawn(cs[i])
|
|
||||||
}
|
|
||||||
if len(ms) == 0 {
|
|
||||||
ms = append(ms, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
func (c *Context) Travel(m *Message, hand func(m *Message, n int) (stop bool)) *Context {
|
|
||||||
if c == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
target := m.target
|
|
||||||
|
|
||||||
cs := []*Context{c}
|
|
||||||
for i := 0; i < len(cs); i++ {
|
|
||||||
if m.target = cs[i]; hand(m, i) {
|
|
||||||
return cs[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
keys := []string{}
|
|
||||||
for k, _ := range cs[i].contexts {
|
|
||||||
keys = append(keys, k)
|
|
||||||
}
|
|
||||||
sort.Strings(keys)
|
|
||||||
for _, k := range keys {
|
|
||||||
cs = append(cs, cs[i].contexts[k])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m.target = target
|
|
||||||
return target
|
|
||||||
}
|
|
||||||
func (c *Context) BackTrace(m *Message, hand func(m *Message) (stop bool)) *Context {
|
|
||||||
target := m.target
|
|
||||||
|
|
||||||
for s := m.target; s != nil; s = s.context {
|
|
||||||
if m.target = s; hand(m) {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m.target = target
|
|
||||||
return target
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) Add(meta string, key string, value ...interface{}) *Message {
|
|
||||||
if m.Meta == nil {
|
|
||||||
m.Meta = make(map[string][]string)
|
|
||||||
}
|
|
||||||
if _, ok := m.Meta[meta]; !ok {
|
|
||||||
m.Meta[meta] = make([]string, 0, 3)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch meta {
|
|
||||||
case "detail", "result":
|
|
||||||
m.Meta[meta] = append(m.Meta[meta], key)
|
|
||||||
m.Meta[meta] = append(m.Meta[meta], kit.Trans(value...)...)
|
|
||||||
|
|
||||||
case "option", "append":
|
|
||||||
if _, ok := m.Meta[key]; !ok {
|
|
||||||
m.Meta[key] = make([]string, 0, 3)
|
|
||||||
}
|
|
||||||
m.Meta[key] = append(m.Meta[key], kit.Trans(value...)...)
|
|
||||||
|
|
||||||
for _, v := range m.Meta[meta] {
|
|
||||||
if v == key {
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Meta[meta] = append(m.Meta[meta], key)
|
|
||||||
|
|
||||||
default:
|
|
||||||
m.Log("error", "add meta error %s %s %v", meta, key, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func (m *Message) Set(meta string, arg ...interface{}) *Message {
|
|
||||||
switch meta {
|
|
||||||
case "detail", "result":
|
|
||||||
if m != nil && m.Meta != nil {
|
|
||||||
delete(m.Meta, meta)
|
|
||||||
}
|
|
||||||
case "option", "append":
|
|
||||||
if len(arg) > 0 {
|
|
||||||
for _, k := range arg {
|
|
||||||
delete(m.Data, kit.Format(k))
|
|
||||||
delete(m.Meta, kit.Format(k))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for _, k := range m.Meta[meta] {
|
|
||||||
delete(m.Data, k)
|
|
||||||
delete(m.Meta, k)
|
|
||||||
}
|
|
||||||
delete(m.Meta, meta)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
m.Log("error", "set meta error %s %s %v", meta, arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
if args := kit.Trans(arg...); len(args) > 0 {
|
|
||||||
m.Add(meta, args[0], args[1:])
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func (m *Message) Put(meta string, key string, value interface{}) *Message {
|
|
||||||
switch meta {
|
|
||||||
case "option", "append":
|
|
||||||
if m.Set(meta, key); m.Data == nil {
|
|
||||||
m.Data = make(map[string]interface{})
|
|
||||||
}
|
|
||||||
m.Data[key] = value
|
|
||||||
|
|
||||||
default:
|
|
||||||
m.Log("error", "put data error %s %s %v", meta, key, value)
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func (m *Message) Get(key string, arg ...interface{}) string {
|
|
||||||
if meta, ok := m.Meta[key]; ok && len(meta) > 0 {
|
|
||||||
index := 0
|
|
||||||
if len(arg) > 0 {
|
|
||||||
index = kit.Int(arg[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
index = (index+2)%(len(meta)+2) - 2
|
|
||||||
if index >= 0 && index < len(meta) {
|
|
||||||
return meta[index]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
func (m *Message) Has(key ...string) bool {
|
|
||||||
switch len(key) {
|
|
||||||
case 1:
|
|
||||||
if _, ok := m.Data[key[0]]; ok {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if _, ok := m.Meta[key[0]]; ok {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
func (m *Message) CopyTo(msg *Message, arg ...string) *Message {
|
|
||||||
msg.Copy(m, "append").Copy(m, "result")
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func (m *Message) CopyFuck(msg *Message, arg ...string) *Message {
|
|
||||||
if m == msg {
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < len(arg); i++ {
|
|
||||||
meta := arg[i]
|
|
||||||
|
|
||||||
switch meta {
|
|
||||||
case "target":
|
|
||||||
m.target = msg.target
|
|
||||||
case "callback":
|
|
||||||
m.callback = msg.callback
|
|
||||||
case "detail", "result":
|
|
||||||
if len(msg.Meta[meta]) > 0 {
|
|
||||||
m.Add(meta, msg.Meta[meta][0], msg.Meta[meta][1:])
|
|
||||||
}
|
|
||||||
case "option", "append":
|
|
||||||
if msg.Meta == nil {
|
|
||||||
msg.Meta = map[string][]string{}
|
|
||||||
}
|
|
||||||
if msg.Meta[meta] == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if i == len(arg)-1 {
|
|
||||||
arg = append(arg, msg.Meta[meta]...)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i++; i < len(arg); i++ {
|
|
||||||
if v, ok := msg.Data[arg[i]]; ok {
|
|
||||||
m.Put(meta, arg[i], v)
|
|
||||||
} else if v, ok := msg.Meta[arg[i]]; ok {
|
|
||||||
m.Add(meta, arg[i], v) // TODO fuck Add
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
if msg.Hand {
|
|
||||||
meta = "append"
|
|
||||||
} else {
|
|
||||||
meta = "option"
|
|
||||||
}
|
|
||||||
|
|
||||||
if v, ok := msg.Data[arg[i]]; ok {
|
|
||||||
m.Put(meta, arg[i], v)
|
|
||||||
}
|
|
||||||
if v, ok := msg.Meta[arg[i]]; ok {
|
|
||||||
m.Add(meta, arg[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func (m *Message) ToHTML(style string) string {
|
|
||||||
cmd := strings.Join(m.Meta["detail"], " ")
|
|
||||||
result := []string{}
|
|
||||||
if len(m.Meta["append"]) > 0 {
|
|
||||||
result = append(result, fmt.Sprintf("<table class='%s'>", style))
|
|
||||||
result = append(result, "<caption>", cmd, "</caption>")
|
|
||||||
m.Table(func(line int, maps map[string]string) {
|
|
||||||
if line == 0 {
|
|
||||||
result = append(result, "<tr>")
|
|
||||||
for _, v := range m.Meta["append"] {
|
|
||||||
result = append(result, "<th>", v, "</th>")
|
|
||||||
}
|
|
||||||
result = append(result, "</tr>")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
result = append(result, "<tr>")
|
|
||||||
for _, k := range m.Meta["append"] {
|
|
||||||
result = append(result, "<td>", maps[k], "</td>")
|
|
||||||
}
|
|
||||||
result = append(result, "</tr>")
|
|
||||||
})
|
|
||||||
result = append(result, "</table>")
|
|
||||||
} else {
|
|
||||||
result = append(result, "<pre><code>")
|
|
||||||
result = append(result, fmt.Sprintf("%s", m.Find("shy", false).Conf("prompt")), cmd, "\n")
|
|
||||||
result = append(result, m.Meta["result"]...)
|
|
||||||
result = append(result, "</code></pre>")
|
|
||||||
}
|
|
||||||
return strings.Join(result, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) Grow(key string, args interface{}, data interface{}) interface{} {
|
|
||||||
cache := m.Confm(key, args)
|
|
||||||
if args == nil {
|
|
||||||
cache = m.Confm(key)
|
|
||||||
}
|
|
||||||
if cache == nil {
|
|
||||||
cache = map[string]interface{}{}
|
|
||||||
}
|
|
||||||
meta, ok := cache["meta"].(map[string]interface{})
|
|
||||||
if !ok {
|
|
||||||
meta = map[string]interface{}{}
|
|
||||||
}
|
|
||||||
list, _ := cache["list"].([]interface{})
|
|
||||||
|
|
||||||
list = append(list, data)
|
|
||||||
if len(list) > kit.Int(kit.Select(m.Conf("cache", "limit"), meta["limit"])) {
|
|
||||||
offset := kit.Int(meta["offset"])
|
|
||||||
least := kit.Int(kit.Select(m.Conf("cache", "least"), meta["least"]))
|
|
||||||
|
|
||||||
name := kit.Select(m.Option("cache.store"), meta["store"])
|
|
||||||
f, e := os.OpenFile(name, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
|
|
||||||
if e != nil {
|
|
||||||
f, _, e = kit.Create(name)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
s, e := f.Stat()
|
|
||||||
m.Assert(e)
|
|
||||||
|
|
||||||
keys := []string{}
|
|
||||||
w := csv.NewWriter(f)
|
|
||||||
if s.Size() == 0 {
|
|
||||||
for k := range list[0].(map[string]interface{}) {
|
|
||||||
keys = append(keys, k)
|
|
||||||
}
|
|
||||||
sort.Strings(keys)
|
|
||||||
w.Write(keys)
|
|
||||||
w.Flush()
|
|
||||||
s, e = f.Stat()
|
|
||||||
} else {
|
|
||||||
r := csv.NewReader(f)
|
|
||||||
keys, e = r.Read()
|
|
||||||
}
|
|
||||||
|
|
||||||
count := len(list) - least
|
|
||||||
record, _ := meta["record"].([]interface{})
|
|
||||||
meta["record"] = append(record, map[string]interface{}{
|
|
||||||
"time": m.Time(),
|
|
||||||
"offset": offset,
|
|
||||||
"position": s.Size(),
|
|
||||||
"count": count,
|
|
||||||
"file": name,
|
|
||||||
})
|
|
||||||
|
|
||||||
for i, v := range list {
|
|
||||||
if i >= count {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
val := v.(map[string]interface{})
|
|
||||||
|
|
||||||
values := []string{}
|
|
||||||
for _, k := range keys {
|
|
||||||
values = append(values, kit.Format(val[k]))
|
|
||||||
}
|
|
||||||
w.Write(values)
|
|
||||||
|
|
||||||
if i < least {
|
|
||||||
list[i] = list[count+i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Log("info", "save %s offset %v+%v", name, offset, count)
|
|
||||||
meta["offset"] = offset + count
|
|
||||||
list = list[:least]
|
|
||||||
w.Flush()
|
|
||||||
}
|
|
||||||
cache["meta"] = meta
|
|
||||||
cache["list"] = list
|
|
||||||
if args == nil {
|
|
||||||
m.Conf(key, cache)
|
|
||||||
} else {
|
|
||||||
m.Conf(key, args, cache)
|
|
||||||
}
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
func (m *Message) Grows(key string, args interface{}, cb interface{}) map[string]interface{} {
|
|
||||||
cache := m.Confm(key, args)
|
|
||||||
if args == nil {
|
|
||||||
cache = m.Confm(key)
|
|
||||||
}
|
|
||||||
if cache == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
meta, ok := cache["meta"].(map[string]interface{})
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
list, ok := cache["list"].([]interface{})
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
offend := kit.Int(kit.Select("0", m.Option("cache.offend")))
|
|
||||||
limit := kit.Int(kit.Select("10", m.Option("cache.limit")))
|
|
||||||
match := kit.Select("", m.Option("cache.match"))
|
|
||||||
value := kit.Select("", m.Option("cache.value"))
|
|
||||||
current := kit.Int(meta["offset"])
|
|
||||||
end := current + len(list) - offend
|
|
||||||
begin := end - limit
|
|
||||||
|
|
||||||
data := make([]interface{}, 0, limit)
|
|
||||||
m.Log("info", "read %v-%v from %v-%v", begin, end, current, current+len(list))
|
|
||||||
if begin < current {
|
|
||||||
store, _ := meta["record"].([]interface{})
|
|
||||||
for s := len(store) - 1; s > -1; s-- {
|
|
||||||
item, _ := store[s].(map[string]interface{})
|
|
||||||
line := kit.Int(item["offset"])
|
|
||||||
m.Log("info", "check history %v %v %v", s, line, item)
|
|
||||||
if begin < line && s > 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for ; s < len(store); s++ {
|
|
||||||
if begin >= end {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
item, _ := store[s].(map[string]interface{})
|
|
||||||
if line+kit.Int(item["count"]) < begin {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
name := kit.Format(item["file"])
|
|
||||||
pos := kit.Int(item["position"])
|
|
||||||
line := kit.Int(item["offset"])
|
|
||||||
m.Log("info", "load history %v %v %v", s, line, item)
|
|
||||||
if f, e := os.Open(name); m.Assert(e) {
|
|
||||||
defer f.Close()
|
|
||||||
r := csv.NewReader(f)
|
|
||||||
heads, _ := r.Read()
|
|
||||||
m.Log("info", "load head %v", heads)
|
|
||||||
|
|
||||||
f.Seek(int64(pos), os.SEEK_SET)
|
|
||||||
r = csv.NewReader(f)
|
|
||||||
for i := line; i < end; i++ {
|
|
||||||
lines, e := r.Read()
|
|
||||||
if e != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if i >= begin {
|
|
||||||
item := map[string]interface{}{}
|
|
||||||
for i := range heads {
|
|
||||||
item[heads[i]] = lines[i]
|
|
||||||
}
|
|
||||||
m.Log("info", "load line %v %v %v", i, len(data), item)
|
|
||||||
if match == "" || strings.Contains(kit.Format(item[match]), value) {
|
|
||||||
data = append(data, item)
|
|
||||||
}
|
|
||||||
begin = i + 1
|
|
||||||
} else {
|
|
||||||
m.Log("info", "skip line %v", i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if begin < current {
|
|
||||||
begin = current
|
|
||||||
}
|
|
||||||
m.Log("info", "cache %v-%v", begin-current, end-current)
|
|
||||||
for i := begin - current; i < end-current; i++ {
|
|
||||||
if match == "" || strings.Contains(kit.Format(kit.Chain(list[i], match)), value) {
|
|
||||||
data = append(data, list[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return kit.Map(map[string]interface{}{"meta": meta, "list": data}, "", cb)
|
|
||||||
}
|
|
@ -1,879 +0,0 @@
|
|||||||
package ctx
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
_ "github.com/shylinux/icebergs"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
"toolkit"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Cache struct {
|
|
||||||
Value string
|
|
||||||
Name string
|
|
||||||
Help string
|
|
||||||
Hand func(m *Message, x *Cache, arg ...string) string
|
|
||||||
}
|
|
||||||
type Config struct {
|
|
||||||
Value interface{}
|
|
||||||
Name string
|
|
||||||
Help string
|
|
||||||
Hand func(m *Message, x *Config, arg ...string) string
|
|
||||||
}
|
|
||||||
type Command struct {
|
|
||||||
Form map[string]int
|
|
||||||
Name string
|
|
||||||
Help interface{}
|
|
||||||
Auto func(m *Message, c *Context, key string, arg ...string) (ok bool)
|
|
||||||
Hand func(m *Message, c *Context, key string, arg ...string) (e error)
|
|
||||||
}
|
|
||||||
type Context struct {
|
|
||||||
Name string
|
|
||||||
Help string
|
|
||||||
|
|
||||||
Caches map[string]*Cache
|
|
||||||
Configs map[string]*Config
|
|
||||||
Commands map[string]*Command
|
|
||||||
|
|
||||||
message *Message
|
|
||||||
requests []*Message
|
|
||||||
sessions []*Message
|
|
||||||
|
|
||||||
contexts map[string]*Context
|
|
||||||
context *Context
|
|
||||||
root *Context
|
|
||||||
|
|
||||||
exit chan bool
|
|
||||||
Server
|
|
||||||
}
|
|
||||||
type Server interface {
|
|
||||||
Spawn(m *Message, c *Context, arg ...string) Server
|
|
||||||
Begin(m *Message, arg ...string) Server
|
|
||||||
Start(m *Message, arg ...string) bool
|
|
||||||
Close(m *Message, arg ...string) bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Context) Context() *Context {
|
|
||||||
return c.context
|
|
||||||
}
|
|
||||||
func (c *Context) Message() *Message {
|
|
||||||
return c.message
|
|
||||||
}
|
|
||||||
|
|
||||||
type Message struct {
|
|
||||||
time time.Time
|
|
||||||
code int
|
|
||||||
|
|
||||||
source *Context
|
|
||||||
target *Context
|
|
||||||
|
|
||||||
Hand bool
|
|
||||||
Meta map[string][]string
|
|
||||||
Data map[string]interface{}
|
|
||||||
Sync chan bool
|
|
||||||
|
|
||||||
callback func(msg *Message) (sub *Message)
|
|
||||||
freeback []func(msg *Message) (done bool)
|
|
||||||
Sessions map[string]*Message
|
|
||||||
|
|
||||||
messages []*Message
|
|
||||||
message *Message
|
|
||||||
root *Message
|
|
||||||
}
|
|
||||||
type LOGGER interface {
|
|
||||||
Log(*Message, string, string, ...interface{})
|
|
||||||
}
|
|
||||||
type DEBUG interface {
|
|
||||||
Wait(*Message, ...interface{}) interface{}
|
|
||||||
Goon(interface{}, ...interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) Time(arg ...interface{}) string {
|
|
||||||
t := m.time
|
|
||||||
if len(arg) > 0 {
|
|
||||||
if d, e := time.ParseDuration(arg[0].(string)); e == nil {
|
|
||||||
arg, t = arg[1:], t.Add(d)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
str := m.Conf("time", "format")
|
|
||||||
if len(arg) > 1 {
|
|
||||||
str = fmt.Sprintf(arg[0].(string), arg[1:]...)
|
|
||||||
} else if len(arg) > 0 {
|
|
||||||
str = fmt.Sprintf("%v", arg[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
if str == "stamp" {
|
|
||||||
return kit.Format(t.Unix())
|
|
||||||
}
|
|
||||||
return t.Format(str)
|
|
||||||
}
|
|
||||||
func (m *Message) Code() int {
|
|
||||||
return m.code
|
|
||||||
}
|
|
||||||
func (m *Message) Source() *Context {
|
|
||||||
return m.source
|
|
||||||
}
|
|
||||||
func (m *Message) Target() *Context {
|
|
||||||
return m.target
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) Insert(meta string, index int, arg ...interface{}) string {
|
|
||||||
if m == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if m.Meta == nil {
|
|
||||||
m.Meta = make(map[string][]string)
|
|
||||||
}
|
|
||||||
m.Meta[meta] = kit.Array(m.Meta[meta], index, arg)
|
|
||||||
|
|
||||||
if -1 < index && index < len(m.Meta[meta]) {
|
|
||||||
return m.Meta[meta][index]
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
func (m *Message) Detail(arg ...interface{}) string {
|
|
||||||
noset, index := true, 0
|
|
||||||
if len(arg) > 0 {
|
|
||||||
switch v := arg[0].(type) {
|
|
||||||
case int:
|
|
||||||
noset, index, arg = false, v, arg[1:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if noset && len(arg) > 0 {
|
|
||||||
index = -2
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.Insert("detail", index, arg...)
|
|
||||||
}
|
|
||||||
func (m *Message) Option(key string, arg ...interface{}) string {
|
|
||||||
if m == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if len(arg) > 0 {
|
|
||||||
m.Insert(key, 0, arg...)
|
|
||||||
if _, ok := m.Meta[key]; ok {
|
|
||||||
m.Add("option", key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for msg := m; msg != nil; msg = msg.message {
|
|
||||||
if !msg.Has(key) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, k := range msg.Meta["option"] {
|
|
||||||
if k == key {
|
|
||||||
return msg.Get(key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
func (m *Message) Optioni(key string, arg ...interface{}) int {
|
|
||||||
return kit.Int(m.Option(key, arg...))
|
|
||||||
|
|
||||||
}
|
|
||||||
func (m *Message) Options(key string, arg ...interface{}) bool {
|
|
||||||
return kit.Right(m.Option(key, arg...))
|
|
||||||
}
|
|
||||||
func (m *Message) Optionv(key string, arg ...interface{}) interface{} {
|
|
||||||
if len(arg) > 0 {
|
|
||||||
switch arg[0].(type) {
|
|
||||||
case nil:
|
|
||||||
default:
|
|
||||||
m.Put("option", key, arg[0])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for msg := m; msg != nil; msg = msg.message {
|
|
||||||
if msg.Meta == nil || !msg.Has(key) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, k := range msg.Meta["option"] {
|
|
||||||
if k == key {
|
|
||||||
if v, ok := msg.Data[key]; ok {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
return msg.Meta[key]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (m *Message) Append(key string, arg ...interface{}) string {
|
|
||||||
if len(arg) > 0 {
|
|
||||||
m.Insert(key, 0, arg...)
|
|
||||||
if _, ok := m.Meta[key]; ok {
|
|
||||||
m.Add("append", key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ms := []*Message{m}
|
|
||||||
for i := 0; i < len(ms); i++ {
|
|
||||||
ms = append(ms, ms[i].messages...)
|
|
||||||
if !ms[i].Has(key) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, k := range ms[i].Meta["append"] {
|
|
||||||
if k == key {
|
|
||||||
return ms[i].Get(key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
func (m *Message) Appendi(key string, arg ...interface{}) int64 {
|
|
||||||
i, _ := strconv.ParseInt(m.Append(key, arg...), 10, 64)
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
func (m *Message) Appends(key string, arg ...interface{}) bool {
|
|
||||||
return kit.Right(m.Append(key, arg...))
|
|
||||||
}
|
|
||||||
func (m *Message) Result(arg ...interface{}) string {
|
|
||||||
noset, index := true, 0
|
|
||||||
if len(arg) > 0 {
|
|
||||||
switch v := arg[0].(type) {
|
|
||||||
case int:
|
|
||||||
noset, index, arg = false, v, arg[1:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if noset && len(arg) > 0 {
|
|
||||||
index = -2
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.Insert("result", index, arg...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) Push(key interface{}, arg ...interface{}) *Message {
|
|
||||||
keys := []string{}
|
|
||||||
switch key := key.(type) {
|
|
||||||
case string:
|
|
||||||
keys = strings.Split(key, " ")
|
|
||||||
case []string:
|
|
||||||
keys = key
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, key := range keys {
|
|
||||||
switch m.Option("table.format") {
|
|
||||||
case "table":
|
|
||||||
m.Add("append", "key", key)
|
|
||||||
key = "value"
|
|
||||||
}
|
|
||||||
switch value := arg[0].(type) {
|
|
||||||
case map[string]interface{}:
|
|
||||||
m.Add("append", key, kit.Select(" ", kit.Format(kit.Chain(value, key))))
|
|
||||||
default:
|
|
||||||
m.Add("append", key, arg...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func (m *Message) Sort(key string, arg ...string) *Message {
|
|
||||||
cmp := "str"
|
|
||||||
if len(arg) > 0 && arg[0] != "" {
|
|
||||||
cmp = arg[0]
|
|
||||||
} else {
|
|
||||||
cmp = "int"
|
|
||||||
for _, v := range m.Meta[key] {
|
|
||||||
if _, e := strconv.Atoi(v); e != nil {
|
|
||||||
cmp = "str"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
number := map[int]int{}
|
|
||||||
table := []map[string]string{}
|
|
||||||
m.Table(func(index int, line map[string]string) {
|
|
||||||
table = append(table, line)
|
|
||||||
switch cmp {
|
|
||||||
case "int":
|
|
||||||
number[index] = kit.Int(line[key])
|
|
||||||
case "int_r":
|
|
||||||
number[index] = -kit.Int(line[key])
|
|
||||||
case "time":
|
|
||||||
number[index] = kit.Time(line[key])
|
|
||||||
case "time_r":
|
|
||||||
number[index] = -kit.Time(line[key])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
for i := 0; i < len(table)-1; i++ {
|
|
||||||
for j := i + 1; j < len(table); j++ {
|
|
||||||
result := false
|
|
||||||
switch cmp {
|
|
||||||
case "", "str":
|
|
||||||
if table[i][key] > table[j][key] {
|
|
||||||
result = true
|
|
||||||
}
|
|
||||||
case "str_r":
|
|
||||||
if table[i][key] < table[j][key] {
|
|
||||||
result = true
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
if number[i] > number[j] {
|
|
||||||
result = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if result {
|
|
||||||
table[i], table[j] = table[j], table[i]
|
|
||||||
number[i], number[j] = number[j], number[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, k := range m.Meta["append"] {
|
|
||||||
delete(m.Meta, k)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, v := range table {
|
|
||||||
for _, k := range m.Meta["append"] {
|
|
||||||
m.Add("append", k, v[k])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func (m *Message) Split(str string, arg ...string) *Message {
|
|
||||||
c := rune(kit.Select(" ", arg, 0)[0])
|
|
||||||
lines := strings.Split(str, "\n")
|
|
||||||
|
|
||||||
pos := []int{}
|
|
||||||
heads := []string{}
|
|
||||||
if h := kit.Select("", arg, 2); h != "" {
|
|
||||||
heads = strings.Split(h, " ")
|
|
||||||
} else {
|
|
||||||
h, lines = lines[0], lines[1:]
|
|
||||||
v := kit.Trans(m.Optionv("cmd_headers"))
|
|
||||||
for i := 0; i < len(v)-1; i += 2 {
|
|
||||||
h = strings.Replace(h, v[i], v[i+1], 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
heads = kit.Split(h, c, kit.Int(kit.Select("-1", arg, 1)))
|
|
||||||
for _, v := range heads {
|
|
||||||
pos = append(pos, strings.Index(h, v))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, l := range lines {
|
|
||||||
if len(l) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if len(pos) > 0 {
|
|
||||||
for i, v := range pos {
|
|
||||||
if v < len(l) && i == len(pos)-1 {
|
|
||||||
m.Add("append", heads[i], strings.TrimSpace(l[v:]))
|
|
||||||
} else if v < len(l) && i+1 < len(pos) && pos[i+1] < len(l) {
|
|
||||||
m.Add("append", heads[i], strings.TrimSpace(l[v:pos[i+1]]))
|
|
||||||
} else {
|
|
||||||
m.Add("append", heads[i], "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ls := kit.Split(l, c, len(heads))
|
|
||||||
for i, v := range heads {
|
|
||||||
m.Add("append", v, kit.Select("", ls, i))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Table()
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func (m *Message) Limit(offset, limit int) *Message {
|
|
||||||
l := len(m.Meta[m.Meta["append"][0]])
|
|
||||||
if offset < 0 {
|
|
||||||
offset = 0
|
|
||||||
}
|
|
||||||
if offset > l {
|
|
||||||
offset = l
|
|
||||||
}
|
|
||||||
if offset+limit > l {
|
|
||||||
limit = l - offset
|
|
||||||
}
|
|
||||||
for _, k := range m.Meta["append"] {
|
|
||||||
m.Meta[k] = m.Meta[k][offset : offset+limit]
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func (m *Message) Filter(value string) *Message {
|
|
||||||
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func (m *Message) Group(method string, args ...string) *Message {
|
|
||||||
|
|
||||||
nrow := len(m.Meta[m.Meta["append"][0]])
|
|
||||||
|
|
||||||
keys := map[string]bool{}
|
|
||||||
for _, v := range args {
|
|
||||||
keys[v] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
counts := []int{}
|
|
||||||
mis := map[int]bool{}
|
|
||||||
for i := 0; i < nrow; i++ {
|
|
||||||
counts = append(counts, 1)
|
|
||||||
if mis[i] {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
next:
|
|
||||||
for j := i + 1; j < nrow; j++ {
|
|
||||||
if mis[j] {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for key := range keys {
|
|
||||||
if m.Meta[key][i] != m.Meta[key][j] {
|
|
||||||
continue next
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, k := range m.Meta["append"] {
|
|
||||||
if !keys[k] {
|
|
||||||
switch method {
|
|
||||||
case "sum", "avg":
|
|
||||||
v1, e1 := strconv.Atoi(m.Meta[k][i])
|
|
||||||
v2, e2 := strconv.Atoi(m.Meta[k][j])
|
|
||||||
if e1 == nil && e2 == nil {
|
|
||||||
m.Meta[k][i] = fmt.Sprintf("%d", v1+v2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mis[j] = true
|
|
||||||
counts[i]++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < nrow; i++ {
|
|
||||||
for _, k := range m.Meta["append"] {
|
|
||||||
if !keys[k] {
|
|
||||||
switch method {
|
|
||||||
case "avg":
|
|
||||||
if v1, e1 := strconv.Atoi(m.Meta[k][i]); e1 == nil {
|
|
||||||
m.Meta[k][i] = strconv.Itoa(v1 / counts[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i := 0; i < nrow; i++ {
|
|
||||||
m.Push("_counts", counts[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < nrow; i++ {
|
|
||||||
if mis[i] {
|
|
||||||
for j := i + 1; j < nrow; j++ {
|
|
||||||
if !mis[j] {
|
|
||||||
for _, k := range m.Meta["append"] {
|
|
||||||
m.Meta[k][i] = m.Meta[k][j]
|
|
||||||
}
|
|
||||||
mis[i], mis[j] = false, true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if mis[i] {
|
|
||||||
for _, k := range m.Meta["append"] {
|
|
||||||
m.Meta[k] = m.Meta[k][0:i]
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func (m *Message) Table(cbs ...interface{}) *Message {
|
|
||||||
if len(m.Meta["append"]) == 0 {
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
// 遍历函数
|
|
||||||
if len(cbs) > 0 {
|
|
||||||
nrow := len(m.Meta[m.Meta["append"][0]])
|
|
||||||
for i := 0; i < nrow; i++ {
|
|
||||||
line := map[string]string{}
|
|
||||||
for _, k := range m.Meta["append"] {
|
|
||||||
line[k] = kit.Select("", m.Meta[k], i)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch cb := cbs[0].(type) {
|
|
||||||
case func(map[string]string):
|
|
||||||
cb(line)
|
|
||||||
case func(map[string]string) bool:
|
|
||||||
if !cb(line) {
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
case func(int, map[string]string):
|
|
||||||
cb(i, line)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
//计算列宽
|
|
||||||
space := kit.Select(m.Conf("table", "space"), m.Option("table.space"))
|
|
||||||
depth, width := 0, map[string]int{}
|
|
||||||
for _, k := range m.Meta["append"] {
|
|
||||||
if len(m.Meta[k]) > depth {
|
|
||||||
depth = len(m.Meta[k])
|
|
||||||
}
|
|
||||||
width[k] = kit.Width(k, len(space))
|
|
||||||
for _, v := range m.Meta[k] {
|
|
||||||
if kit.Width(v, len(space)) > width[k] {
|
|
||||||
width[k] = kit.Width(v, len(space))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 回调函数
|
|
||||||
rows := kit.Select(m.Conf("table", "row_sep"), m.Option("table.row_sep"))
|
|
||||||
cols := kit.Select(m.Conf("table", "col_sep"), m.Option("table.col_sep"))
|
|
||||||
compact := kit.Right(kit.Select(m.Conf("table", "compact"), m.Option("table.compact")))
|
|
||||||
cb := func(maps map[string]string, lists []string, line int) bool {
|
|
||||||
for i, v := range lists {
|
|
||||||
if k := m.Meta["append"][i]; compact {
|
|
||||||
v = maps[k]
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.Echo(v); i < len(lists)-1 {
|
|
||||||
m.Echo(cols)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Echo(rows)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 输出表头
|
|
||||||
row := map[string]string{}
|
|
||||||
wor := []string{}
|
|
||||||
for _, k := range m.Meta["append"] {
|
|
||||||
row[k], wor = k, append(wor, k+strings.Repeat(space, width[k]-kit.Width(k, len(space))))
|
|
||||||
}
|
|
||||||
if !cb(row, wor, -1) {
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
// 输出数据
|
|
||||||
for i := 0; i < depth; i++ {
|
|
||||||
row := map[string]string{}
|
|
||||||
wor := []string{}
|
|
||||||
for _, k := range m.Meta["append"] {
|
|
||||||
data := ""
|
|
||||||
if i < len(m.Meta[k]) {
|
|
||||||
data = m.Meta[k][i]
|
|
||||||
}
|
|
||||||
|
|
||||||
row[k], wor = data, append(wor, data+strings.Repeat(space, width[k]-kit.Width(data, len(space))))
|
|
||||||
}
|
|
||||||
if !cb(row, wor, i) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func (m *Message) Copy(msg *Message, arg ...string) *Message {
|
|
||||||
if msg == nil || m == msg {
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < len(arg); i++ {
|
|
||||||
meta := arg[i]
|
|
||||||
|
|
||||||
switch meta {
|
|
||||||
case "target":
|
|
||||||
m.target = msg.target
|
|
||||||
case "callback":
|
|
||||||
m.callback = msg.callback
|
|
||||||
case "detail", "result":
|
|
||||||
if len(msg.Meta[meta]) > 0 {
|
|
||||||
m.Add(meta, msg.Meta[meta][0], msg.Meta[meta][1:])
|
|
||||||
}
|
|
||||||
case "option", "append":
|
|
||||||
if msg.Meta == nil {
|
|
||||||
msg.Meta = map[string][]string{}
|
|
||||||
}
|
|
||||||
if msg.Meta[meta] == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if i == len(arg)-1 {
|
|
||||||
arg = append(arg, msg.Meta[meta]...)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i++; i < len(arg); i++ {
|
|
||||||
if v, ok := msg.Data[arg[i]]; ok {
|
|
||||||
m.Put(meta, arg[i], v)
|
|
||||||
} else if v, ok := msg.Meta[arg[i]]; ok {
|
|
||||||
m.Set(meta, arg[i], v) // TODO fuck Add
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
if msg.Hand {
|
|
||||||
meta = "append"
|
|
||||||
} else {
|
|
||||||
meta = "option"
|
|
||||||
}
|
|
||||||
|
|
||||||
if v, ok := msg.Data[arg[i]]; ok {
|
|
||||||
m.Put(meta, arg[i], v)
|
|
||||||
}
|
|
||||||
if v, ok := msg.Meta[arg[i]]; ok {
|
|
||||||
m.Add(meta, arg[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func (m *Message) Echo(str string, arg ...interface{}) *Message {
|
|
||||||
if len(arg) > 0 {
|
|
||||||
return m.Add("result", fmt.Sprintf(str, arg...))
|
|
||||||
}
|
|
||||||
return m.Add("result", str)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) Cmdp(t time.Duration, head []string, prefix []string, suffix [][]string) *Message {
|
|
||||||
if head != nil && len(head) > 0 {
|
|
||||||
m.Show(fmt.Sprintf("[%s]...\n", strings.Join(head, " ")))
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, v := range suffix {
|
|
||||||
m.Show(fmt.Sprintf("%v/%v %v...\n", i+1, len(suffix), v))
|
|
||||||
m.CopyFuck(m.Cmd(prefix, v), "append")
|
|
||||||
time.Sleep(t)
|
|
||||||
}
|
|
||||||
m.Show("\n")
|
|
||||||
m.Table()
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func (m *Message) Cmdy(args ...interface{}) *Message {
|
|
||||||
m.Cmd(args...).CopyTo(m)
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func (m *Message) Cmdx(args ...interface{}) string {
|
|
||||||
msg := m.Cmd(args...)
|
|
||||||
if msg.Result(0) == "error: " {
|
|
||||||
return msg.Result(1)
|
|
||||||
}
|
|
||||||
return msg.Result(0)
|
|
||||||
}
|
|
||||||
func (m *Message) Cmds(args ...interface{}) bool {
|
|
||||||
return kit.Right(m.Cmdx(args...))
|
|
||||||
}
|
|
||||||
func (m *Message) Cmd(args ...interface{}) *Message {
|
|
||||||
if m == nil {
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) > 0 {
|
|
||||||
m.Set("detail", kit.Trans(args...))
|
|
||||||
}
|
|
||||||
key, arg := m.Meta["detail"][0], m.Meta["detail"][1:]
|
|
||||||
if key == "_" {
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
msg := m
|
|
||||||
if strings.Contains(key, ":") {
|
|
||||||
ps := strings.Split(key, ":")
|
|
||||||
if ps[0] == "_" {
|
|
||||||
ps[0], arg = arg[0], arg[1:]
|
|
||||||
}
|
|
||||||
msg, key, arg = m.Sess("ssh"), "_route", append([]string{"sync", ps[0], ps[1]}, arg...)
|
|
||||||
defer func() { m.Copy(msg, "append").Copy(msg, "result") }()
|
|
||||||
m.Hand = true
|
|
||||||
|
|
||||||
} else if strings.Contains(key, ".") {
|
|
||||||
arg := strings.Split(key, ".")
|
|
||||||
if msg, key = m.Sess(arg[0]), arg[1]; len(arg) == 2 && msg != nil {
|
|
||||||
msg.Option("remote_code", "")
|
|
||||||
|
|
||||||
} else if msg, key = m.Find(strings.Join(arg[0:len(arg)-1], "."), true), arg[len(arg)-1]; msg != nil {
|
|
||||||
msg.Option("remote_code", "")
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if msg == nil {
|
|
||||||
return msg
|
|
||||||
}
|
|
||||||
|
|
||||||
msg = msg.Match(key, true, func(msg *Message, s *Context, c *Context, key string) bool {
|
|
||||||
msg.Hand = false
|
|
||||||
if x, ok := c.Commands[key]; ok && x.Hand != nil {
|
|
||||||
msg.TryCatch(msg, true, func(msg *Message) {
|
|
||||||
msg.Log("cmd", "%s %s %v %v", c.Name, key, arg, msg.Meta["option"])
|
|
||||||
msg.Hand = true
|
|
||||||
x.Hand(msg, c, key, msg.Form(x, arg)...)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return msg.Hand
|
|
||||||
})
|
|
||||||
return msg
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) Confm(key string, args ...interface{}) map[string]interface{} {
|
|
||||||
random := ""
|
|
||||||
|
|
||||||
var chain interface{}
|
|
||||||
if len(args) > 0 {
|
|
||||||
switch arg := args[0].(type) {
|
|
||||||
case []interface{}:
|
|
||||||
chain, args = arg, args[1:]
|
|
||||||
case []string:
|
|
||||||
chain, args = arg, args[1:]
|
|
||||||
case string:
|
|
||||||
switch arg {
|
|
||||||
case "%", "*":
|
|
||||||
random, args = arg, args[1:]
|
|
||||||
default:
|
|
||||||
chain, args = arg, args[1:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var v interface{}
|
|
||||||
if chain == nil {
|
|
||||||
v = m.Confv(key)
|
|
||||||
} else {
|
|
||||||
v = m.Confv(key, chain)
|
|
||||||
}
|
|
||||||
return kit.Map(v, random, args...)
|
|
||||||
}
|
|
||||||
func (m *Message) Confx(key string, args ...interface{}) string {
|
|
||||||
value := kit.Select(m.Conf(key), m.Option(key))
|
|
||||||
if len(args) == 0 {
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
switch arg := args[0].(type) {
|
|
||||||
case []string:
|
|
||||||
if len(args) > 1 {
|
|
||||||
value = kit.Select(value, arg, args[1])
|
|
||||||
} else {
|
|
||||||
value = kit.Select(value, arg)
|
|
||||||
}
|
|
||||||
args = args[1:]
|
|
||||||
case map[string]interface{}:
|
|
||||||
value = kit.Select(value, kit.Format(arg[key]))
|
|
||||||
case string:
|
|
||||||
value = kit.Select(value, arg)
|
|
||||||
case nil:
|
|
||||||
default:
|
|
||||||
value = kit.Select(value, args[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
format := "%s"
|
|
||||||
if args = args[1:]; len(args) > 0 {
|
|
||||||
format, args = kit.Format(args[0]), args[1:]
|
|
||||||
}
|
|
||||||
arg := []interface{}{format, value}
|
|
||||||
for _, v := range args {
|
|
||||||
arg = append(arg, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
return kit.Format(arg...)
|
|
||||||
}
|
|
||||||
func (m *Message) Confv(key string, args ...interface{}) interface{} {
|
|
||||||
if strings.Contains(key, ".") {
|
|
||||||
target := m.target
|
|
||||||
defer func() { m.target = target }()
|
|
||||||
|
|
||||||
ps := strings.Split(key, ".")
|
|
||||||
if msg := m.Sess(ps[0], false); msg != nil {
|
|
||||||
m.target, key = msg.target, ps[1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var config *Config
|
|
||||||
m.Match(key, false, func(m *Message, s *Context, c *Context, key string) bool {
|
|
||||||
if x, ok := c.Configs[key]; ok {
|
|
||||||
config = x
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
|
|
||||||
if len(args) == 0 {
|
|
||||||
if config == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return config.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
if config == nil {
|
|
||||||
config = &Config{}
|
|
||||||
m.target.Configs[key] = config
|
|
||||||
}
|
|
||||||
|
|
||||||
switch config.Value.(type) {
|
|
||||||
case string:
|
|
||||||
config.Value = kit.Format(args...)
|
|
||||||
case bool:
|
|
||||||
config.Value = kit.Right(args...)
|
|
||||||
case int:
|
|
||||||
config.Value = kit.Int(args...)
|
|
||||||
case nil:
|
|
||||||
config.Value = args[0]
|
|
||||||
default:
|
|
||||||
for i := 0; i < len(args); i += 2 {
|
|
||||||
if i < len(args)-1 {
|
|
||||||
config.Value = kit.Chain(config.Value, args[i], args[i+1])
|
|
||||||
} else {
|
|
||||||
return kit.Chain(config.Value, args[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return config.Value
|
|
||||||
}
|
|
||||||
func (m *Message) Confs(key string, arg ...interface{}) bool {
|
|
||||||
return kit.Right(m.Confv(key, arg...))
|
|
||||||
}
|
|
||||||
func (m *Message) Confi(key string, arg ...interface{}) int {
|
|
||||||
return kit.Int(m.Confv(key, arg...))
|
|
||||||
}
|
|
||||||
func (m *Message) Conf(key string, args ...interface{}) string {
|
|
||||||
return kit.Format(m.Confv(key, args...))
|
|
||||||
}
|
|
||||||
func (m *Message) Caps(key string, arg ...interface{}) bool {
|
|
||||||
if len(arg) > 0 {
|
|
||||||
return kit.Right(m.Cap(key, arg...))
|
|
||||||
}
|
|
||||||
return kit.Right(m.Cap(key))
|
|
||||||
}
|
|
||||||
func (m *Message) Capi(key string, arg ...interface{}) int {
|
|
||||||
n := kit.Int(m.Cap(key))
|
|
||||||
if len(arg) > 0 {
|
|
||||||
return kit.Int(m.Cap(key, n+kit.Int(arg...)))
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
func (m *Message) Cap(key string, arg ...interface{}) string {
|
|
||||||
var cache *Cache
|
|
||||||
m.Match(key, false, func(m *Message, s *Context, c *Context, key string) bool {
|
|
||||||
if x, ok := c.Caches[key]; ok {
|
|
||||||
cache = x
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
|
|
||||||
if len(arg) == 0 {
|
|
||||||
if cache == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if cache.Hand != nil {
|
|
||||||
return cache.Hand(m, cache)
|
|
||||||
}
|
|
||||||
return cache.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
if cache == nil {
|
|
||||||
cache = &Cache{}
|
|
||||||
m.target.Caches[key] = cache
|
|
||||||
}
|
|
||||||
|
|
||||||
if cache.Hand != nil {
|
|
||||||
cache.Value = cache.Hand(m, cache, kit.Format(arg...))
|
|
||||||
} else {
|
|
||||||
cache.Value = kit.Format(arg...)
|
|
||||||
}
|
|
||||||
return cache.Value
|
|
||||||
}
|
|
@ -1,218 +0,0 @@
|
|||||||
package gdb
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/ctx"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type GDB struct {
|
|
||||||
feed map[string]chan interface{}
|
|
||||||
wait chan interface{}
|
|
||||||
goon chan os.Signal
|
|
||||||
|
|
||||||
*ctx.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gdb *GDB) Value(m *ctx.Message, arg ...interface{}) bool {
|
|
||||||
if value, ok := kit.Chain(gdb.Configs["debug"].Value, kit.Trans(arg, "value")).(map[string]interface{}); ok {
|
|
||||||
if !kit.Right(value["enable"]) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if kit.Right(value["source"]) && kit.Format(value["source"]) != m.Source().Name {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if kit.Right(value["target"]) && kit.Format(value["target"]) != m.Target().Name {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Log("error", "value %v %v", arg, kit.Formats(value))
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
func (gdb *GDB) Wait(msg *ctx.Message, arg ...interface{}) interface{} {
|
|
||||||
m := gdb.Message()
|
|
||||||
if m.Cap("status") != "start" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := len(arg); i > 0; i-- {
|
|
||||||
if gdb.Value(m, arg[:i]...) {
|
|
||||||
if result := kit.Chain(kit.Chain(gdb.Configs["debug"].Value, arg[:i]), []string{"value", "result"}); result != nil {
|
|
||||||
m.Log("error", "done %d %v", len(arg[:i]), arg)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
feed := kit.Select("web", kit.Format(kit.Chain(kit.Chain(gdb.Configs["debug"].Value, arg[:i]), []string{"value", "feed"})))
|
|
||||||
|
|
||||||
c, ok := gdb.feed[feed]
|
|
||||||
if !ok {
|
|
||||||
c = make(chan interface{})
|
|
||||||
gdb.feed[feed] = c
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Log("error", "wait %d %v", len(arg[:i]), arg)
|
|
||||||
result := <-c
|
|
||||||
m.Log("error", "done %d %v %v", len(arg[:i]), arg, result)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (gdb *GDB) Goon(result interface{}, arg ...interface{}) {
|
|
||||||
m := gdb.Message()
|
|
||||||
if m.Cap("status") != "start" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.Log("error", "goon %v %v", arg, result); len(arg) > 0 {
|
|
||||||
if c, ok := gdb.feed[kit.Format(arg[0])]; ok {
|
|
||||||
c <- result
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gdb.wait <- result
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gdb *GDB) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server {
|
|
||||||
return &GDB{Context: c}
|
|
||||||
}
|
|
||||||
func (gdb *GDB) Begin(m *ctx.Message, arg ...string) ctx.Server {
|
|
||||||
return gdb
|
|
||||||
}
|
|
||||||
func (gdb *GDB) Start(m *ctx.Message, arg ...string) bool {
|
|
||||||
m.Cmd("nfs.save", m.Conf("logpid"), os.Getpid())
|
|
||||||
gdb.wait = make(chan interface{}, 10)
|
|
||||||
gdb.goon = make(chan os.Signal, 10)
|
|
||||||
gdb.feed = map[string]chan interface{}{}
|
|
||||||
|
|
||||||
m.Confm("signal", func(sig string, action string) {
|
|
||||||
m.Log("signal", "add %s: %s", action, sig)
|
|
||||||
signal.Notify(gdb.goon, syscall.Signal(kit.Int(sig)))
|
|
||||||
})
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case sig := <-gdb.goon:
|
|
||||||
action := m.Conf("signal", sig)
|
|
||||||
m.Log("signal", "%v: %v", action, sig)
|
|
||||||
|
|
||||||
switch action {
|
|
||||||
case "QUIT", "INT":
|
|
||||||
m.Cmd("cli.quit", 0)
|
|
||||||
case "restart":
|
|
||||||
m.Cmd("cli.quit", 1)
|
|
||||||
case "TERM":
|
|
||||||
m.Cmd("cli.quit", 2)
|
|
||||||
case "upgrade":
|
|
||||||
m.Cmd("cli.upgrade", "bench")
|
|
||||||
m.Cmd("cli.upgrade", "system")
|
|
||||||
case "WINCH":
|
|
||||||
m.Cmd("nfs.term", "init")
|
|
||||||
case "CONT":
|
|
||||||
gdb.wait <- time.Now().Format("2006-01-02 15:04:05")
|
|
||||||
default:
|
|
||||||
// gdb.Goon(nil, "cache", "read", "value")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
func (gdb *GDB) Close(m *ctx.Message, arg ...string) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "gdb", Help: "调试中心",
|
|
||||||
Caches: map[string]*ctx.Cache{},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"logpid": &ctx.Config{Name: "logpid", Value: "var/run/bench.pid", Help: ""},
|
|
||||||
"signal": &ctx.Config{Name: "signal", Value: map[string]interface{}{
|
|
||||||
"2": "INT",
|
|
||||||
"3": "QUIT",
|
|
||||||
"15": "TERM",
|
|
||||||
"28": "WINCH",
|
|
||||||
"30": "restart",
|
|
||||||
"31": "upgrade",
|
|
||||||
"5": "TRAP",
|
|
||||||
|
|
||||||
"1": "HUP",
|
|
||||||
// "9": "KILL",
|
|
||||||
// "10": "BUS",
|
|
||||||
// "11": "SEGV",
|
|
||||||
// "17": "STOP",
|
|
||||||
// "23": "IO",
|
|
||||||
// "29": "INFO",
|
|
||||||
|
|
||||||
"18": "TSTP",
|
|
||||||
"19": "CONT",
|
|
||||||
|
|
||||||
"6": "ABRT",
|
|
||||||
|
|
||||||
"14": "ALRM",
|
|
||||||
"20": "CHLD",
|
|
||||||
"21": "TTIN",
|
|
||||||
"22": "TTOUT",
|
|
||||||
|
|
||||||
"13": "PIPE",
|
|
||||||
"16": "URG",
|
|
||||||
|
|
||||||
"4": "ILL",
|
|
||||||
"7": "EMT",
|
|
||||||
"8": "FPE",
|
|
||||||
"12": "SYS",
|
|
||||||
"24": "XCPU",
|
|
||||||
"25": "XFSZ",
|
|
||||||
"26": "VTALRM",
|
|
||||||
"27": "PROF",
|
|
||||||
}, Help: "信号"},
|
|
||||||
"debug": &ctx.Config{Name: "debug", Value: map[string]interface{}{"value": map[string]interface{}{"enable": false},
|
|
||||||
"trace": map[string]interface{}{"value": map[string]interface{}{"enable": true}},
|
|
||||||
"context": map[string]interface{}{"value": map[string]interface{}{"enable": false},
|
|
||||||
"begin": map[string]interface{}{"value": map[string]interface{}{"enable": false}},
|
|
||||||
"start": map[string]interface{}{"value": map[string]interface{}{"enable": false}},
|
|
||||||
},
|
|
||||||
"command": map[string]interface{}{"value": map[string]interface{}{"enable": false},
|
|
||||||
"shit": map[string]interface{}{"value": map[string]interface{}{"enable": true}},
|
|
||||||
},
|
|
||||||
"config": map[string]interface{}{"value": map[string]interface{}{"enable": true}},
|
|
||||||
"cache": map[string]interface{}{"value": map[string]interface{}{"enable": false},
|
|
||||||
"read": map[string]interface{}{"value": map[string]interface{}{"enable": false},
|
|
||||||
"ncontext": map[string]interface{}{"value": map[string]interface{}{"enable": false}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"web": map[string]interface{}{"value": map[string]interface{}{"enable": true, "feed": "web"}},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"_init": &ctx.Command{Name: "_init", Help: "等待调试", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Target().Start(m)
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"wait": &ctx.Command{Name: "wait arg...", Help: "等待调试", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if gdb, ok := m.Target().Server.(*GDB); m.Assert(ok) {
|
|
||||||
go func() {
|
|
||||||
m.Log("info", "wait %v", arg)
|
|
||||||
m.Log("info", "done %v", gdb.Wait(m, arg))
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"goon": &ctx.Command{Name: "goon arg...", Help: "继续运行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if gdb, ok := m.Target().Server.(*GDB); m.Assert(ok) {
|
|
||||||
gdb.Goon(arg[0], arg[1])
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ctx.Index.Register(Index, &GDB{Context: Index})
|
|
||||||
}
|
|
@ -1,512 +0,0 @@
|
|||||||
package lex
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/ctx"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Seed struct {
|
|
||||||
page int
|
|
||||||
hash int
|
|
||||||
word string
|
|
||||||
}
|
|
||||||
type Point struct {
|
|
||||||
s int
|
|
||||||
c byte
|
|
||||||
}
|
|
||||||
type State struct {
|
|
||||||
star bool
|
|
||||||
next int
|
|
||||||
hash int
|
|
||||||
}
|
|
||||||
|
|
||||||
type LEX struct {
|
|
||||||
seed []*Seed
|
|
||||||
hash map[string]int
|
|
||||||
word map[int]string
|
|
||||||
hand map[int]string
|
|
||||||
page map[string]int
|
|
||||||
|
|
||||||
char map[byte][]byte
|
|
||||||
state map[State]*State
|
|
||||||
mat []map[byte]*State
|
|
||||||
|
|
||||||
*ctx.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lex *LEX) charset(c byte) []byte {
|
|
||||||
if cs, ok := lex.char[c]; ok {
|
|
||||||
return cs
|
|
||||||
}
|
|
||||||
return []byte{c}
|
|
||||||
}
|
|
||||||
func (lex *LEX) index(m *ctx.Message, hash string, h string) int {
|
|
||||||
which, names := lex.hash, lex.word
|
|
||||||
if hash == "npage" {
|
|
||||||
which, names = lex.page, lex.hand
|
|
||||||
}
|
|
||||||
|
|
||||||
if x, e := strconv.Atoi(h); e == nil {
|
|
||||||
if hash == "npage" {
|
|
||||||
m.Assert(x <= m.Capi("npage"), "语法集合未创建")
|
|
||||||
} else {
|
|
||||||
lex.hash[h] = x
|
|
||||||
}
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
if x, ok := which[h]; ok {
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
which[h] = m.Capi(hash, 1)
|
|
||||||
names[which[h]] = h
|
|
||||||
m.Assert(hash != "npage" || m.Capi("npage") < m.Confi("meta", "nlang"), "语法集合超过上限")
|
|
||||||
return which[h]
|
|
||||||
}
|
|
||||||
func (lex *LEX) train(m *ctx.Message, page int, hash int, seed []byte) int {
|
|
||||||
m.Log("debug", "%s %s page: %v hash: %v seed: %v", "train", "lex", page, hash, string(seed))
|
|
||||||
|
|
||||||
ss := []int{page}
|
|
||||||
cn := make([]bool, m.Confi("meta", "ncell"))
|
|
||||||
cc := make([]byte, 0, m.Confi("meta", "ncell"))
|
|
||||||
sn := make([]bool, m.Capi("nline"))
|
|
||||||
|
|
||||||
points := []*Point{}
|
|
||||||
|
|
||||||
for p := 0; p < len(seed); p++ {
|
|
||||||
|
|
||||||
switch seed[p] {
|
|
||||||
case '[':
|
|
||||||
set := true
|
|
||||||
if p++; seed[p] == '^' {
|
|
||||||
set, p = false, p+1
|
|
||||||
}
|
|
||||||
|
|
||||||
for ; seed[p] != ']'; p++ {
|
|
||||||
if seed[p] == '\\' {
|
|
||||||
p++
|
|
||||||
for _, c := range lex.charset(seed[p]) {
|
|
||||||
cn[c] = true
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if seed[p+1] == '-' {
|
|
||||||
begin, end := seed[p], seed[p+2]
|
|
||||||
if begin > end {
|
|
||||||
begin, end = end, begin
|
|
||||||
}
|
|
||||||
for c := begin; c <= end; c++ {
|
|
||||||
cn[c] = true
|
|
||||||
}
|
|
||||||
p += 2
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
cn[seed[p]] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
for c := 0; c < len(cn); c++ {
|
|
||||||
if (set && cn[c]) || (!set && !cn[c]) {
|
|
||||||
cc = append(cc, byte(c))
|
|
||||||
}
|
|
||||||
cn[c] = false
|
|
||||||
}
|
|
||||||
|
|
||||||
case '.':
|
|
||||||
for c := 0; c < len(cn); c++ {
|
|
||||||
cc = append(cc, byte(c))
|
|
||||||
}
|
|
||||||
|
|
||||||
case '\\':
|
|
||||||
p++
|
|
||||||
for _, c := range lex.charset(seed[p]) {
|
|
||||||
cc = append(cc, c)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
cc = append(cc, seed[p])
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Log("debug", "page: \033[31m%d %v\033[0m", len(ss), ss)
|
|
||||||
m.Log("debug", "cell: \033[32m%d %v\033[0m", len(cc), cc)
|
|
||||||
|
|
||||||
flag := '\000'
|
|
||||||
if p+1 < len(seed) {
|
|
||||||
flag = rune(seed[p+1])
|
|
||||||
switch flag {
|
|
||||||
case '+', '*', '?':
|
|
||||||
p++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range ss {
|
|
||||||
line := 0
|
|
||||||
for _, c := range cc {
|
|
||||||
|
|
||||||
state := &State{}
|
|
||||||
if lex.mat[s][c] != nil {
|
|
||||||
*state = *lex.mat[s][c]
|
|
||||||
} else {
|
|
||||||
m.Capi("nnode", 1)
|
|
||||||
}
|
|
||||||
m.Log("debug", "GET(%d,%d): %v", s, c, state)
|
|
||||||
|
|
||||||
switch flag {
|
|
||||||
case '+':
|
|
||||||
state.star = true
|
|
||||||
case '*':
|
|
||||||
state.star = true
|
|
||||||
sn[s] = true
|
|
||||||
case '?':
|
|
||||||
sn[s] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if state.next == 0 {
|
|
||||||
if line == 0 || !m.Confs("meta", "compact") {
|
|
||||||
lex.mat = append(lex.mat, make(map[byte]*State))
|
|
||||||
line = m.Capi("nline", 1) - 1
|
|
||||||
sn = append(sn, false)
|
|
||||||
}
|
|
||||||
state.next = line
|
|
||||||
}
|
|
||||||
sn[state.next] = true
|
|
||||||
|
|
||||||
lex.mat[s][c] = state
|
|
||||||
points = append(points, &Point{s, c})
|
|
||||||
m.Log("debug", "SET(%d,%d): %v(%s,%s)", s, c, state, m.Cap("nnode"), m.Cap("nreal"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cc, ss = cc[:0], ss[:0]
|
|
||||||
for s, b := range sn {
|
|
||||||
if sn[s] = false; b {
|
|
||||||
ss = append(ss, s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range ss {
|
|
||||||
if s < m.Confi("meta", "nlang") || s >= len(lex.mat) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(lex.mat[s]) == 0 {
|
|
||||||
last := m.Capi("nline") - 1
|
|
||||||
m.Cap("nline", "0")
|
|
||||||
m.Log("debug", "DEL: %d-%d", last, m.Capi("nline", s))
|
|
||||||
lex.mat = lex.mat[:s]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range ss {
|
|
||||||
for _, p := range points {
|
|
||||||
state := &State{}
|
|
||||||
*state = *lex.mat[p.s][p.c]
|
|
||||||
|
|
||||||
if state.next == s {
|
|
||||||
m.Log("debug", "GET(%d, %d): %v", p.s, p.c, state)
|
|
||||||
if state.hash = hash; state.next >= len(lex.mat) {
|
|
||||||
state.next = 0
|
|
||||||
}
|
|
||||||
lex.mat[p.s][p.c] = state
|
|
||||||
m.Log("debug", "SET(%d, %d): %v", p.s, p.c, state)
|
|
||||||
}
|
|
||||||
|
|
||||||
if x, ok := lex.state[*state]; !ok {
|
|
||||||
lex.state[*state] = lex.mat[p.s][p.c]
|
|
||||||
m.Capi("nreal", 1)
|
|
||||||
} else {
|
|
||||||
lex.mat[p.s][p.c] = x
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Log("debug", "%s %s npage: %v nhash: %v nseed: %v", "train", "lex", m.Capi("npage"), m.Capi("nhash"), m.Capi("nseed"))
|
|
||||||
return hash
|
|
||||||
}
|
|
||||||
func (lex *LEX) parse(m *ctx.Message, page int, line []byte) (hash int, rest []byte, word []byte) {
|
|
||||||
m.Log("debug", "%s %s page: %v line: %v", "parse", "lex", page, line)
|
|
||||||
|
|
||||||
pos := 0
|
|
||||||
for star, s := 0, page; s != 0 && pos < len(line); pos++ {
|
|
||||||
|
|
||||||
c := line[pos]
|
|
||||||
if c == '\\' && pos < len(line)-1 { //跳过转义
|
|
||||||
pos++
|
|
||||||
c = lex.charset(line[pos])[0]
|
|
||||||
}
|
|
||||||
if c > 127 { //跳过中文
|
|
||||||
word = append(word, c)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
state := lex.mat[s][c]
|
|
||||||
if state == nil {
|
|
||||||
s, star, pos = star, 0, pos-1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
m.Log("debug", "GET (%d,%d): %v", s, c, state)
|
|
||||||
|
|
||||||
word = append(word, c)
|
|
||||||
|
|
||||||
if state.star {
|
|
||||||
star = s
|
|
||||||
} else if x, ok := lex.mat[star][c]; !ok || !x.star {
|
|
||||||
star = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if s, hash = state.next, state.hash; s == 0 {
|
|
||||||
s, star = star, 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if pos == len(line) {
|
|
||||||
// hash, pos, word = -1, 0, word[:0]
|
|
||||||
} else if hash == 0 {
|
|
||||||
pos, word = 0, word[:0]
|
|
||||||
}
|
|
||||||
rest = line[pos:]
|
|
||||||
|
|
||||||
m.Log("debug", "%s %s hash: %v word: %v rest: %v", "parse", "lex", hash, word, rest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
func (lex *LEX) Parse(m *ctx.Message, line []byte, page string) (hash int, rest []byte, word []byte) {
|
|
||||||
hash, rest, word = lex.parse(m, lex.index(m, "npage", page), line)
|
|
||||||
return hash, rest, word
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lex *LEX) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server {
|
|
||||||
return &LEX{Context: c}
|
|
||||||
}
|
|
||||||
func (lex *LEX) Begin(m *ctx.Message, arg ...string) ctx.Server {
|
|
||||||
lex.Caches["nseed"] = &ctx.Cache{Name: "种子数量", Value: "0", Help: "词法模板的数量"}
|
|
||||||
lex.Caches["npage"] = &ctx.Cache{Name: "集合数量", Value: "0", Help: "词法集合的数量"}
|
|
||||||
lex.Caches["nhash"] = &ctx.Cache{Name: "类型数量", Value: "0", Help: "词法类型的数量"}
|
|
||||||
|
|
||||||
lex.Caches["nline"] = &ctx.Cache{Name: "状态数量", Value: m.Conf("meta", "nlang"), Help: "状态机状态的数量"}
|
|
||||||
lex.Caches["nnode"] = &ctx.Cache{Name: "节点数量", Value: "0", Help: "状态机连接的逻辑数量"}
|
|
||||||
lex.Caches["nreal"] = &ctx.Cache{Name: "实点数量", Value: "0", Help: "状态机连接的存储数量"}
|
|
||||||
|
|
||||||
lex.page = map[string]int{"nil": 0}
|
|
||||||
lex.hash = map[string]int{"nil": 0}
|
|
||||||
lex.word = map[int]string{0: "nil"}
|
|
||||||
lex.hand = map[int]string{0: "nil"}
|
|
||||||
|
|
||||||
lex.char = map[byte][]byte{
|
|
||||||
't': []byte{'\t'},
|
|
||||||
'n': []byte{'\n'},
|
|
||||||
'b': []byte{'\t', ' '},
|
|
||||||
's': []byte{'\t', ' ', '\n'},
|
|
||||||
'd': []byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'},
|
|
||||||
'x': []byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F'},
|
|
||||||
}
|
|
||||||
lex.state = make(map[State]*State)
|
|
||||||
lex.mat = make([]map[byte]*State, m.Capi("nline"))
|
|
||||||
|
|
||||||
return lex
|
|
||||||
}
|
|
||||||
func (lex *LEX) Start(m *ctx.Message, arg ...string) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
func (lex *LEX) Close(m *ctx.Message, arg ...string) bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "lex", Help: "词法中心",
|
|
||||||
Caches: map[string]*ctx.Cache{
|
|
||||||
"nmat": &ctx.Cache{Name: "nmat", Value: "0", Help: "矩阵数量"},
|
|
||||||
},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"npage": &ctx.Config{Name: "npage", Value: "1", Help: "默认页"},
|
|
||||||
"nhash": &ctx.Config{Name: "nhash", Value: "1", Help: "默认值"},
|
|
||||||
"meta": &ctx.Config{Name: "meta", Value: map[string]interface{}{
|
|
||||||
"ncell": 128, "nlang": 64, "compact": true,
|
|
||||||
"name": "mat%d", "help": "matrix",
|
|
||||||
}, Help: "初始参数"},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"_init": &ctx.Command{Name: "_init", Help: "默认矩阵", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if _, ok := m.Target().Server.(*LEX); m.Assert(ok) {
|
|
||||||
m.Spawn().Cmd("train", "-?[a-zA-Z_0-9:/.]+", "key", "cmd")
|
|
||||||
m.Spawn().Cmd("train", "\"[^\"]*\"", "str", "cmd")
|
|
||||||
m.Spawn().Cmd("train", "'[^']*'", "str", "cmd")
|
|
||||||
m.Spawn().Cmd("train", "#[^\n]*", "com", "cmd")
|
|
||||||
m.Spawn().Cmd("train", "[~!@$%()]", "ops", "cmd")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"spawn": &ctx.Command{Name: "spawn [help [name]]", Help: "创建矩阵", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if _, ok := m.Target().Server.(*LEX); m.Assert(ok) {
|
|
||||||
m.Start(fmt.Sprintf(kit.Select(m.Conf("lex.meta", "name"), arg, 1), m.Capi("nmat", 1)),
|
|
||||||
kit.Select(m.Conf("lex.meta", "help"), arg, 0))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"train": &ctx.Command{Name: "train seed [hash [page]", Help: "词法训练", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if lex, ok := m.Target().Server.(*LEX); m.Assert(ok) {
|
|
||||||
hash := lex.index(m, "nhash", m.Confx("nhash", arg, 1))
|
|
||||||
page := lex.index(m, "npage", m.Confx("npage", arg, 2))
|
|
||||||
if lex.mat[page] == nil {
|
|
||||||
lex.mat[page] = map[byte]*State{}
|
|
||||||
}
|
|
||||||
m.Result(0, lex.train(m, page, hash, []byte(arg[0])))
|
|
||||||
|
|
||||||
lex.seed = append(lex.seed, &Seed{page, hash, arg[0]})
|
|
||||||
m.Cap("stream", fmt.Sprintf("%s,%s,%s", m.Cap("nseed", len(lex.seed)),
|
|
||||||
m.Cap("npage"), m.Cap("nhash", len(lex.hash)-1)))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"parse": &ctx.Command{Name: "parse line [page]", Help: "词法解析", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if lex, ok := m.Target().Server.(*LEX); m.Assert(ok) {
|
|
||||||
hash, rest, word := lex.parse(m, lex.index(m, "npage", m.Confx("npage", arg, 1)), []byte(arg[0]))
|
|
||||||
m.Result(0, hash, string(rest), string(word))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"split": &ctx.Command{Name: "split line [page]", Help: "词法分隔", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if lex, ok := m.Target().Server.(*LEX); m.Assert(ok) {
|
|
||||||
for input := []byte(arg[0]); len(input) > 0; {
|
|
||||||
hash, rest, word := lex.parse(m, lex.index(m, "npage", m.Confx("npage", arg, 1)), input)
|
|
||||||
m.Log("fuck", "what %v %v %v", hash, rest, word)
|
|
||||||
if hash == 0 || len(word) == 0 || len(rest) == len(input) {
|
|
||||||
if len(input) > 0 {
|
|
||||||
input = input[1:]
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Push("word", string(word))
|
|
||||||
m.Push("hash", lex.word[hash])
|
|
||||||
m.Push("rest", string(rest))
|
|
||||||
input = rest
|
|
||||||
}
|
|
||||||
m.Table()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"show": &ctx.Command{Name: "show seed|page|hash|mat|node", Help: "查看信息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if lex, ok := m.Target().Server.(*LEX); m.Assert(ok) {
|
|
||||||
if len(arg) == 0 {
|
|
||||||
m.Push("seed", len(lex.seed))
|
|
||||||
m.Push("page", len(lex.page))
|
|
||||||
m.Push("hash", len(lex.hash))
|
|
||||||
m.Push("nmat", len(lex.mat))
|
|
||||||
m.Push("node", len(lex.state))
|
|
||||||
m.Table()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch arg[0] {
|
|
||||||
case "seed":
|
|
||||||
for _, v := range lex.seed {
|
|
||||||
m.Push("page", lex.hand[v.page])
|
|
||||||
m.Push("word", strings.Replace(strings.Replace(v.word, "\n", "\\n", -1), "\t", "\\t", -1))
|
|
||||||
m.Push("hash", lex.word[v.hash])
|
|
||||||
}
|
|
||||||
m.Sort("page", "int").Table()
|
|
||||||
|
|
||||||
case "page":
|
|
||||||
for k, v := range lex.page {
|
|
||||||
m.Push("page", k)
|
|
||||||
m.Push("code", v)
|
|
||||||
}
|
|
||||||
m.Sort("code", "int").Table()
|
|
||||||
|
|
||||||
case "hash":
|
|
||||||
for k, v := range lex.hash {
|
|
||||||
m.Push("hash", k)
|
|
||||||
m.Push("code", v)
|
|
||||||
}
|
|
||||||
m.Sort("code", "int").Table()
|
|
||||||
|
|
||||||
case "node":
|
|
||||||
for _, v := range lex.state {
|
|
||||||
m.Push("star", v.star)
|
|
||||||
m.Push("next", v.next)
|
|
||||||
m.Push("hash", v.hash)
|
|
||||||
}
|
|
||||||
m.Table()
|
|
||||||
|
|
||||||
case "mat":
|
|
||||||
for i, v := range lex.mat {
|
|
||||||
if i <= m.Capi("npage") {
|
|
||||||
m.Push("index", lex.hand[i])
|
|
||||||
} else if i < m.Confi("meta", "nlang") {
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
m.Push("index", i)
|
|
||||||
}
|
|
||||||
|
|
||||||
for j := byte(0); j < byte(m.Confi("meta", "ncell")); j++ {
|
|
||||||
c := fmt.Sprintf("%c", j)
|
|
||||||
switch c {
|
|
||||||
case "\n":
|
|
||||||
c = "\\n"
|
|
||||||
case "\t":
|
|
||||||
c = "\\t"
|
|
||||||
case " ":
|
|
||||||
default:
|
|
||||||
if j < 0x20 {
|
|
||||||
c = fmt.Sprintf("\\%x", j)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if s := v[j]; s == nil {
|
|
||||||
m.Push(c, "")
|
|
||||||
} else {
|
|
||||||
star := 0
|
|
||||||
if s.star {
|
|
||||||
star = 1
|
|
||||||
}
|
|
||||||
m.Push(c, fmt.Sprintf("%d,%d,%d", star, s.next, s.hash))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ncol := len(m.Meta["append"])
|
|
||||||
nrow := len(m.Meta[m.Meta["append"][0]])
|
|
||||||
for i := 0; i < ncol-1; i++ {
|
|
||||||
for j := i + 1; j < ncol; j++ {
|
|
||||||
same := true
|
|
||||||
void := true
|
|
||||||
for n := 0; n < nrow; n++ {
|
|
||||||
if m.Meta[m.Meta["append"][i]][n] != "" {
|
|
||||||
void = false
|
|
||||||
}
|
|
||||||
if m.Meta[m.Meta["append"][i]][n] != m.Meta[m.Meta["append"][j]][n] {
|
|
||||||
same = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if same {
|
|
||||||
if !void {
|
|
||||||
key = m.Meta["append"][i] + m.Meta["append"][j]
|
|
||||||
m.Meta[key] = m.Meta[m.Meta["append"][i]]
|
|
||||||
m.Meta["append"][i] = key
|
|
||||||
}
|
|
||||||
for k := j; k < ncol-1; k++ {
|
|
||||||
m.Meta["append"][k] = m.Meta["append"][k+1]
|
|
||||||
}
|
|
||||||
ncol--
|
|
||||||
j--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Meta["append"] = m.Meta["append"][:ncol]
|
|
||||||
m.Table()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ctx.Index.Register(Index, &LEX{Context: Index})
|
|
||||||
}
|
|
@ -1,201 +0,0 @@
|
|||||||
package log
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/ctx"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
)
|
|
||||||
|
|
||||||
type LOG struct {
|
|
||||||
queue chan map[string]interface{}
|
|
||||||
file map[string]*os.File
|
|
||||||
*ctx.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
func (log *LOG) Log(msg *ctx.Message, action string, str string, arg ...interface{}) {
|
|
||||||
if log.queue != nil {
|
|
||||||
log.queue <- map[string]interface{}{"action": action, "str": str, "arg": arg, "msg": msg}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (log *LOG) Value(msg *ctx.Message, arg ...interface{}) []string {
|
|
||||||
args := append(kit.Trans(arg...))
|
|
||||||
|
|
||||||
if value, ok := kit.Chain(log.Configs["output"].Value, args).(map[string]interface{}); ok {
|
|
||||||
if kit.Right(value["source"]) && kit.Format(value["source"]) != msg.Source().Name {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if kit.Right(value["target"]) && kit.Format(value["target"]) != msg.Target().Name {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return kit.Trans(value["value"])
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (log *LOG) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server {
|
|
||||||
return &LOG{Context: c}
|
|
||||||
}
|
|
||||||
func (log *LOG) Begin(m *ctx.Message, arg ...string) ctx.Server {
|
|
||||||
return log
|
|
||||||
}
|
|
||||||
func (log *LOG) Start(m *ctx.Message, arg ...string) bool {
|
|
||||||
// 创建文件
|
|
||||||
log.file = map[string]*os.File{}
|
|
||||||
m.Assert(os.MkdirAll(m.Conf("logdir"), 0770))
|
|
||||||
m.Confm("output", "file", func(key string, value string) {
|
|
||||||
switch value {
|
|
||||||
case "":
|
|
||||||
case "stderr":
|
|
||||||
log.file[key] = os.Stderr
|
|
||||||
case "stdout":
|
|
||||||
log.file[key] = os.Stdout
|
|
||||||
default:
|
|
||||||
if f, e := os.Create(path.Join(m.Conf("logdir"), value)); m.Assert(e) {
|
|
||||||
log.file[key] = f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 创建队列
|
|
||||||
log.queue = make(chan map[string]interface{}, m.Confi("logbuf"))
|
|
||||||
m.Cap("stream", m.Conf("output", []string{"bench", "value", "file"}))
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case l := <-log.queue:
|
|
||||||
m.Capi("nlog", 1)
|
|
||||||
msg := l["msg"].(*ctx.Message)
|
|
||||||
args := kit.Trans(l["arg"].([]interface{})...)
|
|
||||||
|
|
||||||
loop:
|
|
||||||
for _, v := range []string{kit.Format(l["action"]), "bench"} {
|
|
||||||
for i := len(args); i >= 0; i-- {
|
|
||||||
value := log.Value(msg, append([]string{v}, args[:i]...))
|
|
||||||
if !kit.Right(value) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if value[0] == "debug" && !m.Options("log.debug") {
|
|
||||||
break loop
|
|
||||||
}
|
|
||||||
|
|
||||||
// 日志文件
|
|
||||||
file := os.Stderr
|
|
||||||
if f, ok := log.file[value[0]]; ok {
|
|
||||||
file = f
|
|
||||||
} else {
|
|
||||||
break loop
|
|
||||||
}
|
|
||||||
|
|
||||||
// 日志格式
|
|
||||||
font := m.Conf("output", []string{"font", kit.Select("", value, 1)})
|
|
||||||
meta := msg.Format(m.Confv("output", []string{"meta", kit.Select("short", value, 2)}).([]interface{})...)
|
|
||||||
|
|
||||||
str := fmt.Sprintf("%d %s %s%s %s%s", m.Capi("nout", 1), meta, font,
|
|
||||||
kit.Format(l["action"]), fmt.Sprintf(kit.Format(l["str"]), l["arg"].([]interface{})...),
|
|
||||||
kit.Select("", "\033[0m", font != ""))
|
|
||||||
|
|
||||||
// 输出日志
|
|
||||||
if fmt.Fprintln(file, str); m.Confs("output", []string{"stdio", value[0]}) {
|
|
||||||
fmt.Println(str)
|
|
||||||
}
|
|
||||||
break loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
func (log *LOG) Close(m *ctx.Message, arg ...string) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "log", Help: "日志中心",
|
|
||||||
Caches: map[string]*ctx.Cache{
|
|
||||||
"nlog": &ctx.Cache{Name: "nlog", Value: "0", Help: "日志调用数量"},
|
|
||||||
"nout": &ctx.Cache{Name: "nout", Value: "0", Help: "日志输出数量"},
|
|
||||||
},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"logbuf": &ctx.Config{Name: "logbuf", Value: "1024", Help: "日志队列长度"},
|
|
||||||
"logdir": &ctx.Config{Name: "logdir", Value: "var/log", Help: "日志目录"},
|
|
||||||
|
|
||||||
"output": &ctx.Config{Name: "output", Value: map[string]interface{}{
|
|
||||||
"stdio": map[string]interface{}{
|
|
||||||
"bench": false,
|
|
||||||
},
|
|
||||||
"file": map[string]interface{}{
|
|
||||||
"debug": "debug.log",
|
|
||||||
"bench": "bench.log",
|
|
||||||
"right": "right.log",
|
|
||||||
"error": "error.log",
|
|
||||||
},
|
|
||||||
"font": map[string]interface{}{
|
|
||||||
"red": "\033[31m",
|
|
||||||
"green": "\033[32m",
|
|
||||||
"yellow": "\033[33m",
|
|
||||||
},
|
|
||||||
"meta": map[string]interface{}{
|
|
||||||
"short": []interface{}{"time", "ship"},
|
|
||||||
"long": []interface{}{"time", "ship"},
|
|
||||||
"cost": []interface{}{"time", "ship", "mill"},
|
|
||||||
},
|
|
||||||
|
|
||||||
"debug": map[string]interface{}{"value": []interface{}{"debug"}},
|
|
||||||
"search": map[string]interface{}{"value": []interface{}{"debug"}},
|
|
||||||
"call": map[string]interface{}{"value": []interface{}{"debug"}},
|
|
||||||
"back": map[string]interface{}{"value": []interface{}{"debug"}},
|
|
||||||
"send": map[string]interface{}{"value": []interface{}{"debug"}},
|
|
||||||
"recv": map[string]interface{}{"value": []interface{}{"debug"}},
|
|
||||||
|
|
||||||
"bench": map[string]interface{}{"value": []interface{}{"bench"}},
|
|
||||||
"begin": map[string]interface{}{"value": []interface{}{"bench", "red"}},
|
|
||||||
"start": map[string]interface{}{"value": []interface{}{"bench", "red"}},
|
|
||||||
"close": map[string]interface{}{"value": []interface{}{"bench", "red"}},
|
|
||||||
"stack": map[string]interface{}{"value": []interface{}{"bench", "yellow"}},
|
|
||||||
"warn": map[string]interface{}{"value": []interface{}{"bench", "yellow"}},
|
|
||||||
"time": map[string]interface{}{"value": []interface{}{"bench", "red"}},
|
|
||||||
|
|
||||||
"right": map[string]interface{}{"value": []interface{}{"right"}},
|
|
||||||
|
|
||||||
"error": map[string]interface{}{"value": []interface{}{"error", "red"}},
|
|
||||||
"trace": map[string]interface{}{"value": []interface{}{"error", "red"}},
|
|
||||||
|
|
||||||
"cmd": map[string]interface{}{"value": []interface{}{"bench", "green"},
|
|
||||||
"lex": map[string]interface{}{"value": []interface{}{"debug", "green"}},
|
|
||||||
"yac": map[string]interface{}{"value": []interface{}{"debug", "green"}},
|
|
||||||
"cli": map[string]interface{}{
|
|
||||||
"cmd": map[string]interface{}{"value": []interface{}{"debug", "red"}},
|
|
||||||
},
|
|
||||||
"mdb": map[string]interface{}{
|
|
||||||
"note": map[string]interface{}{"value": []interface{}{"debug", "red"}},
|
|
||||||
},
|
|
||||||
"aaa": map[string]interface{}{
|
|
||||||
"auth": map[string]interface{}{"value": []interface{}{"debug", "red"}},
|
|
||||||
"hash": map[string]interface{}{"value": []interface{}{"debug", "red"}},
|
|
||||||
"rsa": map[string]interface{}{"value": []interface{}{"debug", "red"}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, Help: "日志输出配置"},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"_init": &ctx.Command{Name: "_init", Help: "初始化", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Target().Start(m)
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"log": &ctx.Command{Name: "log level string...", Help: "输出日志, level: 日志类型, string: 日志内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if log, ok := m.Target().Server.(*LOG); m.Assert(ok) {
|
|
||||||
log.Log(m, arg[0], arg[1], arg[2:])
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ctx.Index.Register(Index, &LOG{Context: Index})
|
|
||||||
}
|
|
@ -1,803 +0,0 @@
|
|||||||
package mdb
|
|
||||||
|
|
||||||
import (
|
|
||||||
_ "github.com/go-sql-driver/mysql"
|
|
||||||
"github.com/gomodule/redigo/redis"
|
|
||||||
|
|
||||||
"contexts/ctx"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"database/sql"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type MDB struct {
|
|
||||||
conn redis.Conn
|
|
||||||
*sql.DB
|
|
||||||
*ctx.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mdb *MDB) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server {
|
|
||||||
c.Caches = map[string]*ctx.Cache{
|
|
||||||
"database": &ctx.Cache{Name: "database", Value: m.Confx("database", arg, 0), Help: "数据库"},
|
|
||||||
"username": &ctx.Cache{Name: "username", Value: m.Confx("username", arg, 1), Help: "用户名"},
|
|
||||||
"password": &ctx.Cache{Name: "password", Value: m.Confx("password", arg, 2), Help: "密码"},
|
|
||||||
"address": &ctx.Cache{Name: "address", Value: m.Confx("address", arg, 3), Help: "地址"},
|
|
||||||
"protocol": &ctx.Cache{Name: "protocol(tcp)", Value: m.Confx("protocol", arg, 4), Help: "协议"},
|
|
||||||
"driver": &ctx.Cache{Name: "driver(mysql)", Value: m.Confx("driver", arg, 5), Help: "驱动"},
|
|
||||||
"redis": &ctx.Cache{Name: "redis", Value: "", Help: "数据缓存"},
|
|
||||||
}
|
|
||||||
c.Configs = map[string]*ctx.Config{
|
|
||||||
"dbs": &ctx.Config{Name: "dbs", Value: []string{}, Help: "数据库"},
|
|
||||||
"tabs": &ctx.Config{Name: "tabs", Value: []string{}, Help: "关系表"},
|
|
||||||
"limit": &ctx.Config{Name: "limit", Value: "10", Help: "分页"},
|
|
||||||
"offset": &ctx.Config{Name: "offset", Value: "0", Help: "偏移"},
|
|
||||||
}
|
|
||||||
|
|
||||||
return &MDB{Context: c}
|
|
||||||
}
|
|
||||||
func (mdb *MDB) Begin(m *ctx.Message, arg ...string) ctx.Server {
|
|
||||||
return mdb
|
|
||||||
}
|
|
||||||
func (mdb *MDB) Start(m *ctx.Message, arg ...string) bool {
|
|
||||||
if db, e := sql.Open(m.Cap("driver"), fmt.Sprintf("%s:%s@%s(%s)/%s", m.Cap("username"), m.Cap("password"),
|
|
||||||
m.Cap("protocol"), m.Cap("address"), m.Cap("database"))); m.Assert(e) {
|
|
||||||
m.Log("info", "mdb open %s", m.Cap("stream", m.Cap("database")))
|
|
||||||
mdb.DB = db
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
func (mdb *MDB) Close(m *ctx.Message, arg ...string) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
|
|
||||||
Caches: map[string]*ctx.Cache{
|
|
||||||
"nsource": &ctx.Cache{Name: "nsource", Value: "0", Help: "已打开数据库的数量"},
|
|
||||||
},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"database": &ctx.Config{Name: "database", Value: "demo", Help: "默认数据库"},
|
|
||||||
"username": &ctx.Config{Name: "username", Value: "demo", Help: "默认账户"},
|
|
||||||
"password": &ctx.Config{Name: "password", Value: "demo", Help: "默认密码"},
|
|
||||||
"address": &ctx.Config{Name: "address", Value: ":6379", Help: "默认地址"},
|
|
||||||
"protocol": &ctx.Config{Name: "protocol(tcp)", Value: "tcp", Help: "默认协议"},
|
|
||||||
"driver": &ctx.Config{Name: "driver(mysql)", Value: "mysql", Help: "默认驱动"},
|
|
||||||
|
|
||||||
"ktv": &ctx.Config{Name: "ktv", Value: map[string]interface{}{
|
|
||||||
"conf": map[string]interface{}{"expire": "24h"}, "data": map[string]interface{}{},
|
|
||||||
}, Help: "缓存数据"},
|
|
||||||
|
|
||||||
"temp": &ctx.Config{Name: "temp", Value: map[string]interface{}{}, Help: "缓存数据"},
|
|
||||||
"temp_view": &ctx.Config{Name: "temp_view", Value: map[string]interface{}{}, Help: "缓存数据"},
|
|
||||||
"temp_expire": &ctx.Config{Name: "temp_expire(s)", Value: "3000", Help: "缓存数据"},
|
|
||||||
|
|
||||||
"note": &ctx.Config{Name: "note", Value: map[string]interface{}{
|
|
||||||
"faa01a8fc2fc92dae3fbc02ac1b4ec75": map[string]interface{}{
|
|
||||||
"create_time": "1990-07-30 07:08:09", "access_time": "2017-11-01 02:03:04",
|
|
||||||
"type": "index", "name": "shy", "data": "", "ship": map[string]interface{}{
|
|
||||||
"prev": map[string]interface{}{"type": "index", "data": ""},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"81c5709d091eb04bd31ee751c3f81023": map[string]interface{}{
|
|
||||||
"create_time": "1990-07-30 07:08:09", "access_time": "2017-11-01 02:03:04",
|
|
||||||
"meta": []interface{}{"text", "text", "place", "place", "label", "label", "friend", "friend", "username", "username"},
|
|
||||||
"view": map[string]interface{}{
|
|
||||||
"list": map[string]interface{}{"name": "left", "create_date": "right"},
|
|
||||||
"edit": map[string]interface{}{"model": "hidden", "username": "hidden"},
|
|
||||||
},
|
|
||||||
"bind": map[string]interface{}{},
|
|
||||||
"type": "model", "name": "shy", "data": "", "ship": map[string]interface{}{
|
|
||||||
"prev": map[string]interface{}{"type": "model", "data": ""},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, Help: "数据结构"},
|
|
||||||
"note_view": &ctx.Config{Name: "note_view", Value: map[string]interface{}{
|
|
||||||
"default": []interface{}{"key", "create_time", "type", "name", "model", "value"},
|
|
||||||
"base": []interface{}{"key", "create_time", "type", "name", "model", "value"},
|
|
||||||
"full": []interface{}{"key", "create_time", "access_time", "type", "name", "model", "value", "view", "data", "ship"},
|
|
||||||
}, Help: "数据视图"},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"open": &ctx.Command{Name: "open [database [username [password [address [protocol [driver]]]]]]",
|
|
||||||
Help: "打开数据库, database: 数据库名, username: 用户名, password: 密码, address: 服务地址, protocol: 服务协议, driver: 数据库类型",
|
|
||||||
Form: map[string]int{"dbname": 1, "dbhelp": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Start(kit.Select(fmt.Sprintf("db%d", m.Capi("nsource", 1)), m.Option("dbname")),
|
|
||||||
kit.Select("数据源", m.Option("dbhelp")), arg...)
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"exec": &ctx.Command{Name: "exec sql [arg]", Help: "操作数据库, sql: SQL语句, arg: 操作参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if mdb, ok := m.Target().Server.(*MDB); m.Assert(ok) && mdb.DB != nil {
|
|
||||||
which := make([]interface{}, 0, len(arg))
|
|
||||||
for _, v := range arg[1:] {
|
|
||||||
which = append(which, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ret, e := mdb.Exec(arg[0], which...); m.Assert(e) {
|
|
||||||
id, _ := ret.LastInsertId()
|
|
||||||
n, _ := ret.RowsAffected()
|
|
||||||
m.Log("info", "last(%s) nrow(%s)", m.Append("last", id), m.Append("nrow", n))
|
|
||||||
m.Echo("%d", n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"query": &ctx.Command{Name: "query sql [arg]", Help: "查询数据库, sql: SQL语句, arg: 查询参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if mdb, ok := m.Target().Server.(*MDB); m.Assert(ok) && mdb.DB != nil {
|
|
||||||
which := make([]interface{}, 0, len(arg))
|
|
||||||
for _, v := range arg[1:] {
|
|
||||||
which = append(which, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
if rows, e := mdb.Query(arg[0], which...); m.Assert(e) {
|
|
||||||
defer rows.Close()
|
|
||||||
if cols, e := rows.Columns(); m.Assert(e) {
|
|
||||||
num := len(cols)
|
|
||||||
|
|
||||||
for rows.Next() {
|
|
||||||
vals := make([]interface{}, num)
|
|
||||||
ptrs := make([]interface{}, num)
|
|
||||||
for i := range vals {
|
|
||||||
ptrs[i] = &vals[i]
|
|
||||||
}
|
|
||||||
rows.Scan(ptrs...)
|
|
||||||
|
|
||||||
for i, k := range cols {
|
|
||||||
m.Push(k, vals[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(m.Meta["append"]) > 0 {
|
|
||||||
m.Log("info", "rows(%d) cols(%d)", len(m.Meta[m.Meta["append"][0]]), len(m.Meta["append"]))
|
|
||||||
} else {
|
|
||||||
m.Log("info", "rows(0) cols(0)")
|
|
||||||
}
|
|
||||||
m.Table()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"redis": &ctx.Command{Name: "redis [open address]|[cmd...]", Help: "缓存数据库", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if mdb, ok := m.Target().Server.(*MDB); m.Assert(ok) {
|
|
||||||
switch arg[0] {
|
|
||||||
case "open":
|
|
||||||
if mdb.conn, e = redis.Dial("tcp", m.Cap("redis", arg[1]), redis.DialKeepAlive(time.Second*10)); m.Assert(e) {
|
|
||||||
m.Log("info", "redis: %v", arg[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
if mdb.conn == nil || mdb.conn.Err() != nil {
|
|
||||||
if m.Caps("redis") {
|
|
||||||
m.Cmd("mdb.redis", "open", m.Cap("redis"))
|
|
||||||
} else {
|
|
||||||
m.Echo("not open")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
args := []interface{}{}
|
|
||||||
for _, v := range arg[1:] {
|
|
||||||
args = append(args, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
if res, err := mdb.conn.Do(arg[0], args...); m.Assert(err) {
|
|
||||||
switch val := res.(type) {
|
|
||||||
case redis.Error:
|
|
||||||
m.Echo("%v", val)
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
for i, v := range val {
|
|
||||||
m.Add("append", "index", i)
|
|
||||||
m.Add("append", "value", v)
|
|
||||||
}
|
|
||||||
m.Table()
|
|
||||||
|
|
||||||
default:
|
|
||||||
var data interface{}
|
|
||||||
if str := kit.Format(res); json.Unmarshal([]byte(str), &data) == nil {
|
|
||||||
m.Echo(kit.Formats(data))
|
|
||||||
} else {
|
|
||||||
m.Echo(str)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
|
|
||||||
"db": &ctx.Command{Name: "db [which]", Help: "查看或选择数据库", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if len(arg) == 0 {
|
|
||||||
m.Cmdy(".query", "show databases").Table()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Assert(m.Cmdy("exec", fmt.Sprintf("use %s", arg[0])))
|
|
||||||
m.Echo(m.Cap("database", arg[0]))
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"tab": &ctx.Command{Name: "tab [which [field]]", Help: "查看关系表,which: 表名, field: 字段名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
switch len(arg) {
|
|
||||||
case 0:
|
|
||||||
m.Cmdy(".query", "show tables").Table()
|
|
||||||
case 1:
|
|
||||||
m.Cmdy(".query", fmt.Sprintf("desc %s", arg[0])).Table()
|
|
||||||
case 2:
|
|
||||||
m.Cmdy(".query", fmt.Sprintf("desc %s", arg[0])).Cmd("select", "Field", arg[1]).CopyTo(m)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"show": &ctx.Command{Name: "show table fields...", Help: "查询数据, table: 表名, fields: 字段, where: 查询条件, group: 聚合字段, order: 排序字段",
|
|
||||||
Form: map[string]int{"where": 1, "eq": 2, "ne": 2, "in": 2, "like": 2, "begin": 2, "group": 1, "order": 1, "desc": 0, "limit": 1, "offset": 1, "other": -1},
|
|
||||||
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if len(arg) == 0 {
|
|
||||||
m.Cmdy(".query", "show tables")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
stmt := []string{
|
|
||||||
fmt.Sprintf("select %s", kit.Select("*", strings.Join(arg[1:], ","))),
|
|
||||||
fmt.Sprintf("from %s", arg[0]),
|
|
||||||
}
|
|
||||||
|
|
||||||
where := []string{}
|
|
||||||
if m.Has("where") {
|
|
||||||
where = append(where, m.Option("where"))
|
|
||||||
}
|
|
||||||
for i := 0; i < len(m.Meta["eq"]); i += 2 {
|
|
||||||
where = append(where, fmt.Sprintf("%s='%s'", m.Meta["eq"][i], m.Meta["eq"][i+1]))
|
|
||||||
}
|
|
||||||
for i := 0; i < len(m.Meta["ne"]); i += 2 {
|
|
||||||
where = append(where, fmt.Sprintf("%s!='%s'", m.Meta["ne"][i], m.Meta["ne"][i+1]))
|
|
||||||
}
|
|
||||||
for i := 0; i < len(m.Meta["in"]); i += 2 {
|
|
||||||
where = append(where, fmt.Sprintf("%s in (%s)", m.Meta["in"][i], m.Meta["in"][i+1]))
|
|
||||||
}
|
|
||||||
for i := 0; i < len(m.Meta["like"]); i += 2 {
|
|
||||||
where = append(where, fmt.Sprintf("%s like '%s'", m.Meta["like"][i], m.Meta["like"][i+1]))
|
|
||||||
}
|
|
||||||
for i := 0; i < len(m.Meta["begin"]); i += 2 {
|
|
||||||
where = append(where, fmt.Sprintf("%s like '%s%%'", m.Meta["begin"][i], m.Meta["begin"][i+1]))
|
|
||||||
}
|
|
||||||
if len(where) > 0 {
|
|
||||||
stmt = append(stmt, "where", strings.Join(where, " and "))
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.Has("group") {
|
|
||||||
stmt = append(stmt, fmt.Sprintf("group by %s", m.Option("group")))
|
|
||||||
}
|
|
||||||
if m.Has("order") {
|
|
||||||
stmt = append(stmt, fmt.Sprintf("order by %s", m.Option("order")))
|
|
||||||
}
|
|
||||||
if m.Has("desc") {
|
|
||||||
stmt = append(stmt, "desc")
|
|
||||||
}
|
|
||||||
|
|
||||||
stmt = append(stmt, fmt.Sprintf("limit %s", m.Confx("limit")))
|
|
||||||
stmt = append(stmt, fmt.Sprintf("offset %s", m.Confx("offset")))
|
|
||||||
|
|
||||||
for _, v := range m.Meta["other"] {
|
|
||||||
stmt = append(stmt, m.Parse(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Cmdy(".query", strings.Join(stmt, " "))
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"update": &ctx.Command{Name: "update [table [condition [field [value]]...]]",
|
|
||||||
Help: "修改数据, table: 关系表, condition: 条件语句, field: 字段名, value: 字段值",
|
|
||||||
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
switch len(arg) {
|
|
||||||
case 0:
|
|
||||||
m.Cmdy(".show")
|
|
||||||
case 1:
|
|
||||||
m.Cmdy(".show", arg[0])
|
|
||||||
case 2:
|
|
||||||
m.Cmdy(".show", arg[0], "where", arg[1])
|
|
||||||
case 3:
|
|
||||||
m.Cmdy(".show", arg[0], arg[2], "where", arg[1])
|
|
||||||
default:
|
|
||||||
fields := []string{}
|
|
||||||
values := []string{}
|
|
||||||
for i := 2; i < len(arg)-1; i += 2 {
|
|
||||||
fields = append(fields, arg[i])
|
|
||||||
values = append(values, fmt.Sprintf("%s='%s'", arg[i], arg[i+1]))
|
|
||||||
}
|
|
||||||
|
|
||||||
stmt := []string{"update", arg[0]}
|
|
||||||
stmt = append(stmt, "set", strings.Join(values, ","))
|
|
||||||
stmt = append(stmt, "where", arg[1])
|
|
||||||
m.Cmd(".exec", strings.Join(stmt, " "))
|
|
||||||
|
|
||||||
m.Cmdy(".show", arg[0], fields, "where", arg[1])
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
|
|
||||||
"ktv": &ctx.Command{Name: "ktv", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if len(arg) == 0 {
|
|
||||||
now := kit.Int(m.Time("stamp"))
|
|
||||||
m.Confm("ktv", "data", func(key string, value map[string]interface{}) {
|
|
||||||
m.Push("key", key)
|
|
||||||
m.Push("expire", kit.Int(value["expire"])-now)
|
|
||||||
m.Push("value", value["value"])
|
|
||||||
})
|
|
||||||
m.Table()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(arg) == 1 {
|
|
||||||
if m.Confi("ktv", []string{"data", arg[0], "expire"}) < kit.Int(m.Time("stamp")) {
|
|
||||||
m.Conf("ktv", []string{"data", arg[0]}, "")
|
|
||||||
}
|
|
||||||
m.Echo(m.Conf("ktv", []string{"data", arg[0], "value"}))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
m.Confv("ktv", []string{"data", arg[0]}, map[string]interface{}{
|
|
||||||
"expire": m.Time(kit.Select(m.Conf("ktv", "conf.expire"), arg, 2), "stamp"),
|
|
||||||
"value": arg[1],
|
|
||||||
})
|
|
||||||
m.Echo(arg[1])
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"temp": &ctx.Command{Name: "temp [type [meta [data]]] [tid [node|ship|data] [chain... [select ...]]]",
|
|
||||||
Form: map[string]int{"select": -1, "limit": 1}, Help: "缓存数据", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if len(arg) > 0 && arg[0] == "check" {
|
|
||||||
h := ""
|
|
||||||
for i := 1; i < len(arg)-1; i += 2 {
|
|
||||||
switch arg[i] {
|
|
||||||
case "url", "trans":
|
|
||||||
h = ""
|
|
||||||
}
|
|
||||||
if h = m.Cmdx("aaa.hash", arg[i], arg[i+1], h); !m.Confs("temp", h) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
expire := kit.Time(m.Conf("temp", []string{h, "create_time"})) + kit.Int(m.Confx("temp_expire")) - kit.Time(m.Time())
|
|
||||||
m.Log("info", "expire: %ds", expire)
|
|
||||||
if expire < 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Echo(h)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(arg) > 2 { // 添加数据
|
|
||||||
if temp := m.Confm("temp", arg[0]); temp == nil {
|
|
||||||
h := m.Cmdx("aaa.hash", arg[0], arg[1])
|
|
||||||
m.Confv("temp", h, map[string]interface{}{
|
|
||||||
"create_time": m.Time(), "expire_time": m.Time("60s"),
|
|
||||||
"type": arg[0], "meta": arg[1], "data": m.Optionv(arg[2]),
|
|
||||||
})
|
|
||||||
arg[2], arg = h, arg[2:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(arg) > 1 {
|
|
||||||
if temp, msg := m.Confm("temp", arg[0]), m; temp != nil {
|
|
||||||
hash, arg := arg[0], arg[1:]
|
|
||||||
switch arg[0] {
|
|
||||||
case "node": // 查看节点
|
|
||||||
m.Put("option", "temp", temp).Cmdy("ctx.trans", "temp")
|
|
||||||
return
|
|
||||||
case "ship": //查看链接
|
|
||||||
for k, v := range temp {
|
|
||||||
val := v.(map[string]interface{})
|
|
||||||
m.Add("append", "key", k)
|
|
||||||
m.Add("append", "create_time", val["create_time"])
|
|
||||||
m.Add("append", "type", val["type"])
|
|
||||||
m.Add("append", "meta", val["meta"])
|
|
||||||
}
|
|
||||||
m.Sort("create_time", "time_r").Table()
|
|
||||||
return
|
|
||||||
case "data": // 查看数据
|
|
||||||
arg = arg[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
trans := strings.Join(append([]string{hash, "data"}, arg...), ".")
|
|
||||||
h := m.Cmdx("aaa.hash", "trans", trans)
|
|
||||||
|
|
||||||
if len(arg) == 0 || temp["type"].(string) == "trans" {
|
|
||||||
h = hash
|
|
||||||
} else { // 转换数据
|
|
||||||
if view := m.Confm("temp", h); view != nil && false { // 加载缓存
|
|
||||||
msg = m.Spawn()
|
|
||||||
switch data := view["data"].(type) {
|
|
||||||
case map[string][]string:
|
|
||||||
msg.Meta = data
|
|
||||||
case map[string]interface{}:
|
|
||||||
for k, v := range data {
|
|
||||||
switch val := v.(type) {
|
|
||||||
case []interface{}:
|
|
||||||
msg.Add("append", k, val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Confv("temp", []string{h, "data"}, msg.Meta)
|
|
||||||
}
|
|
||||||
temp = view
|
|
||||||
} else if arg[0] == "hash" { // 添加缓存
|
|
||||||
m.Echo(hash)
|
|
||||||
} else if arg[0] == "" { // 添加缓存
|
|
||||||
b, _ := json.MarshalIndent(temp["data"], "", " ")
|
|
||||||
m.Echo(string(b))
|
|
||||||
} else {
|
|
||||||
msg = m.Put("option", "temp", temp["data"]).Cmd("ctx.trans", "temp", arg)
|
|
||||||
|
|
||||||
m.Confv("temp", h, map[string]interface{}{
|
|
||||||
"create_time": m.Time(), "expire_time": m.Time("60s"),
|
|
||||||
"type": "trans", "meta": trans, "data": msg.Meta,
|
|
||||||
"ship": map[string]interface{}{
|
|
||||||
hash: map[string]interface{}{"create_time": m.Time(), "ship": "0", "type": temp["type"], "meta": temp["meta"]},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
m.Confv("temp", []string{hash, "ship", h}, map[string]interface{}{
|
|
||||||
"create_time": m.Time(), "ship": "1", "type": "trans", "meta": trans,
|
|
||||||
})
|
|
||||||
temp = m.Confm("temp", h)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.Options("select") { // 过滤数据
|
|
||||||
chain := strings.Join(m.Optionv("select").([]string), " ")
|
|
||||||
hh := m.Cmdx("aaa.hash", "select", chain, h)
|
|
||||||
|
|
||||||
if view := m.Confm("temp", hh); view != nil && false { // 加载缓存
|
|
||||||
msg = msg.Spawn()
|
|
||||||
switch data := view["data"].(type) {
|
|
||||||
case map[string][]string:
|
|
||||||
msg.Meta = data
|
|
||||||
case map[string]interface{}:
|
|
||||||
for k, v := range data {
|
|
||||||
switch val := v.(type) {
|
|
||||||
case []interface{}:
|
|
||||||
msg.Add("append", k, val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Confv("temp", []string{h, "data"}, msg.Meta)
|
|
||||||
}
|
|
||||||
} else { // 添加缓存
|
|
||||||
msg = msg.Spawn().Copy(msg, "append").Cmd("select", m.Optionv("select"))
|
|
||||||
|
|
||||||
m.Confv("temp", hh, map[string]interface{}{
|
|
||||||
"create_time": m.Time(), "expire_time": m.Time("60s"),
|
|
||||||
"type": "select", "meta": chain, "data": msg.Meta,
|
|
||||||
"ship": map[string]interface{}{
|
|
||||||
h: map[string]interface{}{"create_time": m.Time(), "ship": "0", "type": temp["type"], "meta": temp["meta"]},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
m.Confv("temp", []string{h, "ship", hh}, map[string]interface{}{
|
|
||||||
"create_time": m.Time(), "ship": "1", "type": "select", "meta": chain,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
msg.CopyTo(m)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h, arg := arg[0], arg[1:]
|
|
||||||
if h != "" {
|
|
||||||
if temp := m.Confm("temp", h); temp != nil {
|
|
||||||
m.Echo(h)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 缓存列表
|
|
||||||
m.Confm("temp", func(key string, temp map[string]interface{}) {
|
|
||||||
if len(arg) == 0 || strings.HasPrefix(key, arg[0]) || strings.HasSuffix(key, arg[0]) || (temp["type"].(string) == arg[0] && (len(arg) == 1 || strings.Contains(temp["meta"].(string), arg[1]))) {
|
|
||||||
m.Add("append", "key", key)
|
|
||||||
m.Add("append", "create_time", temp["create_time"])
|
|
||||||
m.Add("append", "type", temp["type"])
|
|
||||||
m.Add("append", "meta", temp["meta"])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
m.Sort("create_time", "time_r").Table().Cmd("select", m.Optionv("select"))
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"note": &ctx.Command{Name: "note [model [name [type name]...]]|[index [name data...]]|[value name data...]|[name model data...]",
|
|
||||||
Form: map[string]int{"eq": 2, "begin": 2, "offset": 1, "limit": 1}, Help: "记事", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
offset := kit.Int(kit.Select(m.Conf("table", "offset"), m.Option("table.offset")))
|
|
||||||
limit := kit.Int(kit.Select(m.Conf("table", "limit"), m.Option("table.limit")))
|
|
||||||
|
|
||||||
// 节点列表
|
|
||||||
if len(arg) == 0 {
|
|
||||||
m.CopyFuck(m.Cmd("mdb.config", "note", "format", "table", "fields", "create_time", "access_time", "type", "name", "data", "ship"), "append").Set("result").Table()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 节点详情
|
|
||||||
if note := m.Confm("note", arg[0]); note != nil {
|
|
||||||
m.CopyFuck(m.Cmd("mdb.config", "note", arg[0]), "append").Set("result").Table()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 节点列表
|
|
||||||
hm, _ := kit.Hash("type", arg[0], "name", "shy")
|
|
||||||
if len(arg) == 2 && arg[0] == "value" {
|
|
||||||
hm, _ = kit.Hash("type", "index", "name", arg[1])
|
|
||||||
hm = m.Conf("note", []string{hm, "ship", "value", "data"})
|
|
||||||
arg = arg[1:]
|
|
||||||
} else if len(arg) == 2 && arg[0] == "note" {
|
|
||||||
hm, _ = kit.Hash("type", "model", "name", arg[1])
|
|
||||||
hm = m.Conf("note", []string{hm, "ship", "note", "data"})
|
|
||||||
arg = arg[1:]
|
|
||||||
}
|
|
||||||
if len(arg) == 1 && arg[0] != "show" {
|
|
||||||
for i := offset; hm != "" && i < limit+offset; hm, i = m.Conf("note", []string{hm, "ship", "prev", "data"}), i+1 {
|
|
||||||
model := m.Confm("note", hm)
|
|
||||||
m.Add("append", "key", hm)
|
|
||||||
m.Add("append", "create_time", model["create_time"])
|
|
||||||
m.Add("append", "access_time", model["access_time"])
|
|
||||||
m.Add("append", "type", model["type"])
|
|
||||||
m.Add("append", "name", model["name"])
|
|
||||||
m.Add("append", "view", kit.Format(model["view"]))
|
|
||||||
m.Add("append", "data", kit.Format(model["data"]))
|
|
||||||
m.Add("append", "ship", kit.Format(model["ship"]))
|
|
||||||
}
|
|
||||||
m.Table()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch arg[0] {
|
|
||||||
case "show":
|
|
||||||
if len(arg) == 1 { // 查看索引
|
|
||||||
m.Cmdy("mdb.note", "index")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if len(arg) == 2 {
|
|
||||||
if arg[1] == "model" { // 查看模型
|
|
||||||
m.Cmdy("mdb.note", "model")
|
|
||||||
} else { // 查看数值
|
|
||||||
m.Cmdy("mdb.note", "value", arg[1])
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
fields := kit.View(arg[3:], m.Confm("note_view"))
|
|
||||||
|
|
||||||
hv, _ := kit.Hash("type", "value", "name", arg[1], "data", kit.Select(arg[2], m.Option(arg[2])))
|
|
||||||
hn := m.Conf("note", []string{hv, "ship", "note", "data"})
|
|
||||||
if arg[1] == "model" {
|
|
||||||
hm, _ := kit.Hash("type", "model", "name", arg[2])
|
|
||||||
hv, hn = "prev", m.Conf("note", []string{hm, "ship", "note", "data"})
|
|
||||||
}
|
|
||||||
|
|
||||||
fuck := 0
|
|
||||||
for i := 0; hn != "" && i < limit+offset; hn, i = m.Conf("note", []string{hn, "ship", hv, "data"}), i+1 {
|
|
||||||
m.Log("fuck", "what %d %d %d %s", offset, limit, i, hn)
|
|
||||||
// m.Log("fuck", "what hn: %v %v", hn, kit.Formats(m.Confv("note", hn)))
|
|
||||||
// 翻页
|
|
||||||
if fuck++; fuck > 1000 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if i < offset {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// 关系表
|
|
||||||
note := m.Confm("note", hn)
|
|
||||||
hvs := kit.Trans(note["data"])
|
|
||||||
hm := kit.Format(kit.Chain(note, "ship.model.data"))
|
|
||||||
|
|
||||||
// 值转换
|
|
||||||
value := []interface{}{}
|
|
||||||
values := map[string]interface{}{}
|
|
||||||
m.Confm("note", []string{hm, "data"}, func(i int, model map[string]interface{}) {
|
|
||||||
v := m.Conf("note", []string{hvs[i], "data"})
|
|
||||||
value = append(value, map[string]interface{}{"type": model["type"], "name": model["name"], "value": v})
|
|
||||||
values[kit.Format(model["name"])] = v
|
|
||||||
})
|
|
||||||
|
|
||||||
// 行筛选
|
|
||||||
miss := false
|
|
||||||
if !miss && m.Has("eq") {
|
|
||||||
for j := 0; j < len(m.Meta["eq"]); j += 2 {
|
|
||||||
if kit.Select(kit.Format(note[m.Meta["eq"][j]]), kit.Format(values[m.Meta["eq"][j]])) != m.Meta["eq"][j+1] {
|
|
||||||
miss = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !miss && m.Has("begin") {
|
|
||||||
for j := 0; j < len(m.Meta["begin"]); j += 2 {
|
|
||||||
if !strings.HasPrefix(kit.Select(kit.Format(note[m.Meta["begin"][j]]),
|
|
||||||
kit.Format(values[m.Meta["begin"][j]])), m.Meta["begin"][j+1]) {
|
|
||||||
miss = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if miss {
|
|
||||||
i--
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// 列筛选
|
|
||||||
for j := 0; j < len(fields); j++ {
|
|
||||||
switch fields[j] {
|
|
||||||
case "key":
|
|
||||||
m.Add("append", "key", hn)
|
|
||||||
case "create_time", "access_time", "type", "name":
|
|
||||||
m.Add("append", fields[j], note[fields[j]])
|
|
||||||
case "model":
|
|
||||||
m.Add("append", "model", m.Conf("note", []string{hm, "name"}))
|
|
||||||
case "view":
|
|
||||||
m.Add("append", "view", kit.Format(m.Conf("note", []string{hm, "view"})))
|
|
||||||
case "value":
|
|
||||||
m.Add("append", "value", kit.Format(value))
|
|
||||||
case "data", "ship":
|
|
||||||
m.Add("append", fields[j], kit.Format(note[fields[j]]))
|
|
||||||
default:
|
|
||||||
m.Add("append", fields[j], kit.Format(values[fields[j]]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Table()
|
|
||||||
|
|
||||||
case "model":
|
|
||||||
// 模板详情
|
|
||||||
hm, _ := kit.Hash("type", arg[0], "name", arg[1])
|
|
||||||
if len(arg) == 2 {
|
|
||||||
m.CopyFuck(m.Cmd("mdb.config", "note", hm), "append").Set("result").Table()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// 模板视图
|
|
||||||
if arg[2] == "view" {
|
|
||||||
for i := 4; i < len(arg)-1; i += 2 {
|
|
||||||
m.Conf("note", []string{hm, "view", arg[3], arg[i]}, arg[i+1])
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// 操作模板
|
|
||||||
data := []interface{}{}
|
|
||||||
if model := m.Confm("note", hm); model == nil { // 添加模板
|
|
||||||
view := map[string]interface{}{}
|
|
||||||
m.Confm("note", "81c5709d091eb04bd31ee751c3f81023.view", func(key string, fields map[string]interface{}) {
|
|
||||||
vs := map[string]interface{}{}
|
|
||||||
for k, v := range fields {
|
|
||||||
vs[k] = v
|
|
||||||
}
|
|
||||||
view[key] = vs
|
|
||||||
})
|
|
||||||
|
|
||||||
prev := m.Conf("note", []string{"81c5709d091eb04bd31ee751c3f81023", "ship", "prev", "data"})
|
|
||||||
m.Confv("note", hm, map[string]interface{}{
|
|
||||||
"type": "model", "name": arg[1], "data": data, "view": view,
|
|
||||||
"create_time": m.Time(), "access_time": m.Time(),
|
|
||||||
"ship": map[string]interface{}{
|
|
||||||
"prev": map[string]interface{}{"type": "model", "data": prev},
|
|
||||||
"note": map[string]interface{}{"type": "note", "data": ""},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
m.Conf("note", []string{"81c5709d091eb04bd31ee751c3f81023", "ship", "prev", "data"}, hm)
|
|
||||||
} else { // 修改模板
|
|
||||||
data = m.Confv("note", []string{hm, "data"}).([]interface{})
|
|
||||||
m.Confv("note", []string{hm, "access_time"}, m.Time())
|
|
||||||
}
|
|
||||||
|
|
||||||
// 操作元素
|
|
||||||
if len(data) == 0 {
|
|
||||||
arg = append(arg, kit.Trans(m.Confv("note", "81c5709d091eb04bd31ee751c3f81023.meta"))...)
|
|
||||||
for i := 2; i < len(arg)-1; i += 2 {
|
|
||||||
data = append(data, map[string]interface{}{"name": arg[i], "type": arg[i+1]})
|
|
||||||
|
|
||||||
hi, _ := kit.Hash("type", "index", "name", arg[i+1])
|
|
||||||
if index := m.Confm("note", hi); index == nil {
|
|
||||||
m.Cmd("mdb.note", "index", arg[i+1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Confv("note", []string{hm, "data"}, data)
|
|
||||||
m.Echo(hm)
|
|
||||||
|
|
||||||
case "index":
|
|
||||||
// 操作索引
|
|
||||||
data := arg[2:]
|
|
||||||
hi, _ := kit.Hash("type", arg[0], "name", arg[1])
|
|
||||||
if index := m.Confm("note", hi); index == nil { // 添加索引
|
|
||||||
prev := m.Conf("note", []string{"faa01a8fc2fc92dae3fbc02ac1b4ec75", "ship", "prev", "data"})
|
|
||||||
m.Confv("note", hi, map[string]interface{}{
|
|
||||||
"create_time": m.Time(), "access_time": m.Time(),
|
|
||||||
"type": "index", "name": arg[1], "data": data, "ship": map[string]interface{}{
|
|
||||||
"prev": map[string]interface{}{"type": "index", "data": prev},
|
|
||||||
"value": map[string]interface{}{"type": "value", "data": ""},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
m.Confv("note", []string{"faa01a8fc2fc92dae3fbc02ac1b4ec75", "ship", "prev", "data"}, hi)
|
|
||||||
} else { // 修改索引
|
|
||||||
m.Confv("note", []string{hi, "access_time"}, m.Time())
|
|
||||||
data, _ = m.Confv("note", []string{hi, "data"}).([]string)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 操作元素
|
|
||||||
m.Confv("note", []string{hi, "data"}, data)
|
|
||||||
m.Echo(hi)
|
|
||||||
|
|
||||||
case "value":
|
|
||||||
hi := m.Cmdx("mdb.note", "index", arg[1])
|
|
||||||
hv, _ := kit.Hash("type", arg[0], "name", arg[1], "data", arg[2])
|
|
||||||
if value := m.Confm("note", hv); value == nil {
|
|
||||||
prev := m.Conf("note", []string{hi, "ship", "value", "data"})
|
|
||||||
m.Confv("note", hv, map[string]interface{}{
|
|
||||||
"create_time": m.Time(), "access_time": m.Time(),
|
|
||||||
"type": arg[0], "name": arg[1], "data": arg[2], "ship": map[string]interface{}{
|
|
||||||
"prev": map[string]interface{}{"type": "value", "data": prev},
|
|
||||||
"index": map[string]interface{}{"type": "index", "data": hi},
|
|
||||||
"note": map[string]interface{}{"type": "note", "data": ""},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
m.Conf("note", []string{hi, "ship", "value", "data"}, hv)
|
|
||||||
} else {
|
|
||||||
m.Confv("note", []string{hv, "access_time"}, m.Time())
|
|
||||||
}
|
|
||||||
m.Echo(hv)
|
|
||||||
|
|
||||||
default:
|
|
||||||
if len(arg) == 2 {
|
|
||||||
}
|
|
||||||
|
|
||||||
hm, _ := kit.Hash("type", "model", "name", arg[1])
|
|
||||||
hn, _ := kit.Hash("type", "note", "name", arg[0], "uniq")
|
|
||||||
hp := m.Conf("note", []string{hm, "ship", "note", "data"})
|
|
||||||
if hp == hn {
|
|
||||||
hp = ""
|
|
||||||
}
|
|
||||||
ship := map[string]interface{}{
|
|
||||||
"prev": map[string]interface{}{"type": "note", "data": hp},
|
|
||||||
"model": map[string]interface{}{"type": "model", "data": hm},
|
|
||||||
}
|
|
||||||
|
|
||||||
data := []interface{}{}
|
|
||||||
m.Confm("note", []string{hm, "data"}, func(i int, index map[string]interface{}) {
|
|
||||||
hv := m.Cmdx("mdb.note", "value", index["type"], kit.Select(m.Option(kit.Format(index["name"])), arg, i+2))
|
|
||||||
data = append(data, hv)
|
|
||||||
|
|
||||||
ship[hv] = map[string]interface{}{"type": "note", "data": m.Conf("note", []string{hv, "ship", "note", "data"})}
|
|
||||||
m.Conf("note", []string{hv, "ship", "note", "data"}, hn)
|
|
||||||
})
|
|
||||||
|
|
||||||
m.Confv("note", hn, map[string]interface{}{
|
|
||||||
"create_time": m.Time(), "access_time": m.Time(),
|
|
||||||
"type": "note", "name": arg[0], "data": data, "ship": ship,
|
|
||||||
})
|
|
||||||
m.Conf("note", []string{hm, "ship", "note", "data"}, hn)
|
|
||||||
m.Echo(hn)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
|
|
||||||
sync := len(arg) > 0 && arg[0] == "sync"
|
|
||||||
if sync {
|
|
||||||
m.Cmdy("ssh.sh", "sub", "context", "mdb", "note", arg)
|
|
||||||
m.Set("result").Table()
|
|
||||||
arg = arg[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
h, _ := kit.Hash("uniq")
|
|
||||||
data := map[string]interface{}{
|
|
||||||
"create_time": m.Time(),
|
|
||||||
"type": arg[0],
|
|
||||||
"title": arg[1],
|
|
||||||
"content": arg[2],
|
|
||||||
}
|
|
||||||
for i := 3; i < len(arg)-1; i += 2 {
|
|
||||||
kit.Chain(data, data[arg[i]], arg[i+1])
|
|
||||||
}
|
|
||||||
m.Conf("note", h, data)
|
|
||||||
m.Echo(h)
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ctx.Index.Register(Index, &MDB{Context: Index})
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,647 +0,0 @@
|
|||||||
package nfs
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/nsf/termbox-go"
|
|
||||||
|
|
||||||
"contexts/ctx"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (nfs *NFS) Read(p []byte) (n int, err error) {
|
|
||||||
m := nfs.Context.Message()
|
|
||||||
if !m.Caps("termbox") {
|
|
||||||
return nfs.in.Read(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
m.TryCatch(m, true, func(m *ctx.Message) {
|
|
||||||
scroll_count := 0
|
|
||||||
scroll_lines := m.Confi("term", "scroll_lines")
|
|
||||||
which := m.Capi("ninput")
|
|
||||||
what := make([]rune, 0, 1024)
|
|
||||||
rest := make([]rune, 0, 1024)
|
|
||||||
back := make([]rune, 0, 1024)
|
|
||||||
|
|
||||||
m.Option("bio.cmd", "")
|
|
||||||
m.Options("bio.shadow", m.Confs("show_shadow"))
|
|
||||||
|
|
||||||
defer func() { m.Option("bio.cmd", "") }()
|
|
||||||
|
|
||||||
frame, table, index, pick := map[string]interface{}{}, []map[string]string{}, 0, 0
|
|
||||||
if change, f, t, i := nfs.Auto(what, ":", 0); change {
|
|
||||||
frame, table, index, pick = f, t, i, 0
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
switch ev := termbox.PollEvent(); ev.Type {
|
|
||||||
case termbox.EventInterrupt:
|
|
||||||
case termbox.EventResize:
|
|
||||||
nfs.Term(m, "resize")
|
|
||||||
case termbox.EventMouse:
|
|
||||||
switch ev.Key {
|
|
||||||
case termbox.MouseLeft:
|
|
||||||
if m.Confs("term", "mouse.resize") {
|
|
||||||
nfs.Term(m, "window", ev.MouseX, ev.MouseY)
|
|
||||||
nfs.prompt(what).shadow(rest)
|
|
||||||
}
|
|
||||||
|
|
||||||
case termbox.MouseMiddle:
|
|
||||||
case termbox.MouseRight:
|
|
||||||
if m.Confs("term", "mouse.resize") {
|
|
||||||
nfs.Term(m, "resize", ev.MouseX, ev.MouseY)
|
|
||||||
}
|
|
||||||
case termbox.MouseRelease:
|
|
||||||
case termbox.MouseWheelUp:
|
|
||||||
if scroll_count++; scroll_count > m.Confi("term", "scroll_count") {
|
|
||||||
nfs.Term(m, "scroll", -1).Term(m, "flush")
|
|
||||||
scroll_count = 0
|
|
||||||
}
|
|
||||||
case termbox.MouseWheelDown:
|
|
||||||
if scroll_count++; scroll_count > m.Confi("term", "scroll_count") {
|
|
||||||
nfs.Term(m, "scroll", 1).Term(m, "flush")
|
|
||||||
scroll_count = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case termbox.EventError:
|
|
||||||
case termbox.EventNone:
|
|
||||||
case termbox.EventRaw:
|
|
||||||
case termbox.EventKey:
|
|
||||||
|
|
||||||
switch ev.Key {
|
|
||||||
case termbox.KeyCtrlP:
|
|
||||||
if which--; which < 0 {
|
|
||||||
which = m.Capi("ninput") - 1
|
|
||||||
}
|
|
||||||
if v := m.Conf("input", []interface{}{which, "line"}); v != "" {
|
|
||||||
what, rest = append(what[:0], []rune(v)...), rest[:0]
|
|
||||||
nfs.prompt(what).shadow(rest)
|
|
||||||
}
|
|
||||||
case termbox.KeyCtrlN:
|
|
||||||
if which++; which >= m.Capi("ninput") {
|
|
||||||
which = 0
|
|
||||||
}
|
|
||||||
if v := m.Conf("input", []interface{}{which, "line"}); v != "" {
|
|
||||||
what, rest = append(what[:0], []rune(v)...), rest[:0]
|
|
||||||
nfs.prompt(what).shadow(rest)
|
|
||||||
}
|
|
||||||
|
|
||||||
case termbox.KeyCtrlA:
|
|
||||||
if len(what) > 0 {
|
|
||||||
what, rest = append(what, rest...), rest[:0]
|
|
||||||
rest, what = append(rest, what...), what[:0]
|
|
||||||
nfs.prompt(what).shadow(rest)
|
|
||||||
}
|
|
||||||
case termbox.KeyCtrlF:
|
|
||||||
if len(rest) > 0 {
|
|
||||||
pos := len(what) + 1
|
|
||||||
what, rest = append(what, rest...), rest[:0]
|
|
||||||
rest, what = append(rest, what[pos:]...), what[:pos]
|
|
||||||
nfs.prompt(what).shadow(rest)
|
|
||||||
}
|
|
||||||
case termbox.KeyCtrlB:
|
|
||||||
if len(what) > 0 {
|
|
||||||
pos := len(what) - 1
|
|
||||||
what, rest = append(what, rest...), rest[:0]
|
|
||||||
rest, what = append(rest, what[pos:]...), what[:pos]
|
|
||||||
nfs.prompt(what).shadow(rest)
|
|
||||||
}
|
|
||||||
case termbox.KeyCtrlE:
|
|
||||||
if len(rest) > 0 {
|
|
||||||
what, rest = append(what, rest...), rest[:0]
|
|
||||||
nfs.prompt(what).shadow(rest)
|
|
||||||
}
|
|
||||||
|
|
||||||
case termbox.KeyCtrlU:
|
|
||||||
back = back[:0]
|
|
||||||
back, what = append(back, what...), what[:0]
|
|
||||||
nfs.prompt(what).shadow(rest)
|
|
||||||
case termbox.KeyCtrlD: // termbox.KeyBackspace
|
|
||||||
if len(rest) > 0 {
|
|
||||||
pos := len(what)
|
|
||||||
what, rest = append(what, rest[1:]...), rest[:0]
|
|
||||||
rest, what = append(rest, what[pos:]...), what[:pos]
|
|
||||||
nfs.prompt(what).shadow(rest)
|
|
||||||
}
|
|
||||||
case termbox.KeyCtrlH: // termbox.KeyBackspace
|
|
||||||
if len(what) > 0 {
|
|
||||||
what = what[:len(what)-1]
|
|
||||||
nfs.prompt(what).shadow(rest)
|
|
||||||
}
|
|
||||||
case termbox.KeyCtrlK:
|
|
||||||
back = back[:0]
|
|
||||||
back, rest = append(back, rest...), rest[:0]
|
|
||||||
nfs.prompt(what).shadow(rest)
|
|
||||||
|
|
||||||
case termbox.KeyCtrlW:
|
|
||||||
if len(what) > 0 {
|
|
||||||
pos := len(what) - 1
|
|
||||||
for space := what[pos] == ' '; pos >= 0; pos-- {
|
|
||||||
if (space && what[pos] != ' ') || (!space && what[pos] == ' ') {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
back = back[:0]
|
|
||||||
back, what = append(back, what[pos+1:]...), what[:pos+1]
|
|
||||||
nfs.prompt(what).shadow(rest)
|
|
||||||
}
|
|
||||||
case termbox.KeyCtrlY:
|
|
||||||
what = append(what, back...)
|
|
||||||
nfs.prompt(what).shadow(rest)
|
|
||||||
|
|
||||||
case termbox.KeyCtrlR:
|
|
||||||
nfs.Term(m, "refresh").Term(m, "flush")
|
|
||||||
nfs.prompt(what).shadow(rest)
|
|
||||||
case termbox.KeyCtrlL:
|
|
||||||
m.Confi("term", "begin_row", m.Capi("noutput"))
|
|
||||||
m.Confi("term", "begin_col", 0)
|
|
||||||
nfs.Term(m, "clear", "all").Term(m, "flush")
|
|
||||||
nfs.prompt(what).shadow(rest)
|
|
||||||
|
|
||||||
case termbox.KeyCtrlT:
|
|
||||||
m.Option("scroll", true)
|
|
||||||
nfs.Term(m, "scroll", scroll_lines).Term(m, "flush")
|
|
||||||
m.Option("scroll", false)
|
|
||||||
case termbox.KeyCtrlO:
|
|
||||||
m.Option("scroll", true)
|
|
||||||
nfs.Term(m, "scroll", -scroll_lines).Term(m, "flush")
|
|
||||||
m.Option("scroll", false)
|
|
||||||
|
|
||||||
case termbox.KeyCtrlJ, termbox.KeyEnter:
|
|
||||||
what = append(what, '\n')
|
|
||||||
n = copy(p, []byte(string(what)))
|
|
||||||
return
|
|
||||||
case termbox.KeyCtrlQ, termbox.KeyCtrlC:
|
|
||||||
nfs.Term(m, "exit")
|
|
||||||
n = copy(p, []byte("return\n"))
|
|
||||||
return
|
|
||||||
|
|
||||||
case termbox.KeyCtrlV:
|
|
||||||
|
|
||||||
for i := -1; i < 8; i++ {
|
|
||||||
nfs.Term(m, "color", i, m.Confi("term", "rest_fg"), fmt.Sprintf("\nhello bg %d", i))
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := -1; i < 8; i++ {
|
|
||||||
nfs.Term(m, "color", m.Confi("term", "rest_bg"), i, fmt.Sprintf("\nhello fg %d", i))
|
|
||||||
}
|
|
||||||
nfs.Term(m, "flush")
|
|
||||||
|
|
||||||
case termbox.KeyCtrlG:
|
|
||||||
case termbox.KeyCtrlX:
|
|
||||||
m.Options("bio.shadow", !m.Options("bio.shadow"))
|
|
||||||
case termbox.KeyCtrlS:
|
|
||||||
|
|
||||||
case termbox.KeyCtrlZ:
|
|
||||||
|
|
||||||
case termbox.KeyTab:
|
|
||||||
m.Options("bio.shadow", true)
|
|
||||||
// if index > len(what) {
|
|
||||||
// nfs.shadow("", table, frame)
|
|
||||||
// } else {
|
|
||||||
// if lines := kit.Int(frame["lines"]); lines > 0 {
|
|
||||||
// pick = (pick + 1) % lines
|
|
||||||
// }
|
|
||||||
// nfs.shadow(what[index:], table, frame, pick)
|
|
||||||
// rest = append(rest[:0], []rune(kit.Format(frame["pick"]))[len(what)-index:]...)
|
|
||||||
// nfs.prompt(what).shadow(rest)
|
|
||||||
// nfs.shadow(what[index:], table, frame, pick)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
case termbox.KeySpace:
|
|
||||||
what = append(what, ' ')
|
|
||||||
nfs.prompt(what).shadow(rest)
|
|
||||||
if !m.Options("bio.shadow") {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if index > len(what) {
|
|
||||||
nfs.shadow("", table, frame)
|
|
||||||
} else {
|
|
||||||
m.Option("auto_key", strings.TrimSpace(string(what[index:])))
|
|
||||||
if change, f, t, i := nfs.Auto(what, " ", len(what)); change {
|
|
||||||
frame, table, index, pick = f, t, i, 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if nfs.shadow(what[index:], table, frame); len(table) > 0 {
|
|
||||||
rest = append(rest[:0], []rune(table[0][kit.Format(frame["field"])])...)
|
|
||||||
nfs.prompt(what).shadow(rest)
|
|
||||||
nfs.shadow(what[index:], table, frame)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
what = append(what, ev.Ch)
|
|
||||||
nfs.prompt(what).shadow(rest)
|
|
||||||
if !m.Options("bio.shadow") {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if change, f, t, i := nfs.Auto(what, kit.Format(ev.Ch), len(what)); change {
|
|
||||||
frame, table, index, pick = f, t, i, 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if index > len(what) {
|
|
||||||
nfs.shadow("", table, frame)
|
|
||||||
} else {
|
|
||||||
nfs.shadow(what[index:], table, frame, pick)
|
|
||||||
if pos, word := len(what)-index, kit.Format(frame["pick"]); len(table) > 0 && pos < len(word) {
|
|
||||||
rest = append(rest[:0], []rune(word)[pos:]...)
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
nfs.prompt(what).shadow(rest)
|
|
||||||
nfs.shadow(what[index:], table, frame, pick)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
func (nfs *NFS) Auto(what []rune, trigger string, index int) (change bool, frame map[string]interface{}, table []map[string]string, nindex int) {
|
|
||||||
return
|
|
||||||
m := nfs.Context.Message()
|
|
||||||
|
|
||||||
auto_target := m.Optionv("bio.ctx").(*ctx.Context)
|
|
||||||
auto_cmd := ""
|
|
||||||
auto_arg := []string{}
|
|
||||||
|
|
||||||
switch trigger {
|
|
||||||
case " ":
|
|
||||||
switch m.Conf("term", "help_state") {
|
|
||||||
case "context":
|
|
||||||
// auto_target = auto_target.Sub(m.Option("auto_key"))
|
|
||||||
m.Optionv("bio.ctx", auto_target)
|
|
||||||
trigger = ":"
|
|
||||||
case "command":
|
|
||||||
m.Option("arg_index", index)
|
|
||||||
auto_cmd = m.Option("bio.cmd", m.Option("auto_key"))
|
|
||||||
trigger = "="
|
|
||||||
case "argument":
|
|
||||||
auto_cmd = m.Option("bio.cmd")
|
|
||||||
auto_arg = strings.Split(strings.TrimSpace(string(what[m.Optioni("arg_index"):])), " ")
|
|
||||||
trigger = "="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto := m.Confm("auto", trigger)
|
|
||||||
if auto == nil {
|
|
||||||
return false, nil, nil, 0
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd := []interface{}{kit.Select(kit.Format(auto["cmd"]), auto_cmd)}
|
|
||||||
if len(auto_arg) == 0 {
|
|
||||||
auto_arg = kit.Trans(auto["arg"])
|
|
||||||
}
|
|
||||||
for _, v := range auto_arg {
|
|
||||||
cmd = append(cmd, m.Parse(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
table = []map[string]string{}
|
|
||||||
m.Spawn(auto_target).Cmd(cmd...).Table(func(line int, maps map[string]string) {
|
|
||||||
fields := []interface{}{}
|
|
||||||
for _, v := range auto["fields"].([]interface{}) {
|
|
||||||
fields = append(fields, maps[kit.Format(v)])
|
|
||||||
}
|
|
||||||
maps["format"] = fmt.Sprintf(kit.Format(auto["format"]), fields...)
|
|
||||||
table = append(table, maps)
|
|
||||||
})
|
|
||||||
m.Conf("term", []interface{}{"help_table", auto["table"]}, table)
|
|
||||||
|
|
||||||
frame = map[string]interface{}{
|
|
||||||
"color": auto["color"],
|
|
||||||
"table": auto["table"],
|
|
||||||
"field": auto["field"],
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.Conf("term", []interface{}{"help_index"}, index); index == 0 {
|
|
||||||
m.Conf("term", "help_stack", []interface{}{frame})
|
|
||||||
} else {
|
|
||||||
m.Conf("term", []interface{}{"help_stack", -2}, frame)
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Conf("term", "help_next_auto", auto["next_auto"])
|
|
||||||
m.Conf("term", "help_state", auto["state"])
|
|
||||||
return true, frame, table, index
|
|
||||||
}
|
|
||||||
func (nfs *NFS) Term(msg *ctx.Message, action string, args ...interface{}) *NFS {
|
|
||||||
m := nfs.Context.Message()
|
|
||||||
// m.Log("debug", "%s %v", action, args)
|
|
||||||
|
|
||||||
switch action {
|
|
||||||
case "exit":
|
|
||||||
if m.Caps("termbox") {
|
|
||||||
termbox.Close()
|
|
||||||
}
|
|
||||||
m.Caps("termbox", false)
|
|
||||||
return nfs
|
|
||||||
|
|
||||||
case "init":
|
|
||||||
defer func() {
|
|
||||||
if e := recover(); e != nil {
|
|
||||||
m.Log("warn", "term init %s", e)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
termbox.Init()
|
|
||||||
termbox.SetInputMode(termbox.InputEsc)
|
|
||||||
termbox.SetInputMode(termbox.InputMouse)
|
|
||||||
m.Cap("termbox", "true")
|
|
||||||
}
|
|
||||||
|
|
||||||
width, height := termbox.Size()
|
|
||||||
msg.Conf("term", "width", width)
|
|
||||||
msg.Conf("term", "height", height)
|
|
||||||
|
|
||||||
left := msg.Confi("term", "left")
|
|
||||||
top := msg.Confi("term", "top")
|
|
||||||
right := msg.Confi("term", "right")
|
|
||||||
bottom := msg.Confi("term", "bottom")
|
|
||||||
|
|
||||||
x := m.Confi("term", "cursor_x")
|
|
||||||
y := m.Confi("term", "cursor_y")
|
|
||||||
bg := termbox.Attribute(msg.Confi("term", "bgcolor"))
|
|
||||||
fg := termbox.Attribute(msg.Confi("term", "fgcolor"))
|
|
||||||
|
|
||||||
begin_row := m.Confi("term", "begin_row")
|
|
||||||
begin_col := m.Confi("term", "begin_col")
|
|
||||||
|
|
||||||
switch action {
|
|
||||||
case "init":
|
|
||||||
m.Conf("term", "left", 0)
|
|
||||||
m.Conf("term", "top", 0)
|
|
||||||
m.Conf("term", "right", width)
|
|
||||||
m.Conf("term", "bottom", height)
|
|
||||||
|
|
||||||
case "exit":
|
|
||||||
m.Cap("termbox", "false")
|
|
||||||
termbox.Close()
|
|
||||||
|
|
||||||
case "window":
|
|
||||||
if len(args) > 1 {
|
|
||||||
msg.Conf("term", "left", args[0])
|
|
||||||
msg.Conf("term", "top", args[1])
|
|
||||||
}
|
|
||||||
if len(args) > 3 {
|
|
||||||
msg.Conf("term", "right", args[2])
|
|
||||||
msg.Conf("term", "bottom", args[3])
|
|
||||||
} else {
|
|
||||||
msg.Conf("term", "right", width)
|
|
||||||
msg.Conf("term", "bottom", height)
|
|
||||||
}
|
|
||||||
|
|
||||||
case "resize":
|
|
||||||
if len(args) > 1 {
|
|
||||||
msg.Conf("term", "right", args[0])
|
|
||||||
msg.Conf("term", "bottom", args[1])
|
|
||||||
right = msg.Confi("term", "right")
|
|
||||||
bottom = msg.Confi("term", "bottom")
|
|
||||||
} else {
|
|
||||||
msg.Conf("term", "right", right)
|
|
||||||
msg.Conf("term", "bottom", bottom)
|
|
||||||
}
|
|
||||||
|
|
||||||
fallthrough
|
|
||||||
case "clear":
|
|
||||||
if len(args) == 0 {
|
|
||||||
top = m.Confi("term", "prompt_y")
|
|
||||||
} else if kit.Format(args[0]) == "all" {
|
|
||||||
// nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
for x := left; x < right; x++ {
|
|
||||||
for y := top; y < bottom; y++ {
|
|
||||||
termbox.SetCell(x, y, ' ', fg, bg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Conf("term", "cursor_x", left)
|
|
||||||
m.Conf("term", "cursor_y", top)
|
|
||||||
termbox.SetCursor(left, top)
|
|
||||||
|
|
||||||
case "cursor":
|
|
||||||
m.Conf("term", "cursor_x", kit.Format(args[0]))
|
|
||||||
m.Conf("term", "cursor_y", kit.Format(args[1]))
|
|
||||||
termbox.SetCursor(m.Confi("term", "cursor_x"), m.Confi("term", "cursor_y"))
|
|
||||||
|
|
||||||
case "flush":
|
|
||||||
termbox.Flush()
|
|
||||||
|
|
||||||
case "scroll":
|
|
||||||
n := 1
|
|
||||||
if len(args) > 0 {
|
|
||||||
n = kit.Int(args[0])
|
|
||||||
}
|
|
||||||
m.Options("on_scroll", true)
|
|
||||||
|
|
||||||
// 向下滚动
|
|
||||||
for i := begin_row; n > 0 && i < m.Capi("noutput"); i++ {
|
|
||||||
line := []rune(m.Conf("output", []interface{}{i, "line"}))
|
|
||||||
|
|
||||||
for j, l := begin_col, left; n > 0; j, l = j+1, l+1 {
|
|
||||||
if j >= len(line)-1 {
|
|
||||||
begin_row, begin_col = i+1, 0
|
|
||||||
n--
|
|
||||||
break
|
|
||||||
} else if line[j] == '\n' {
|
|
||||||
begin_row, begin_col = i, j+1
|
|
||||||
n--
|
|
||||||
} else if l >= right-1 && m.Confs("term", "wrap") {
|
|
||||||
begin_row, begin_col = i, j
|
|
||||||
n--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 向上滚动
|
|
||||||
for i := begin_row; n < 0 && i >= 0; i-- {
|
|
||||||
line := []rune(m.Conf("output", []interface{}{i, "line"}))
|
|
||||||
if begin_col == 0 {
|
|
||||||
i--
|
|
||||||
line = []rune(m.Conf("output", []interface{}{i, "line"}))
|
|
||||||
begin_col = len(line)
|
|
||||||
}
|
|
||||||
|
|
||||||
for j, l := begin_col-1, right-1; n < 0; j, l = j-1, l-1 {
|
|
||||||
if j <= 0 {
|
|
||||||
begin_row, begin_col = i, 0
|
|
||||||
n++
|
|
||||||
break
|
|
||||||
} else if line[j-1] == '\n' {
|
|
||||||
begin_row, begin_col = i, j
|
|
||||||
n++
|
|
||||||
} else if l < left && m.Confs("term", "wrap") {
|
|
||||||
begin_row, begin_col = i, j
|
|
||||||
n++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Conf("term", "begin_row", begin_row)
|
|
||||||
m.Conf("term", "begin_col", begin_col)
|
|
||||||
|
|
||||||
fallthrough
|
|
||||||
case "refresh":
|
|
||||||
|
|
||||||
nfs.Term(m, "clear", "all")
|
|
||||||
for i := begin_row; i < m.Capi("noutput"); i++ {
|
|
||||||
if line := m.Conf("output", []interface{}{i, "line"}); begin_col < len(line) {
|
|
||||||
nfs.Term(m, "print", line[begin_col:])
|
|
||||||
}
|
|
||||||
begin_col = 0
|
|
||||||
}
|
|
||||||
// nfs.Term(m, "print", "\n")
|
|
||||||
// nfs.Term(m, "print", m.Conf("prompt"))
|
|
||||||
m.Options("on_scroll", false)
|
|
||||||
|
|
||||||
case "print":
|
|
||||||
list := kit.Format(args...)
|
|
||||||
n := strings.Count(list, "\n") + y - bottom
|
|
||||||
|
|
||||||
for _, v := range list {
|
|
||||||
if x < right {
|
|
||||||
if termbox.SetCell(x, y, v, fg, bg); v > 255 {
|
|
||||||
x++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if x++; v == '\n' || (x >= right && m.Confs("term", "wrap")) {
|
|
||||||
x, y = left, y+1
|
|
||||||
if y >= bottom {
|
|
||||||
if m.Options("on_scroll") {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if n%bottom > 0 {
|
|
||||||
|
|
||||||
nfs.Term(m, "scroll", n%bottom+1)
|
|
||||||
n -= n % bottom
|
|
||||||
x = m.Confi("term", "cursor_x")
|
|
||||||
y = m.Confi("term", "cursor_y")
|
|
||||||
|
|
||||||
} else if n > 0 {
|
|
||||||
|
|
||||||
nfs.Term(m, "scroll", bottom)
|
|
||||||
n -= bottom
|
|
||||||
x = m.Confi("term", "cursor_x")
|
|
||||||
y = m.Confi("term", "cursor_y")
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if x < right {
|
|
||||||
m.Conf("term", "cursor_x", x)
|
|
||||||
m.Conf("term", "cursor_y", y)
|
|
||||||
termbox.SetCursor(x, y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.Options("on_scroll") {
|
|
||||||
x = 0
|
|
||||||
y = y + 1
|
|
||||||
m.Conf("term", "cursor_x", x)
|
|
||||||
m.Conf("term", "cursor_y", y)
|
|
||||||
termbox.SetCursor(x, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
case "color":
|
|
||||||
msg.Conf("term", "bgcolor", kit.Int(args[0])+1)
|
|
||||||
msg.Conf("term", "fgcolor", kit.Int(args[1])+1)
|
|
||||||
nfs.Term(m, "print", args[2:]...)
|
|
||||||
msg.Conf("term", "fgcolor", fg)
|
|
||||||
msg.Conf("term", "bgcolor", bg)
|
|
||||||
|
|
||||||
case "shadow":
|
|
||||||
x := m.Confi("term", "cursor_x")
|
|
||||||
y := m.Confi("term", "cursor_y")
|
|
||||||
nfs.Term(m, "color", args...)
|
|
||||||
nfs.Term(m, "cursor", x, y).Term(m, "flush")
|
|
||||||
}
|
|
||||||
return nfs
|
|
||||||
}
|
|
||||||
func (nfs *NFS) prompt(arg ...interface{}) *NFS {
|
|
||||||
m := nfs.Context.Message()
|
|
||||||
target, _ := m.Optionv("bio.ctx").(*ctx.Context)
|
|
||||||
if target == nil {
|
|
||||||
target = nfs.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
line := fmt.Sprintf("%d[%s]%s> ", m.Capi("ninput"), time.Now().Format("15:04:05"), target.Name)
|
|
||||||
m.Conf("prompt", line)
|
|
||||||
|
|
||||||
line += kit.Format(arg...)
|
|
||||||
if m.Caps("termbox") {
|
|
||||||
m.Conf("term", "prompt_y", m.Conf("term", "cursor_y"))
|
|
||||||
nfs.Term(m, "clear").Term(m, "print", line).Term(m, "flush")
|
|
||||||
} else if nfs.out != nil {
|
|
||||||
nfs.out.WriteString(line)
|
|
||||||
}
|
|
||||||
return nfs
|
|
||||||
}
|
|
||||||
func (nfs *NFS) shadow(args ...interface{}) *NFS {
|
|
||||||
if len(args) == 0 {
|
|
||||||
return nfs
|
|
||||||
}
|
|
||||||
|
|
||||||
m := nfs.Context.Message()
|
|
||||||
x := m.Confi("term", "cursor_x")
|
|
||||||
y := m.Confi("term", "cursor_y")
|
|
||||||
defer func() { nfs.Term(m, "cursor", x, y).Term(m, "flush") }()
|
|
||||||
|
|
||||||
switch arg := args[0].(type) {
|
|
||||||
case []rune:
|
|
||||||
if len(args) == 1 {
|
|
||||||
nfs.Term(m, "color", m.Confi("term", "rest_bg"), m.Confi("term", "rest_fg"), string(arg))
|
|
||||||
} else {
|
|
||||||
cmd := strings.Split(string(arg), " ")
|
|
||||||
switch table := args[1].(type) {
|
|
||||||
case []map[string]string:
|
|
||||||
frame := args[2].(map[string]interface{})
|
|
||||||
field := kit.Format(frame["field"])
|
|
||||||
fg := kit.Int(frame["color"])
|
|
||||||
pick := kit.Int(kit.Select("0", args, 3))
|
|
||||||
|
|
||||||
i := 0
|
|
||||||
for _, line := range table {
|
|
||||||
if strings.Contains(kit.Format(line[field]), cmd[0]) {
|
|
||||||
if i == pick {
|
|
||||||
frame["pick"] = line[field]
|
|
||||||
nfs.Term(m, "color", m.Confi("term", "pick_bg"), m.Confi("term", "pick_fg"), "\n", kit.Format(line["format"]))
|
|
||||||
} else {
|
|
||||||
nfs.Term(m, "color", 0, fg, "\n", kit.Format(line["format"]))
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
if i > 10 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
frame["lines"] = i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return nfs
|
|
||||||
}
|
|
||||||
func (nfs *NFS) print(arg ...string) *NFS {
|
|
||||||
m := nfs.Context.Message()
|
|
||||||
|
|
||||||
line := strings.TrimRight(strings.Join(arg, ""), "\n")
|
|
||||||
m.Log("debug", "noutput %s", m.Cap("noutput", m.Capi("noutput")+1))
|
|
||||||
m.Confv("output", -2, map[string]interface{}{"time": time.Now().Unix(), "line": line})
|
|
||||||
|
|
||||||
if m.Caps("termbox") {
|
|
||||||
nfs.Term(m, "clear").Term(m, "print", line).Term(m, "flush")
|
|
||||||
m.Conf("term", "prompt_y", m.Confi("term", "cursor_y")+1)
|
|
||||||
m.Conf("term", "cursor_y", m.Confi("term", "cursor_y")+1)
|
|
||||||
} else {
|
|
||||||
nfs.out.WriteString(line)
|
|
||||||
nfs.out.WriteString("\n")
|
|
||||||
}
|
|
||||||
return nfs
|
|
||||||
}
|
|
||||||
func (nfs *NFS) Show(arg ...interface{}) bool {
|
|
||||||
nfs.prompt(arg...)
|
|
||||||
return true
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,309 +0,0 @@
|
|||||||
package tcp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/ctx"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"crypto/tls"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type TCP struct {
|
|
||||||
net.Conn
|
|
||||||
net.Listener
|
|
||||||
*ctx.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tcp *TCP) parse(m *ctx.Message, arg ...string) ([]string, []string, bool) {
|
|
||||||
defer func() {
|
|
||||||
if e := recover(); e != nil {
|
|
||||||
m.Log("warn", "%v", e)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
address := []string{}
|
|
||||||
if arg[1] == "dev" {
|
|
||||||
m.Cmd("web.get", arg[1], arg[2], "temp", "ports", "format", "object", "temp_expire", "10").Table(func(line map[string]string) {
|
|
||||||
address = append(address, line["value"])
|
|
||||||
})
|
|
||||||
if len(address) == 0 {
|
|
||||||
return nil, nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 2; i < len(arg)-1; i++ {
|
|
||||||
arg[i] = arg[i+1]
|
|
||||||
}
|
|
||||||
if len(arg) > 2 {
|
|
||||||
arg = arg[:len(arg)-1]
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
address = append(address, m.Cap("address", m.Confx("address", arg, 1)))
|
|
||||||
}
|
|
||||||
return address, arg, true
|
|
||||||
}
|
|
||||||
func (tcp *TCP) retry(m *ctx.Message, address []string, action func(address string) (net.Conn, error)) net.Conn {
|
|
||||||
var count int32
|
|
||||||
cs := make(chan net.Conn)
|
|
||||||
|
|
||||||
for i := 0; i < m.Confi("retry", "counts"); i++ {
|
|
||||||
for _, p := range address {
|
|
||||||
m.Gos(m.Spawn().Add("option", "address", p), func(msg *ctx.Message) {
|
|
||||||
m.Log("info", "dial: %v", msg.Option("address"))
|
|
||||||
if count >= 1 {
|
|
||||||
msg.Log("info", "skip: %v", msg.Option("address"))
|
|
||||||
} else if c, e := action(msg.Option("address")); e != nil {
|
|
||||||
msg.Log("info", "%s", e)
|
|
||||||
} else if atomic.AddInt32(&count, 1) > 1 {
|
|
||||||
msg.Log("info", "close: %s", c.LocalAddr())
|
|
||||||
c.Close()
|
|
||||||
} else {
|
|
||||||
cs <- c
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
case c := <-cs:
|
|
||||||
return c
|
|
||||||
|
|
||||||
case <-time.After(kit.Duration(m.Conf("retry", "interval"))):
|
|
||||||
m.Log("info", "dial %s:%v timeout", m.Cap("protocol"), address)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (tcp *TCP) Read(b []byte) (n int, e error) {
|
|
||||||
if m := tcp.Context.Message(); m.Assert(tcp.Conn != nil) {
|
|
||||||
if n, e = tcp.Conn.Read(b); e == io.EOF || m.Assert(e) {
|
|
||||||
m.Capi("nrecv", n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
func (tcp *TCP) Write(b []byte) (n int, e error) {
|
|
||||||
if m := tcp.Context.Message(); m.Assert(tcp.Conn != nil) {
|
|
||||||
if n, e = tcp.Conn.Write(b); e == io.EOF || m.Assert(e) {
|
|
||||||
m.Capi("nsend", n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tcp *TCP) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server {
|
|
||||||
c.Caches = map[string]*ctx.Cache{
|
|
||||||
"protocol": &ctx.Cache{Name: "protocol(tcp/tcp4/tcp6)", Value: "", Help: "网络协议"},
|
|
||||||
"security": &ctx.Cache{Name: "security(true/false)", Value: "", Help: "加密通信"},
|
|
||||||
"address": &ctx.Cache{Name: "address", Value: "", Help: "网络地址"},
|
|
||||||
"nrecv": &ctx.Cache{Name: "nrecv", Value: "0", Help: "接收字节数"},
|
|
||||||
"nsend": &ctx.Cache{Name: "nsend", Value: "0", Help: "发送字节数"},
|
|
||||||
}
|
|
||||||
return &TCP{Context: c}
|
|
||||||
}
|
|
||||||
func (tcp *TCP) Begin(m *ctx.Message, arg ...string) ctx.Server {
|
|
||||||
return tcp
|
|
||||||
}
|
|
||||||
func (tcp *TCP) Start(m *ctx.Message, arg ...string) bool {
|
|
||||||
address, arg, ok := tcp.parse(m, arg...)
|
|
||||||
if len(address) == 0 || !ok {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
m.Cap("security", m.Confx("security", arg, 2))
|
|
||||||
m.Cap("protocol", m.Confx("protocol", arg, 3))
|
|
||||||
|
|
||||||
switch arg[0] {
|
|
||||||
case "dial":
|
|
||||||
if m.Caps("security") {
|
|
||||||
cert, e := tls.LoadX509KeyPair(m.Cap("certfile"), m.Cap("keyfile"))
|
|
||||||
m.Assert(e)
|
|
||||||
conf := &tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true}
|
|
||||||
|
|
||||||
tcp.Conn = tcp.retry(m, address, func(p string) (net.Conn, error) {
|
|
||||||
return tls.Dial(m.Cap("protocol"), p, conf)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
tcp.Conn = tcp.retry(m, address, func(p string) (net.Conn, error) {
|
|
||||||
return net.DialTimeout(m.Cap("protocol"), p, kit.Duration(m.Conf("retry", "timeout")))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Log("info", "%s connect %s", m.Cap("nclient"),
|
|
||||||
m.Cap("stream", fmt.Sprintf("%s->%s", tcp.LocalAddr(), m.Cap("address", tcp.RemoteAddr().String()))))
|
|
||||||
|
|
||||||
m.Sess("tcp", m)
|
|
||||||
m.Option("ms_source", tcp.Context.Name)
|
|
||||||
m.Put("option", "io", tcp).Back()
|
|
||||||
return false
|
|
||||||
|
|
||||||
case "accept":
|
|
||||||
c, e := m.Optionv("io").(net.Conn)
|
|
||||||
m.Assert(e)
|
|
||||||
tcp.Conn = c
|
|
||||||
|
|
||||||
m.Log("info", "%s accept %s", m.Cap("nclient"),
|
|
||||||
m.Cap("stream", fmt.Sprintf("%s<-%s", tcp.LocalAddr(), tcp.RemoteAddr())))
|
|
||||||
|
|
||||||
m.Sess("tcp", m)
|
|
||||||
m.Option("ms_source", tcp.Context.Name)
|
|
||||||
m.Put("option", "io", tcp).Back()
|
|
||||||
return false
|
|
||||||
|
|
||||||
case "listen":
|
|
||||||
if m.Caps("security") {
|
|
||||||
m.Sess("aaa", m.Sess("aaa").Cmd("login", "cert", m.Cap("certfile"), "key", m.Cap("keyfile"), "tcp"))
|
|
||||||
cert, e := tls.LoadX509KeyPair(m.Cap("certfile"), m.Cap("keyfile"))
|
|
||||||
m.Assert(e)
|
|
||||||
conf := &tls.Config{Certificates: []tls.Certificate{cert}}
|
|
||||||
|
|
||||||
l, e := tls.Listen(m.Cap("protocol"), m.Cap("address"), conf)
|
|
||||||
m.Assert(e)
|
|
||||||
tcp.Listener = l
|
|
||||||
} else {
|
|
||||||
l, e := net.Listen(m.Cap("protocol"), m.Cap("address"))
|
|
||||||
m.Assert(e)
|
|
||||||
tcp.Listener = l
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Log("info", "%d listen %v", m.Capi("nlisten"), m.Cap("stream", fmt.Sprintf("%s", tcp.Addr())))
|
|
||||||
|
|
||||||
addr := strings.Split(tcp.Addr().String(), ":")
|
|
||||||
ports := []interface{}{}
|
|
||||||
if m.Cmd("tcp.ifconfig").Table(func(line map[string]string) {
|
|
||||||
ports = append(ports, fmt.Sprintf("%s:%s", line["ip"], addr[len(addr)-1]))
|
|
||||||
}); len(ports) == 0 {
|
|
||||||
ports = append(ports, fmt.Sprintf("%s:%s", "127.0.0.1", addr[len(addr)-1]))
|
|
||||||
}
|
|
||||||
m.Back(m.Spawn(m.Source()).Put("option", "node.port", ports))
|
|
||||||
default:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
if c, e := tcp.Accept(); m.Assert(e) {
|
|
||||||
m.Spawn(Index).Put("option", "io", c).Call(func(sub *ctx.Message) *ctx.Message {
|
|
||||||
return sub.Spawn(m.Source())
|
|
||||||
}, "accept", c.RemoteAddr().String(), m.Cap("security"), m.Cap("protocol"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
func (tcp *TCP) Close(m *ctx.Message, arg ...string) bool {
|
|
||||||
switch tcp.Context {
|
|
||||||
case m.Target():
|
|
||||||
if tcp.Listener != nil {
|
|
||||||
m.Log("info", " close %v", m.Cap("stream"))
|
|
||||||
tcp.Listener.Close()
|
|
||||||
tcp.Listener = nil
|
|
||||||
}
|
|
||||||
if tcp.Conn != nil {
|
|
||||||
m.Log("info", " close %v", m.Cap("stream"))
|
|
||||||
tcp.Conn.Close()
|
|
||||||
tcp.Conn = nil
|
|
||||||
}
|
|
||||||
case m.Source():
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "tcp", Help: "网络中心",
|
|
||||||
Caches: map[string]*ctx.Cache{
|
|
||||||
"nlisten": &ctx.Cache{Name: "nlisten", Value: "0", Help: "监听数量"},
|
|
||||||
"nclient": &ctx.Cache{Name: "nclient", Value: "0", Help: "连接数量"},
|
|
||||||
},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"address": &ctx.Config{Name: "address", Value: ":9090", Help: "网络地址"},
|
|
||||||
"security": &ctx.Config{Name: "security(true/false)", Value: "false", Help: "加密通信"},
|
|
||||||
"protocol": &ctx.Config{Name: "protocol(tcp/tcp4/tcp6)", Value: "tcp4", Help: "网络协议"},
|
|
||||||
"retry": &ctx.Config{Name: "retry", Value: map[string]interface{}{
|
|
||||||
"interval": "3s", "counts": 3, "timeout": "10s",
|
|
||||||
}, Help: "网络重试"},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"listen": &ctx.Command{Name: "listen address [security [protocol]]", Help: "网络监听", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Start(fmt.Sprintf("pub%d", m.Capi("nlisten", 1)), "网络监听", m.Meta["detail"]...)
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"accept": &ctx.Command{Name: "accept address [security [protocol]]", Help: "网络连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Start(fmt.Sprintf("sub%d", m.Capi("nclient", 1)), "网络连接", m.Meta["detail"]...)
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"dial": &ctx.Command{Name: "dial address [security [protocol]]", Help: "网络连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Start(fmt.Sprintf("com%d", m.Capi("nclient", 1)), "网络连接", m.Meta["detail"]...)
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
|
|
||||||
"send": &ctx.Command{Name: "send message", Help: "发送消息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if tcp, ok := m.Target().Server.(*TCP); m.Assert(ok) {
|
|
||||||
fmt.Fprint(tcp, arg[0])
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"recv": &ctx.Command{Name: "recv size", Help: "接收消息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if tcp, ok := m.Target().Server.(*TCP); m.Assert(ok) {
|
|
||||||
if n, e := strconv.Atoi(arg[0]); m.Assert(e) {
|
|
||||||
buf := make([]byte, n)
|
|
||||||
n, _ = tcp.Read(buf)
|
|
||||||
m.Echo(string(buf[:n]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
|
|
||||||
"ifconfig": &ctx.Command{Name: "ifconfig [name]", Help: "网络配置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if ifs, e := net.Interfaces(); m.Assert(e) {
|
|
||||||
for _, v := range ifs {
|
|
||||||
if len(arg) > 0 && !strings.Contains(v.Name, arg[0]) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if ips, e := v.Addrs(); m.Assert(e) {
|
|
||||||
for _, x := range ips {
|
|
||||||
ip := strings.Split(x.String(), "/")
|
|
||||||
if strings.Contains(ip[0], ":") || len(ip) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if len(v.HardwareAddr.String()) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Push("index", v.Index)
|
|
||||||
m.Push("name", v.Name)
|
|
||||||
m.Push("ip", ip[0])
|
|
||||||
m.Push("mask", ip[1])
|
|
||||||
m.Push("hard", v.HardwareAddr.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Table()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"probe": &ctx.Command{Name: "probe [port]", Help: "端口检测", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if len(arg) == 0 {
|
|
||||||
for i := 0; i < 1024; i++ {
|
|
||||||
m.Show("port: %v", i)
|
|
||||||
if t, e := net.DialTimeout("tcp", fmt.Sprintf(":%d", i), 3*time.Second); e == nil {
|
|
||||||
m.Push("port", i)
|
|
||||||
t.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Table()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if t, e := net.DialTimeout("tcp", arg[0], 10*time.Second); e == nil {
|
|
||||||
m.Echo("active")
|
|
||||||
t.Close()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ctx.Index.Register(Index, &TCP{Context: Index})
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
package web
|
|
||||||
|
|
||||||
import (
|
|
||||||
// "github.com/PuerkitoBio/goquery"
|
|
||||||
)
|
|
||||||
|
|
||||||
func parseHTML() {
|
|
||||||
/*
|
|
||||||
page, e := goquery.NewDocumentFromReader(res.Body)
|
|
||||||
m.Assert(e)
|
|
||||||
|
|
||||||
page.Find(kit.Select("html", m.Option("parse_chain"))).Each(func(n int, s *goquery.Selection) {
|
|
||||||
if m.Options("parse_select") {
|
|
||||||
for i := 0; i < len(m.Meta["parse_select"])-2; i += 3 {
|
|
||||||
item := s.Find(m.Meta["parse_select"][i+1])
|
|
||||||
if m.Meta["parse_select"][i+1] == "" {
|
|
||||||
item = s
|
|
||||||
}
|
|
||||||
if v, ok := item.Attr(m.Meta["parse_select"][i+2]); ok {
|
|
||||||
m.Add("append", m.Meta["parse_select"][i], v)
|
|
||||||
m.Log("info", "item attr %v", v)
|
|
||||||
} else {
|
|
||||||
m.Add("append", m.Meta["parse_select"][i], strings.Replace(item.Text(), "\n", "", -1))
|
|
||||||
m.Log("info", "item text %v", item.Text())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
s.Find("a").Each(func(n int, s *goquery.Selection) {
|
|
||||||
if attr, ok := s.Attr("href"); ok {
|
|
||||||
s.SetAttr("href", proxy(m, attr))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
s.Find("img").Each(func(n int, s *goquery.Selection) {
|
|
||||||
if attr, ok := s.Attr("src"); ok {
|
|
||||||
s.SetAttr("src", proxy(m, attr))
|
|
||||||
}
|
|
||||||
if attr, ok := s.Attr("r-lazyload"); ok {
|
|
||||||
s.SetAttr("src", proxy(m, attr))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
s.Find("script").Each(func(n int, s *goquery.Selection) {
|
|
||||||
if attr, ok := s.Attr("src"); ok {
|
|
||||||
s.SetAttr("src", proxy(m, attr))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if html, e := s.Html(); e == nil {
|
|
||||||
m.Add("append", "html", html)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
m.Table()
|
|
||||||
|
|
||||||
*/
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,617 +0,0 @@
|
|||||||
package chat
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/ctx"
|
|
||||||
"contexts/web"
|
|
||||||
mis "github.com/shylinux/toolkits"
|
|
||||||
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"strings"
|
|
||||||
"toolkit"
|
|
||||||
)
|
|
||||||
|
|
||||||
func check(m *ctx.Message, arg []string) ([]string, string, bool) {
|
|
||||||
if !m.Options("sessid") || !m.Options("username") {
|
|
||||||
return nil, "", false
|
|
||||||
}
|
|
||||||
|
|
||||||
rid := m.Option("river")
|
|
||||||
if len(arg[0]) != 32 {
|
|
||||||
arg[0] = m.Cmdx("aaa.short", arg[0])
|
|
||||||
}
|
|
||||||
if m.Confs("flow", arg[0]) {
|
|
||||||
rid, arg = arg[0], arg[1:]
|
|
||||||
}
|
|
||||||
if rid != "" && len(rid) != 32 {
|
|
||||||
rid = m.Cmdx("aaa.short", rid)
|
|
||||||
}
|
|
||||||
return arg, rid, true
|
|
||||||
}
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "chat", Help: "会议中心",
|
|
||||||
Caches: map[string]*ctx.Cache{},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"login": &ctx.Config{Name: "login", Value: map[string]interface{}{"check": false, "local": true, "expire": "720h"}, Help: "用户登录"},
|
|
||||||
"componet": &ctx.Config{Name: "componet", Value: map[string]interface{}{
|
|
||||||
"index": []interface{}{
|
|
||||||
map[string]interface{}{"name": "head",
|
|
||||||
"tmpl": "head", "metas": []interface{}{map[string]interface{}{
|
|
||||||
"name": "viewport", "content": "width=device-width, initial-scale=0.7, user-scalable=no",
|
|
||||||
}}, "favicon": "favicon.ico", "styles": []interface{}{
|
|
||||||
// "example.css", "chat.css",
|
|
||||||
"can_style.css",
|
|
||||||
}},
|
|
||||||
map[string]interface{}{"name": "toast",
|
|
||||||
"tmpl": "fieldset", "view": "Toast dialog", "init": "initToast",
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "carte",
|
|
||||||
"tmpl": "fieldset", "view": "Carte dialog", "init": "initCarte",
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "debug",
|
|
||||||
"tmpl": "fieldset", "view": "Debug dialog", "init": "initDebug",
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "favor",
|
|
||||||
"tmpl": "fieldset", "view": "Favor dialog", "init": "initFavor",
|
|
||||||
"ctx": "web.chat", "cmd": "favor",
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "tutor",
|
|
||||||
"tmpl": "fieldset", "view": "Tutor dialog", "init": "initTutor",
|
|
||||||
"ctx": "web.chat", "cmd": "tutor",
|
|
||||||
},
|
|
||||||
|
|
||||||
map[string]interface{}{"name": "login",
|
|
||||||
"tmpl": "fieldset", "view": "Login dialog", "init": "initLogin",
|
|
||||||
"ctx": "web.chat", "cmd": "login",
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "header",
|
|
||||||
"tmpl": "fieldset", "view": "Header", "init": "initHeader",
|
|
||||||
"ctx": "web.chat", "cmd": "login",
|
|
||||||
},
|
|
||||||
|
|
||||||
map[string]interface{}{"name": "ocean",
|
|
||||||
"tmpl": "fieldset", "view": "Ocean dialog", "init": "initOcean",
|
|
||||||
"ctx": "web.chat", "cmd": "ocean",
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "steam",
|
|
||||||
"tmpl": "fieldset", "view": "Steam dialog", "init": "initSteam",
|
|
||||||
"ctx": "web.chat", "cmd": "steam",
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "river",
|
|
||||||
"tmpl": "fieldset", "view": "River", "init": "initRiver",
|
|
||||||
"ctx": "web.chat", "cmd": "river",
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "storm",
|
|
||||||
"tmpl": "fieldset", "view": "Storm", "init": "initStorm",
|
|
||||||
"ctx": "web.chat", "cmd": "storm",
|
|
||||||
},
|
|
||||||
|
|
||||||
map[string]interface{}{"name": "target",
|
|
||||||
"tmpl": "fieldset", "view": "Target", "init": "initTarget",
|
|
||||||
"ctx": "web.chat", "cmd": "river",
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "source",
|
|
||||||
"tmpl": "fieldset", "view": "Source", "init": "initSource",
|
|
||||||
"ctx": "web.chat", "cmd": "storm",
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "action",
|
|
||||||
"tmpl": "fieldset", "view": "Action", "init": "initAction",
|
|
||||||
"ctx": "web.chat", "cmd": "storm",
|
|
||||||
},
|
|
||||||
|
|
||||||
map[string]interface{}{"name": "footer",
|
|
||||||
"tmpl": "fieldset", "view": "Footer", "init": "initFooter",
|
|
||||||
"ctx": "web.chat", "cmd": "login",
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "tail",
|
|
||||||
"tmpl": "tail", "scripts": []interface{}{
|
|
||||||
// "toolkit.js", "context.js", "example.js", "chat.js",
|
|
||||||
"can_proto.js", "can_order.js", "can_frame.js",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, Help: "组件列表"},
|
|
||||||
"share": &ctx.Config{Name: "share", Value: map[string]interface{}{
|
|
||||||
"meta": map[string]interface{}{
|
|
||||||
"fields": "id time share type code remote_ip",
|
|
||||||
"store": "var/tmp/share.csv",
|
|
||||||
"limit": 30, "least": 10,
|
|
||||||
},
|
|
||||||
"hash": map[string]interface{}{},
|
|
||||||
"list": []interface{}{},
|
|
||||||
}, Help: "共享链接"},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"login": &ctx.Command{Name: "login [username password]", Help: "登录", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if len(arg) > 0 {
|
|
||||||
switch arg[0] {
|
|
||||||
case "weixin":
|
|
||||||
if msg := m.Find("cli.weixin", true); msg != nil {
|
|
||||||
msg.Cmd("js_token")
|
|
||||||
m.Copy(msg, "append")
|
|
||||||
m.Append("remote_ip", m.Option("remote_ip"))
|
|
||||||
m.Append("nickname", kit.Select(m.Option("username"), m.Option("nickname")))
|
|
||||||
m.Table()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 非登录态
|
|
||||||
if !m.Options("sessid") || !m.Options("username") {
|
|
||||||
if len(arg) > 0 {
|
|
||||||
// 用户登录
|
|
||||||
if m.Cmds("ssh.work", "share", arg[0]) {
|
|
||||||
if m.Cmds("aaa.auth", "username", arg[0], "password", arg[1]) {
|
|
||||||
m.Option("username", arg[0])
|
|
||||||
m.Option("sessid", m.Cmdx("aaa.user", "session", "select"))
|
|
||||||
if !m.Cmds("aaa.auth", "username", arg[0], "data", "chat.default") && m.Option("username") != m.Conf("runtime", "work.name") {
|
|
||||||
m.Cmd("aaa.auth", "username", arg[0], "data", "chat.default",
|
|
||||||
m.Cmdx(".ocean", "spawn", "", m.Option("username")+"@"+m.Conf("runtime", "work.name"), m.Option("username")))
|
|
||||||
}
|
|
||||||
r := m.Optionv("request").(*http.Request)
|
|
||||||
w := m.Optionv("response").(http.ResponseWriter)
|
|
||||||
|
|
||||||
web.Cookie(m, w, r)
|
|
||||||
m.Echo(m.Option("sessid"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(arg) > 0 {
|
|
||||||
switch arg[0] {
|
|
||||||
case "share":
|
|
||||||
m.Append("qrcode", arg[1])
|
|
||||||
return
|
|
||||||
case "relay":
|
|
||||||
relay := m.Cmdx("aaa.relay", "share", arg[1:])
|
|
||||||
m.Log("info", "relay: %s", relay)
|
|
||||||
m.Echo(m.Cmdx("aaa.short", relay))
|
|
||||||
return
|
|
||||||
case "rename":
|
|
||||||
m.Cmd("aaa.auth", "username", m.Option("username"), "data", "nickname", arg[1])
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if m.Log("info", "nickname: %s", m.Option("nickname", m.Cmdx("aaa.auth", "username", m.Option("username"), "data", "nickname"))); !m.Options("nickname") {
|
|
||||||
// m.Option("nickname", m.Option("username"))
|
|
||||||
// }
|
|
||||||
m.Append("remote_ip", m.Option("remote_ip"))
|
|
||||||
m.Append("nickname", kit.Select(m.Option("username"), m.Option("nickname")))
|
|
||||||
m.Echo(m.Option("username"))
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"ocean": &ctx.Command{Name: "ocean [search [name]]|[spawn hash name user...]", Help: "海洋, search [name]: 搜索员工, spawn hash name user...: 创建群聊", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
// 登录失败
|
|
||||||
if !m.Options("sessid") || !m.Options("username") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(arg) == 0 {
|
|
||||||
arg = append(arg, "search")
|
|
||||||
}
|
|
||||||
|
|
||||||
switch arg[0] {
|
|
||||||
// 搜索员工
|
|
||||||
case "search":
|
|
||||||
m.Cmdy("ssh.work", "search")
|
|
||||||
|
|
||||||
// 创建群聊
|
|
||||||
case "spawn":
|
|
||||||
// 用户列表
|
|
||||||
user := map[string]interface{}{}
|
|
||||||
if len(arg) > 3 {
|
|
||||||
arg = append(arg, m.Option("username"))
|
|
||||||
arg = append(arg, m.Conf("runtime", "work.name"))
|
|
||||||
for _, v := range arg[3:] {
|
|
||||||
if p := m.Cmdx("ssh._route", m.Conf("runtime", "work.route"), "_check", "work", v); p != "" {
|
|
||||||
user[v] = map[string]interface{}{"user": p}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加群聊
|
|
||||||
h := kit.Select(kit.Hashs("uniq"), arg, 1)
|
|
||||||
m.Conf("flow", h, map[string]interface{}{
|
|
||||||
"conf": map[string]interface{}{
|
|
||||||
"create_user": m.Option("username"),
|
|
||||||
"create_time": m.Time(),
|
|
||||||
"update_time": m.Time(),
|
|
||||||
"nick": kit.Select("what", arg, 2),
|
|
||||||
"route": kit.Select(m.Conf("runtime", "node.route"), m.Option("node.route"), arg[1] != ""),
|
|
||||||
},
|
|
||||||
"user": user,
|
|
||||||
"tool": map[string]interface{}{},
|
|
||||||
"text": map[string]interface{}{},
|
|
||||||
})
|
|
||||||
|
|
||||||
if m.Echo(h); arg[1] != "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Cmdx(".steam", h, "spawn", "index")
|
|
||||||
|
|
||||||
// 分发群聊
|
|
||||||
m.Confm("flow", []string{h, "user"}, func(key string, value map[string]interface{}) {
|
|
||||||
if kit.Right(value["user"]) && kit.Format(value["user"]) != m.Conf("runtime", "node.route") {
|
|
||||||
m.Cmd("ssh._route", value["user"], "context", "chat", "ocean", "spawn", h, arg[2])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"river": &ctx.Command{Name: "river hash [brow begin]|[flow type text [index]]|[wave route group index args...]", Help: "河流", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
// 登录失败
|
|
||||||
if !m.Options("sessid") || !m.Options("username") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 自动入群
|
|
||||||
if m.Options("river") {
|
|
||||||
if m.Short("river"); m.Confs("flow", m.Option("river")) && !m.Confs("flow", []string{m.Option("river"), "user", m.Option("username")}) {
|
|
||||||
u := m.Cmdx("ssh._route", m.Conf("runtime", "work.route"), "_check", "work", m.Option("username"))
|
|
||||||
m.Conf("flow", []string{m.Option("river"), "user", m.Option("username"), "user"}, u)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 群聊列表
|
|
||||||
if len(arg) == 0 {
|
|
||||||
m.Confm("flow", func(key string, value map[string]interface{}) {
|
|
||||||
if kit.Chain(value, []string{"user", m.Option("username")}) == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Push("key", m.Cmdx("aaa.short", key))
|
|
||||||
m.Push("nick", kit.Chains(value, "conf.nick"))
|
|
||||||
m.Push("create_user", kit.Chains(value, "conf.create_user"))
|
|
||||||
m.Push("create_time", kit.Chains(value, "conf.create_time"))
|
|
||||||
m.Push("update_time", kit.Chains(value, "conf.update_time"))
|
|
||||||
|
|
||||||
if list, ok := kit.Chain(value, "text.list").([]interface{}); ok {
|
|
||||||
m.Push("count", len(list))
|
|
||||||
} else {
|
|
||||||
m.Push("count", 0)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if !m.Appends("key") {
|
|
||||||
m.Cmd(".ocean", "spawn", "", "hello", m.Option("username"))
|
|
||||||
m.Cmdy(".river")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
m.Sort("name").Sort("update_time", "time_r").Table()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 登录失败
|
|
||||||
arg, rid, ok := check(m, arg)
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch arg[0] {
|
|
||||||
// 消息列表
|
|
||||||
case "brow":
|
|
||||||
begin := kit.Int(kit.Select("0", arg, 1))
|
|
||||||
m.Confm("flow", []string{rid, "text.list"}, func(index int, value map[string]interface{}) {
|
|
||||||
if index < begin {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
m.Push("index", index)
|
|
||||||
m.Push("type", value["type"])
|
|
||||||
m.Push("text", value["text"])
|
|
||||||
m.Push("create_time", value["create_time"])
|
|
||||||
m.Push("create_user", value["create_user"])
|
|
||||||
m.Push("create_nick", value["create_nick"])
|
|
||||||
})
|
|
||||||
m.Table()
|
|
||||||
return
|
|
||||||
|
|
||||||
// 推送消息
|
|
||||||
case "flow":
|
|
||||||
up := m.Conf("flow", []string{rid, "conf.route"})
|
|
||||||
|
|
||||||
// 上传消息
|
|
||||||
if len(arg) == 3 && up != m.Conf("runtime", "node.route") {
|
|
||||||
m.Cmdy("ssh._route", up, "context", "chat", "river", rid, "flow", arg[1], arg[2])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存消息
|
|
||||||
m.Conf("flow", []string{rid, "text.list.-2"}, map[string]interface{}{
|
|
||||||
"create_nick": m.Option("nickname"),
|
|
||||||
"create_user": m.Option("username"),
|
|
||||||
"create_time": m.Time(),
|
|
||||||
"type": arg[1],
|
|
||||||
"text": arg[2],
|
|
||||||
})
|
|
||||||
m.Conf("flow", []string{rid, "conf.update_time"}, m.Time())
|
|
||||||
count := m.Confi("flow", []string{rid, "text.count"}) + 1
|
|
||||||
m.Confi("flow", []string{rid, "text.count"}, count)
|
|
||||||
|
|
||||||
m.Append("create_user", m.Option("username"))
|
|
||||||
m.Echo("%d", count)
|
|
||||||
|
|
||||||
// 分发消息
|
|
||||||
if up == m.Conf("runtime", "node.route") {
|
|
||||||
m.Confm("flow", []string{rid, "user"}, func(key string, value map[string]interface{}) {
|
|
||||||
if kit.Right(value["user"]) && kit.Format(value["user"]) != m.Conf("runtime", "node.route") {
|
|
||||||
m.Cmd("ssh._route", value["user"], "context", "chat", "river", rid, "flow", arg[1], arg[2], count, "sync")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 推送命令
|
|
||||||
case "wave":
|
|
||||||
m.Cmdy("ssh._route", arg[1], "tool", "run", arg[2], arg[3], rid, arg[4:])
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"storm": &ctx.Command{Name: "storm rid [[delete] group [index [arg...]]]", Help: "风雨", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
// 登录失败
|
|
||||||
if len(arg[0]) != 32 {
|
|
||||||
arg[0] = m.Cmdx("aaa.short", arg[0])
|
|
||||||
}
|
|
||||||
rid, arg := arg[0], arg[1:]
|
|
||||||
|
|
||||||
m.Option("river", rid)
|
|
||||||
// 命令列表
|
|
||||||
if len(arg) == 0 {
|
|
||||||
m.Confm("flow", []string{rid, "tool"}, func(key string, value map[string]interface{}) {
|
|
||||||
m.Push("key", key)
|
|
||||||
m.Push("count", len(value["list"].([]interface{})))
|
|
||||||
m.Push("status", kit.Format(value["status"]))
|
|
||||||
})
|
|
||||||
m.Sort("key").Table()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch arg[0] {
|
|
||||||
// 删除命令
|
|
||||||
case "delete":
|
|
||||||
str := m.Conf("flow", []string{rid, "tool", arg[1]})
|
|
||||||
m.Log("info", "delete %v %v %v", rid, arg[1], str)
|
|
||||||
m.Conf("flow", []string{rid, "tool", arg[1]}, "")
|
|
||||||
m.Echo(str)
|
|
||||||
|
|
||||||
case "clone":
|
|
||||||
args := []string{}
|
|
||||||
m.Confm("flow", []string{rid, "tool", arg[2], "list"}, func(index int, value map[string]interface{}) {
|
|
||||||
args = append(args, kit.Format(value["node"]), kit.Format(value["group"]), kit.Format(value["index"]), kit.Format(value["name"]))
|
|
||||||
})
|
|
||||||
m.Cmdy(".steam", rid, "spawn", arg[1], args)
|
|
||||||
|
|
||||||
arg[2] = m.Conf("flow", []string{rid, "tool", arg[2], "status"})
|
|
||||||
fallthrough
|
|
||||||
case "save":
|
|
||||||
if arg[2] != "" {
|
|
||||||
m.Cmdy("ssh._route", arg[2], "web.chat.storm", rid, arg[:2], "", arg[3:])
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if m.Confv("flow", []string{rid, "tool", arg[1], "status"}, arg[3]); kit.Select("", arg, 4) != "" {
|
|
||||||
m.Confv("flow", []string{rid, "tool", arg[1], "list"}, kit.UnMarshal(arg[4]))
|
|
||||||
}
|
|
||||||
case "load":
|
|
||||||
if len(arg) > 2 {
|
|
||||||
m.Cmdy("ssh._route", arg[2], "web.chat.storm", rid, arg[:2])
|
|
||||||
break
|
|
||||||
}
|
|
||||||
m.Confm("flow", []string{rid, "tool", arg[1]}, func(value map[string]interface{}) {
|
|
||||||
m.Append("status", kit.Format(value["status"]))
|
|
||||||
m.Append("list", kit.Format(value["list"]))
|
|
||||||
})
|
|
||||||
|
|
||||||
default:
|
|
||||||
// 命令列表
|
|
||||||
m.Set("option", "name")
|
|
||||||
m.Set("option", "init")
|
|
||||||
m.Set("option", "view")
|
|
||||||
if len(arg) == 1 {
|
|
||||||
list := m.Confv("flow", []string{rid, "tool", arg[0], "list"})
|
|
||||||
if m.Option("you") != "" {
|
|
||||||
if msg := m.Cmd("ssh._route", m.Option("you"), "web.chat.storm", rid, "load", arg[0]); msg.Appends("list") {
|
|
||||||
list = kit.UnMarshal(msg.Append("list"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
short := m.Cmdx("aaa.short", rid)
|
|
||||||
kit.Map(list, "", func(index int, tool map[string]interface{}) {
|
|
||||||
m.Push("river", short)
|
|
||||||
m.Push("storm", arg[0])
|
|
||||||
m.Push("action", index)
|
|
||||||
|
|
||||||
m.Push("node", tool["node"])
|
|
||||||
m.Push("group", tool["group"])
|
|
||||||
m.Push("index", tool["index"])
|
|
||||||
|
|
||||||
msg := m.Cmd("ssh._route", tool["node"], "tool", tool["group"], tool["index"])
|
|
||||||
|
|
||||||
m.Push("name", msg.Append("name"))
|
|
||||||
m.Push("help", msg.Append("help"))
|
|
||||||
m.Push("view", msg.Append("view"))
|
|
||||||
m.Push("init", msg.Append("init"))
|
|
||||||
m.Push("inputs", msg.Append("inputs"))
|
|
||||||
m.Push("exports", msg.Append("exports"))
|
|
||||||
m.Push("display", msg.Append("display"))
|
|
||||||
m.Push("feature", msg.Append("feature"))
|
|
||||||
})
|
|
||||||
m.Table()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// 推送命令
|
|
||||||
if tool := m.Confm("flow", []string{rid, "tool", arg[0], "list", arg[1]}); tool != nil {
|
|
||||||
m.Cmdy("ssh._route", tool["node"], "tool", "run", tool["group"], tool["index"], rid, arg[2:])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"steam": &ctx.Command{Name: "steam rid [user node]|[spawn name [route group index name]...]", Help: "天空", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
// 登录失败
|
|
||||||
arg, rid, ok := check(m, arg)
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 上传请求
|
|
||||||
if up := m.Conf("flow", []string{rid, "conf.route"}); up != m.Conf("runtime", "node.route") {
|
|
||||||
m.Cmdy("ssh._remote", up, "context", "chat", "steam", rid, arg)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设备列表
|
|
||||||
if len(arg) == 0 {
|
|
||||||
m.Confm("flow", []string{rid, "user"}, func(key string, value map[string]interface{}) {
|
|
||||||
m.Push("user", key)
|
|
||||||
m.Push("node", value["user"])
|
|
||||||
})
|
|
||||||
m.Confm("ssh.node", func(key string, value map[string]interface{}) {
|
|
||||||
m.Push("user", value["type"])
|
|
||||||
m.Push("node", value["name"])
|
|
||||||
})
|
|
||||||
m.Table()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch arg[0] {
|
|
||||||
// 创建命令
|
|
||||||
case "spawn":
|
|
||||||
if len(arg) == 2 {
|
|
||||||
self := m.Conf("runtime", "node.route")
|
|
||||||
m.Confm("ssh.componet", arg[1], func(index int, value map[string]interface{}) {
|
|
||||||
arg = append(arg, self, arg[1], kit.Format(index), kit.Format(value["name"]))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
list := []interface{}{}
|
|
||||||
for i := 2; i < len(arg)-3; i += 4 {
|
|
||||||
list = append(list, map[string]interface{}{
|
|
||||||
"node": arg[i], "group": arg[i+1], "index": arg[i+2], "name": arg[i+3],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Conf("flow", []string{rid, "tool", arg[1]}, map[string]interface{}{
|
|
||||||
"create_user": m.Option("username"),
|
|
||||||
"create_time": m.Time(),
|
|
||||||
"list": list,
|
|
||||||
})
|
|
||||||
|
|
||||||
// 命令列表
|
|
||||||
default:
|
|
||||||
m.Cmdy("ssh._route", arg[1], "tool")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
|
|
||||||
"favor": &ctx.Command{Name: "favor", Help: "命令", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Cmdy(arg)
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"tutor": &ctx.Command{Name: "tutor", Help: "向导", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Cmdy(arg)
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
|
|
||||||
"/share/": &ctx.Command{Name: "/share/", Help: "共享链接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
h := strings.TrimPrefix(key, "/share/")
|
|
||||||
m.Confm("share", []string{"hash", h}, func(value map[string]interface{}) {
|
|
||||||
switch kit.Format(value["type"]) {
|
|
||||||
case "file":
|
|
||||||
// 下载文件
|
|
||||||
m.Cmdy("/download/" + h)
|
|
||||||
|
|
||||||
case "wiki":
|
|
||||||
// 查看文档
|
|
||||||
p := path.Join(path.Join("var/share", h))
|
|
||||||
if !m.Options("force") {
|
|
||||||
if _, e := os.Stat(p); e == nil {
|
|
||||||
// 读取缓存
|
|
||||||
m.Log("info", "read cache %v", p)
|
|
||||||
r := m.Optionv("request").(*http.Request)
|
|
||||||
w := m.Optionv("response").(http.ResponseWriter)
|
|
||||||
http.ServeFile(w, r, p)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Option("title", fmt.Sprintf("%v:%v", value["dream"], value["code"]))
|
|
||||||
m.Option("favicon", "favicon.ico")
|
|
||||||
// 生成模板
|
|
||||||
m.Echo(ctx.Execute(m, "share.tmpl"))
|
|
||||||
|
|
||||||
// 生成文档
|
|
||||||
m.Cmdy("ssh._route", value["dream"], "web.wiki.note", value["code"])
|
|
||||||
if f, _, e := kit.Create(p); e == nil {
|
|
||||||
defer f.Close()
|
|
||||||
for _, v := range m.Meta["result"] {
|
|
||||||
f.WriteString(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 访问记录
|
|
||||||
m.Grow("share", nil, map[string]interface{}{
|
|
||||||
"time": m.Time(),
|
|
||||||
"share": h,
|
|
||||||
"type": value["type"],
|
|
||||||
"code": value["code"],
|
|
||||||
"sid": m.Option("sid"),
|
|
||||||
"agent": m.Option("agent"),
|
|
||||||
"sessid": m.Option("sessid"),
|
|
||||||
"username": m.Option("username"),
|
|
||||||
"remote_ip": m.Option("remote_ip"),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"share": &ctx.Command{Name: "share type code", Help: "共享链接", Hand: func(m *ctx.Message, c *ctx.Context, cmd string, arg ...string) (e error) {
|
|
||||||
if len(arg) > 2 {
|
|
||||||
switch arg[1] {
|
|
||||||
case "delete":
|
|
||||||
// 删除共享
|
|
||||||
switch arg[2] {
|
|
||||||
case "key":
|
|
||||||
m.Log("info", "delete share %v %v", arg[3], mis.Formats(m.Conf("share", "hash."+arg[3])))
|
|
||||||
m.Conf("share", "hash."+arg[3], "")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(arg) < 2 {
|
|
||||||
// 共享列表
|
|
||||||
m.Confm("share", "hash", func(key string, value map[string]interface{}) {
|
|
||||||
m.Push("key", key)
|
|
||||||
m.Push("time", value["time"])
|
|
||||||
m.Push("type", value["type"])
|
|
||||||
m.Push("code", value["code"])
|
|
||||||
m.Push("dream", value["dream"])
|
|
||||||
m.Push("link", fmt.Sprintf("%s/chat/share/%s", m.Cmdx(".spide", "self", "client", "url"), key))
|
|
||||||
})
|
|
||||||
m.Sort("time", "time_r")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 共享链接
|
|
||||||
h := kit.ShortKey(m.Confm(cmd, "hash"), 6)
|
|
||||||
m.Confv(cmd, []string{"hash", h}, map[string]interface{}{
|
|
||||||
"from": m.Option("username"),
|
|
||||||
"time": m.Time(),
|
|
||||||
"type": arg[0],
|
|
||||||
"code": arg[1],
|
|
||||||
"dream": m.Option("you"),
|
|
||||||
})
|
|
||||||
m.Echo("%s/chat/share/%s", m.Cmdx(".spide", "self", "client", "url"), h)
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
web.Index.Register(Index, &web.WEB{Context: Index})
|
|
||||||
}
|
|
@ -1,358 +0,0 @@
|
|||||||
package chat
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/ctx"
|
|
||||||
"contexts/web"
|
|
||||||
"examples/chat"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"encoding/json"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func get(m *ctx.Message, arg ...string) *ctx.Message {
|
|
||||||
m.Option("temp_expire", -1)
|
|
||||||
m.Option("format", "object")
|
|
||||||
m.Cmdy("web.get", "feishu", arg, "temp", "data")
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func post(m *ctx.Message, arg ...string) *ctx.Message {
|
|
||||||
m.Option("temp_expire", -1)
|
|
||||||
m.Option("format", "object")
|
|
||||||
m.Cmdy("web.get", "method", "POST", "feishu", arg,
|
|
||||||
"content_type", "application/json",
|
|
||||||
"temp", "data",
|
|
||||||
)
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func parse(m *ctx.Message) {
|
|
||||||
data := m.Optionv("content_data")
|
|
||||||
if data == nil {
|
|
||||||
json.NewDecoder(m.Optionv("request").(*http.Request).Body).Decode(&data)
|
|
||||||
m.Optionv("content_data", data)
|
|
||||||
|
|
||||||
switch d := data.(type) {
|
|
||||||
case map[string]interface{}:
|
|
||||||
for k, v := range d {
|
|
||||||
switch d := v.(type) {
|
|
||||||
case map[string]interface{}:
|
|
||||||
for k, v := range d {
|
|
||||||
m.Add("option", k, v)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
for _, v := range kit.Trans(v) {
|
|
||||||
m.Add("option", "msg."+k, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if kit.Map(kit.Chain(data, "action.value"), "", func(key string, value string) {
|
|
||||||
m.Add("option", key, value)
|
|
||||||
}) != nil {
|
|
||||||
m.Option("msg.type", "event_click")
|
|
||||||
}
|
|
||||||
m.Log("info", "msg: %v", kit.Formats(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "feishu", Help: "飞书",
|
|
||||||
Caches: map[string]*ctx.Cache{},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"app": &ctx.Config{Name: "app", Value: map[string]interface{}{}, Help: "服务配置"},
|
|
||||||
"user": &ctx.Config{Name: "user", Value: map[string]interface{}{}, Help: "服务配置"},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"app": &ctx.Command{Name: "app login|token bot", Help: "应用", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if len(arg) == 0 {
|
|
||||||
m.Confm("app", func(key string, value map[string]interface{}) {
|
|
||||||
m.Push("key", key)
|
|
||||||
m.Push("id", value["id"])
|
|
||||||
})
|
|
||||||
m.Table()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch arg[0] {
|
|
||||||
case "login":
|
|
||||||
m.Confv("app", arg[1], map[string]interface{}{"id": arg[2], "mm": arg[3]})
|
|
||||||
case "token":
|
|
||||||
if now := time.Now().Unix(); !m.Confs("app", []string{arg[1], "token"}) || int64(m.Confi("app", []string{arg[1], "expire"})) < now {
|
|
||||||
post(m, "auth/v3/tenant_access_token/internal/", "app_id", m.Conf("app", []string{arg[1], "id"}),
|
|
||||||
"app_secret", m.Conf("app", []string{arg[1], "mm"}))
|
|
||||||
m.Conf("app", []string{arg[1], "token"}, m.Append("tenant_access_token"))
|
|
||||||
m.Conf("app", []string{arg[1], "expire"}, int64(m.Appendi("expire"))+now)
|
|
||||||
m.Set("result")
|
|
||||||
}
|
|
||||||
m.Echo(m.Conf("app", []string{arg[1], "token"}))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"ship": &ctx.Command{Name: "ship", Help: "组织", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
data := kit.UnMarshal(m.Cmdx("web.get", "feishu", "contact/v1/scope/get/",
|
|
||||||
"headers", "Authorization", "Bearer "+m.Cmdx(".app", "token", "bot"),
|
|
||||||
))
|
|
||||||
kit.Map(kit.Chain(data, "data.authed_departments"), "", func(index int, value string) {
|
|
||||||
m.Push("type", "ship")
|
|
||||||
m.Push("value", value)
|
|
||||||
})
|
|
||||||
kit.Map(kit.Chain(data, "data.authed_open_ids"), "", func(index int, value string) {
|
|
||||||
m.Push("type", "user")
|
|
||||||
m.Push("value", value)
|
|
||||||
})
|
|
||||||
m.Table()
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"group": &ctx.Command{Name: "group", Help: "群组", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if len(arg) == 0 {
|
|
||||||
kit.Map(kit.Chain(kit.UnMarshal(m.Cmdx("web.get", "feishu", "chat/v4/list", "headers", "Authorization", "Bearer "+m.Cmdx(".app", "token", "bot"))),
|
|
||||||
"data.groups"), "", func(index int, value map[string]interface{}) {
|
|
||||||
m.Push("key", value["chat_id"])
|
|
||||||
m.Push("name", value["name"])
|
|
||||||
m.Push("avatar", value["avatar"])
|
|
||||||
})
|
|
||||||
m.Table()
|
|
||||||
}
|
|
||||||
kit.Map(kit.Chain(kit.UnMarshal(m.Cmdx("web.get", "feishu", "chat/v4/info", "headers", "Authorization", "Bearer "+m.Cmdx(".app", "token", "bot"))),
|
|
||||||
"data.members"), "", func(index int, value map[string]interface{}) {
|
|
||||||
m.Push("key", value["open_id"])
|
|
||||||
})
|
|
||||||
m.Table()
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"user": &ctx.Command{Name: "user code|email|mobile", Help: "用户", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
switch arg[0] {
|
|
||||||
case "code":
|
|
||||||
post(m, "/connect/qrconnect/oauth2/access_token/",
|
|
||||||
"app_secret", m.Conf("app", []string{"bot", "mm"}), "app_id", m.Conf("app", []string{"bot", "id"}),
|
|
||||||
"grant_type", "authorization_code", "code", arg[1],
|
|
||||||
)
|
|
||||||
msg := get(m.Spawn(), "/connect/qrconnect/oauth2/user_info/",
|
|
||||||
"headers", "Authorization", "Bearer "+m.Append("access_token"),
|
|
||||||
)
|
|
||||||
m.Confv("user", m.Append("open_id"), map[string]interface{}{
|
|
||||||
"name": m.Append("name"),
|
|
||||||
"en_name": m.Append("en_name"),
|
|
||||||
"avatar_url": m.Append("avatar_url"),
|
|
||||||
"access_token": m.Append("access_token"),
|
|
||||||
"token_type": m.Append("token_type"),
|
|
||||||
"expire": int64(m.Appendi("expire")) + time.Now().Unix(),
|
|
||||||
"refresh_token": m.Append("refresh_token"),
|
|
||||||
"tenant_key": m.Append("tenant_key"),
|
|
||||||
|
|
||||||
"email": msg.Append("Email"),
|
|
||||||
"mobile": msg.Append("Mobile"),
|
|
||||||
"status": msg.Append("status"),
|
|
||||||
"employee": msg.Append("EmployeeID"),
|
|
||||||
})
|
|
||||||
|
|
||||||
default:
|
|
||||||
us := []string{}
|
|
||||||
ps := []string{}
|
|
||||||
for i := 0; i < len(arg); i++ {
|
|
||||||
us = append(us, kit.Select("mobiles", "emails", strings.Contains(arg[i], "@")), arg[i])
|
|
||||||
ps = append(ps, kit.Select("mobile", "email", strings.Contains(arg[i], "@"))+"_users")
|
|
||||||
}
|
|
||||||
|
|
||||||
data := kit.UnMarshal(m.Cmdx("web.get", "feishu", "user/v1/batch_get_id", us,
|
|
||||||
"headers", "Authorization", "Bearer "+m.Cmdx(".app", "token", "bot")))
|
|
||||||
|
|
||||||
for i, v := range ps {
|
|
||||||
m.Append(arg[i], kit.Chain(data, []string{"data", v, arg[i], "0", "open_id"}))
|
|
||||||
}
|
|
||||||
m.Table()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"send": &ctx.Command{Name: "send [chat_id|open_id|user_id|email] who [menu] [title] text", Help: "消息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
var form = map[string]interface{}{"content": map[string]interface{}{}}
|
|
||||||
switch arg[0] {
|
|
||||||
case "chat_id", "open_id", "user_id", "email":
|
|
||||||
form[arg[0]], arg = arg[1], arg[2:]
|
|
||||||
default:
|
|
||||||
form["chat_id"], arg = arg[0], arg[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
switch arg[0] {
|
|
||||||
case "menu":
|
|
||||||
elements := []interface{}{}
|
|
||||||
elements = append(elements, map[string]interface{}{
|
|
||||||
"tag": "div",
|
|
||||||
"text": map[string]interface{}{
|
|
||||||
"tag": "plain_text",
|
|
||||||
"content": arg[2],
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
actions := []interface{}{}
|
|
||||||
for i := 3; i < len(arg); i++ {
|
|
||||||
button := map[string]interface{}{
|
|
||||||
"tag": "button", "text": map[string]interface{}{
|
|
||||||
"tag": "plain_text", "content": arg[i],
|
|
||||||
},
|
|
||||||
"type": "default",
|
|
||||||
}
|
|
||||||
|
|
||||||
switch arg[i+1] {
|
|
||||||
case "confirm":
|
|
||||||
button[arg[i+1]], i = map[string]interface{}{
|
|
||||||
"title": map[string]interface{}{"tag": "lark_md", "content": arg[i+2]},
|
|
||||||
"text": map[string]interface{}{"tag": "lark_md", "content": arg[i+3]},
|
|
||||||
}, i+3
|
|
||||||
case "value":
|
|
||||||
button[arg[i+1]], i = map[string]interface{}{
|
|
||||||
arg[i+2]: arg[i+3],
|
|
||||||
}, i+3
|
|
||||||
case "url":
|
|
||||||
button[arg[i+1]], i = arg[i+2], i+2
|
|
||||||
default:
|
|
||||||
button["value"], i = map[string]interface{}{
|
|
||||||
arg[i+1]: arg[i+2],
|
|
||||||
}, i+2
|
|
||||||
}
|
|
||||||
|
|
||||||
actions = append(actions, button)
|
|
||||||
}
|
|
||||||
elements = append(elements, map[string]interface{}{
|
|
||||||
"tag": "action", "actions": actions,
|
|
||||||
})
|
|
||||||
|
|
||||||
kit.Chain(form, "msg_type", "interactive")
|
|
||||||
kit.Chain(form, "card", map[string]interface{}{
|
|
||||||
"config": map[string]interface{}{
|
|
||||||
"wide_screen_mode": true,
|
|
||||||
// "title": map[string]interface{}{
|
|
||||||
// "tag": "lark_md", "content": arg[1],
|
|
||||||
// },
|
|
||||||
},
|
|
||||||
"header": map[string]interface{}{
|
|
||||||
"title": map[string]interface{}{
|
|
||||||
"tag": "lark_md", "content": arg[1],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"elements": elements,
|
|
||||||
})
|
|
||||||
default:
|
|
||||||
switch len(arg) {
|
|
||||||
case 0:
|
|
||||||
case 1:
|
|
||||||
kit.Chain(form, "msg_type", "text")
|
|
||||||
kit.Chain(form, "content.text", arg[0])
|
|
||||||
default:
|
|
||||||
content := []interface{}{}
|
|
||||||
line := []interface{}{}
|
|
||||||
for _, v := range arg[1:] {
|
|
||||||
if v == "\n" {
|
|
||||||
content, line = append(content, line), []interface{}{}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
line = append(line, map[string]interface{}{
|
|
||||||
"tag": "text", "text": v,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
content = append(content, line)
|
|
||||||
|
|
||||||
kit.Chain(form, "msg_type", "post")
|
|
||||||
kit.Chain(form, "content.post", map[string]interface{}{
|
|
||||||
"zh_cn": map[string]interface{}{
|
|
||||||
"title": arg[0],
|
|
||||||
"content": content,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Cmdy("web.get", "method", "POST", "feishu", "message/v4/send/",
|
|
||||||
"headers", "Authorization", "Bearer "+m.Cmdx(".app", "token", "bot"),
|
|
||||||
"content_data", kit.Formats(form), "content_type", "application/json",
|
|
||||||
"temp", "data", "data.message_id",
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"/msg": &ctx.Command{Name: "/msg", Help: "消息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
parse(m)
|
|
||||||
|
|
||||||
switch m.Option("msg.type") {
|
|
||||||
case "url_verification":
|
|
||||||
m.Echo(kit.Format(map[string]interface{}{"challenge": m.Option("challenge")}))
|
|
||||||
|
|
||||||
case "event_callback":
|
|
||||||
switch m.Option("type") {
|
|
||||||
case "chat_disband":
|
|
||||||
case "p2p_chat_create":
|
|
||||||
if m.Options("open_chat_id") {
|
|
||||||
m.Cmdy(".send", m.Option("open_chat_id"), "我们做朋友吧~")
|
|
||||||
}
|
|
||||||
case "add_bot":
|
|
||||||
if m.Options("open_chat_id") {
|
|
||||||
m.Cmdy(".send", m.Option("open_chat_id"), "我来也~")
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
if m.Options("open_chat_id") {
|
|
||||||
m.Option("username", m.Option("open_id"))
|
|
||||||
m.Option("sessid", m.Cmdx("aaa.user", "session", "select"))
|
|
||||||
m.Cmd("ssh._check", "work", "create", m.Option("username"))
|
|
||||||
m.Goshy([]string{m.Option("text_without_at_bot")}, 0, nil, func(msg *ctx.Message) {
|
|
||||||
m.Cmdy(".send", m.Option("open_chat_id"), kit.Select("你好", strings.Join(msg.Meta["result"], "")))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case "event_click":
|
|
||||||
m.Echo(kit.Format(map[string]interface{}{
|
|
||||||
"header": map[string]interface{}{
|
|
||||||
"title": map[string]interface{}{
|
|
||||||
"tag": "lark_md", "content": "haha",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"elements": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"tag": "action",
|
|
||||||
"actions": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"tag": "button",
|
|
||||||
"type": "default",
|
|
||||||
"text": map[string]interface{}{
|
|
||||||
"tag": "plain_text",
|
|
||||||
"content": m.Time(),
|
|
||||||
},
|
|
||||||
"value": map[string]interface{}{
|
|
||||||
"hi": "hello",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"/sso": &ctx.Command{Name: "/sso", Help: "消息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if m.Options("code") {
|
|
||||||
m.Option("username", m.Cmd(".user", "code", m.Option("code")).Append("open_id"))
|
|
||||||
m.Option("sessid", m.Cmdx("aaa.user", "session", "select"))
|
|
||||||
m.Cmd("ssh._check", "work", "create", m.Option("username"))
|
|
||||||
|
|
||||||
w := m.Optionv("response").(http.ResponseWriter)
|
|
||||||
r := m.Optionv("request").(*http.Request)
|
|
||||||
web.Cookie(m, w, r)
|
|
||||||
m.Append("redirect", m.Cmdx("web.spide", "serve", "merge", m.Option("index_path")), "code", "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !m.Options("sessid") || !m.Options("username") {
|
|
||||||
m.Append("redirect", m.Cmdx("web.spide", "feishu", "merge", "/connect/qrconnect/page/sso/",
|
|
||||||
"redirect_uri", m.Cmdx("web.spide", "serve", "merge", m.Option("index_path")),
|
|
||||||
"app_id", m.Conf("app", "bot.id"), "state", "ok"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
m.Cmd("/render")
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
chat.Index.Register(Index, &web.WEB{Context: Index})
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,51 +0,0 @@
|
|||||||
package mall
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/ctx"
|
|
||||||
"contexts/web"
|
|
||||||
"toolkit"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "mall", Help: "交易中心",
|
|
||||||
Caches: map[string]*ctx.Cache{},
|
|
||||||
Configs: map[string]*ctx.Config{},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"salary": {Name: "salary table month total base tax", Help: "工资", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if len(arg) < 3 || arg[2] == "" {
|
|
||||||
m.Cmdy("ssh.data", "show", arg[0], "fields", "id", "month",
|
|
||||||
"total", "base", "zhu", "old", "bad", "mis", "tax", "rest")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
total := kit.Int(arg[2])
|
|
||||||
base := kit.Int(kit.Select(arg[2], arg, 3))
|
|
||||||
tax := kit.Int(kit.Select("0", arg, 4))
|
|
||||||
|
|
||||||
zhu := base * 120 / 1000
|
|
||||||
if len(arg) > 5 {
|
|
||||||
zhu = kit.Int(arg[5])
|
|
||||||
}
|
|
||||||
old := base * 80 / 1000
|
|
||||||
if len(arg) > 6 {
|
|
||||||
old = kit.Int(arg[6])
|
|
||||||
}
|
|
||||||
bad := base * 20 / 1000
|
|
||||||
if len(arg) > 7 {
|
|
||||||
bad = kit.Int(arg[7])
|
|
||||||
}
|
|
||||||
mis := base * 5 / 1000
|
|
||||||
if len(arg) > 8 {
|
|
||||||
mis = kit.Int(arg[8])
|
|
||||||
}
|
|
||||||
|
|
||||||
rest := total - zhu - old - bad - mis - tax
|
|
||||||
m.Cmdy("ssh.data", "insert", arg[0], "month", arg[1], "total", total, "base", base, "tax",
|
|
||||||
tax, "zhu", zhu, "old", old, "bad", bad, "mis", mis, "rest", rest)
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
web.Index.Register(Index, &web.WEB{Context: Index})
|
|
||||||
}
|
|
@ -1,79 +0,0 @@
|
|||||||
package team
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/ctx"
|
|
||||||
"contexts/web"
|
|
||||||
"fmt"
|
|
||||||
"toolkit"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "team", Help: "团队中心",
|
|
||||||
Caches: map[string]*ctx.Cache{},
|
|
||||||
Configs: map[string]*ctx.Config{},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"task": {Name: "task create table level class status begin_time close_time target detail arg...", Help: "任务", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
switch arg[0] {
|
|
||||||
case "progress":
|
|
||||||
if len(arg) > 3 && arg[1] != "" {
|
|
||||||
switch arg[3] {
|
|
||||||
case "prepare", "action", "cancel", "finish":
|
|
||||||
time := "close_time"
|
|
||||||
switch arg[3] {
|
|
||||||
case "prepare", "action":
|
|
||||||
time = "begin_time"
|
|
||||||
case "cancel", "finish":
|
|
||||||
time = "close_time"
|
|
||||||
default:
|
|
||||||
time = "update_time"
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新任务
|
|
||||||
m.Cmd("ssh.data", "update", arg[1], arg[2], "status", arg[3], time, m.Time())
|
|
||||||
arg = []string{arg[0], m.Option("table")}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 任务进度
|
|
||||||
m.Option("cache.limit", kit.Select("30", arg, 2))
|
|
||||||
m.Option("cache.offend", kit.Select("0", arg, 3))
|
|
||||||
m.Meta["append"] = []string{"prepare", "action", "cancel", "finish"}
|
|
||||||
m.Cmd("ssh.data", "show", arg[1]).Table(func(index int, value map[string]string) {
|
|
||||||
m.Push(value["status"],
|
|
||||||
fmt.Sprintf("<span data-id='%s' title='%s'>%s</span>", value["id"], value["detail"], value["target"]))
|
|
||||||
})
|
|
||||||
m.Table()
|
|
||||||
|
|
||||||
case "create":
|
|
||||||
// 创建任务
|
|
||||||
if len(arg) > 7 {
|
|
||||||
if len(arg) < 9 {
|
|
||||||
arg = append(arg, "")
|
|
||||||
}
|
|
||||||
m.Cmdy("ssh.data", "insert", arg[1], "level", arg[2], "class", arg[3],
|
|
||||||
"status", arg[4], "begin_time", arg[5], "close_time", arg[6],
|
|
||||||
"target", arg[7], "detail", arg[8], arg[9:])
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
arg = []string{arg[1]}
|
|
||||||
fallthrough
|
|
||||||
default:
|
|
||||||
// 更新任务
|
|
||||||
if len(arg) > 1 && arg[1] == "modify" {
|
|
||||||
m.Cmdy("ssh.data", "update", m.Option("table"), arg[0], arg[2], arg[3])
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查看任务
|
|
||||||
if len(arg) > 0 && arg[0] == "" {
|
|
||||||
arg = arg[:0]
|
|
||||||
}
|
|
||||||
m.Cmdy("ssh.data", "show", arg, "fields", "id", "level", "class", "status", "target", "begin_time", "close_time")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
web.Index.Register(Index, &web.WEB{Context: Index})
|
|
||||||
}
|
|
@ -1,277 +0,0 @@
|
|||||||
package wiki
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/ctx"
|
|
||||||
mis "github.com/shylinux/toolkits"
|
|
||||||
"strings"
|
|
||||||
"toolkit"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 图形接口
|
|
||||||
type Chart interface {
|
|
||||||
Init(*ctx.Message, ...string) Chart
|
|
||||||
Draw(*ctx.Message, int, int) Chart
|
|
||||||
|
|
||||||
GetWidth(...string) int
|
|
||||||
GetHeight(...string) int
|
|
||||||
}
|
|
||||||
|
|
||||||
// 图形基类
|
|
||||||
type Block struct {
|
|
||||||
Text string
|
|
||||||
FontColor string
|
|
||||||
FontFamily string
|
|
||||||
BackGround string
|
|
||||||
|
|
||||||
FontSize int
|
|
||||||
LineSize int
|
|
||||||
Padding int
|
|
||||||
Margin int
|
|
||||||
|
|
||||||
Width, Height int
|
|
||||||
|
|
||||||
TextData string
|
|
||||||
RectData string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Block) Init(m *ctx.Message, arg ...string) Chart {
|
|
||||||
b.Text = kit.Select(b.Text, arg, 0)
|
|
||||||
b.FontColor = kit.Select("white", kit.Select(b.FontColor, arg, 1))
|
|
||||||
b.BackGround = kit.Select("red", kit.Select(b.BackGround, arg, 2))
|
|
||||||
b.FontSize = kit.Int(kit.Select("24", kit.Select(kit.Format(b.FontSize), arg, 3)))
|
|
||||||
b.LineSize = kit.Int(kit.Select("12", kit.Select(kit.Format(b.LineSize), arg, 4)))
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
func (b *Block) Draw(m *ctx.Message, x, y int) Chart {
|
|
||||||
m.Echo(`<rect x="%d" y="%d" width="%d" height="%d" fill="%s" %v/>`,
|
|
||||||
x+b.Margin/2, y+b.Margin/2, b.GetWidth(), b.GetHeight(), b.BackGround, b.RectData)
|
|
||||||
m.Echo("\n")
|
|
||||||
m.Echo(`<text x="%d" y="%d" font-size="%d" style="dominant-baseline:middle;text-anchor:middle;" fill="%s" %v>%v</text>`,
|
|
||||||
x+b.GetWidths()/2, y+b.GetHeights()/2, b.FontSize, b.FontColor, b.TextData, b.Text)
|
|
||||||
m.Echo("\n")
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
func (b *Block) Data(root interface{}) {
|
|
||||||
mis.Table(mis.Value(root, "data"), 0, 100, func(key string, value string) {
|
|
||||||
b.TextData += key + "='" + value + "' "
|
|
||||||
})
|
|
||||||
mis.Table(mis.Value(root, "rect"), 0, 100, func(key string, value string) {
|
|
||||||
b.RectData += key + "='" + value + "' "
|
|
||||||
})
|
|
||||||
b.FontColor = kit.Select(b.FontColor, mis.Value(root, "fg"))
|
|
||||||
b.BackGround = kit.Select(b.BackGround, mis.Value(root, "bg"))
|
|
||||||
}
|
|
||||||
func (b *Block) GetWidth(str ...string) int {
|
|
||||||
if b.Width != 0 {
|
|
||||||
return b.Width
|
|
||||||
}
|
|
||||||
return len(kit.Select(b.Text, str, 0))*b.FontSize*6/10 + b.Padding
|
|
||||||
}
|
|
||||||
func (b *Block) GetHeight(str ...string) int {
|
|
||||||
if b.Height != 0 {
|
|
||||||
return b.Height
|
|
||||||
}
|
|
||||||
return b.FontSize*b.LineSize/10 + b.Padding
|
|
||||||
}
|
|
||||||
func (b *Block) GetWidths(str ...string) int {
|
|
||||||
return b.GetWidth(str...) + b.Margin
|
|
||||||
}
|
|
||||||
func (b *Block) GetHeights(str ...string) int {
|
|
||||||
return b.GetHeight() + b.Margin
|
|
||||||
}
|
|
||||||
|
|
||||||
// 树
|
|
||||||
type Chain struct {
|
|
||||||
data map[string]interface{}
|
|
||||||
max map[int]int
|
|
||||||
Block
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Chain) Init(m *ctx.Message, arg ...string) Chart {
|
|
||||||
// 解数据
|
|
||||||
b.data = mis.Parse(nil, "", b.show(m, arg[0])...).(map[string]interface{})
|
|
||||||
b.FontColor = kit.Select("white", arg, 1)
|
|
||||||
b.BackGround = kit.Select("red", arg, 2)
|
|
||||||
b.FontSize = kit.Int(kit.Select("24", arg, 3))
|
|
||||||
b.LineSize = kit.Int(kit.Select("12", arg, 4))
|
|
||||||
b.Padding = kit.Int(kit.Select("8", arg, 5))
|
|
||||||
b.Margin = kit.Int(kit.Select("8", arg, 6))
|
|
||||||
m.Log("info", "data %v", kit.Formats(b.data))
|
|
||||||
|
|
||||||
// 计算尺寸
|
|
||||||
b.max = map[int]int{}
|
|
||||||
b.Height = b.size(m, b.data, 0, b.max) * b.GetHeights()
|
|
||||||
width := 0
|
|
||||||
for _, v := range b.max {
|
|
||||||
width += b.GetWidths(strings.Repeat(" ", v))
|
|
||||||
}
|
|
||||||
b.Width = width
|
|
||||||
m.Log("info", "data %v", kit.Formats(b.data))
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
func (b *Chain) Draw(m *ctx.Message, x, y int) Chart {
|
|
||||||
return b.draw(m, b.data, 0, b.max, x, y, &Block{})
|
|
||||||
}
|
|
||||||
func (b *Chain) show(m *ctx.Message, str string) (res []string) {
|
|
||||||
miss := []int{}
|
|
||||||
list := mis.Split(str, "\n")
|
|
||||||
for _, line := range list {
|
|
||||||
// 计算缩进
|
|
||||||
dep := 0
|
|
||||||
loop:
|
|
||||||
for _, v := range []rune(line) {
|
|
||||||
switch v {
|
|
||||||
case ' ':
|
|
||||||
dep++
|
|
||||||
case '\t':
|
|
||||||
dep += 4
|
|
||||||
default:
|
|
||||||
break loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 计算层次
|
|
||||||
if len(miss) > 0 {
|
|
||||||
if miss[len(miss)-1] > dep {
|
|
||||||
for i := len(miss) - 1; i >= 0; i-- {
|
|
||||||
if miss[i] < dep {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
res = append(res, "]", "}")
|
|
||||||
miss = miss[:i]
|
|
||||||
}
|
|
||||||
miss = append(miss, dep)
|
|
||||||
} else if miss[len(miss)-1] < dep {
|
|
||||||
miss = append(miss, dep)
|
|
||||||
} else {
|
|
||||||
res = append(res, "]", "}")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
miss = append(miss, dep)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 输出节点
|
|
||||||
word := mis.Split(line)
|
|
||||||
res = append(res, "{", "meta", "{", "text")
|
|
||||||
res = append(res, word...)
|
|
||||||
res = append(res, "}", "list", "[")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
func (b *Chain) size(m *ctx.Message, root map[string]interface{}, depth int, width map[int]int) int {
|
|
||||||
meta := root["meta"].(map[string]interface{})
|
|
||||||
|
|
||||||
// 最大宽度
|
|
||||||
text := kit.Format(meta["text"])
|
|
||||||
if len(text) > width[depth] {
|
|
||||||
width[depth] = len(text)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 计算高度
|
|
||||||
height := 0
|
|
||||||
if list, ok := root["list"].([]interface{}); ok && len(list) > 0 {
|
|
||||||
kit.Map(root["list"], "", func(index int, value map[string]interface{}) {
|
|
||||||
height += b.size(m, value, depth+1, width)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
height = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
meta["height"] = height
|
|
||||||
return height
|
|
||||||
}
|
|
||||||
func (b *Chain) draw(m *ctx.Message, root map[string]interface{}, depth int, width map[int]int, x, y int, p *Block) Chart {
|
|
||||||
meta := root["meta"].(map[string]interface{})
|
|
||||||
b.Width, b.Height = 0, 0
|
|
||||||
|
|
||||||
// 当前节点
|
|
||||||
block := &Block{
|
|
||||||
BackGround: kit.Select(b.BackGround, kit.Select(p.BackGround, meta["bg"])),
|
|
||||||
FontColor: kit.Select(b.FontColor, kit.Select(p.FontColor, meta["fg"])),
|
|
||||||
FontSize: b.FontSize,
|
|
||||||
LineSize: b.LineSize,
|
|
||||||
Padding: b.Padding,
|
|
||||||
Margin: b.Margin,
|
|
||||||
Width: b.GetWidth(strings.Repeat(" ", width[depth])),
|
|
||||||
}
|
|
||||||
|
|
||||||
block.Data(root["meta"])
|
|
||||||
block.Init(m, kit.Format(meta["text"])).Draw(m, x, y+(kit.Int(meta["height"])-1)*b.GetHeights()/2)
|
|
||||||
|
|
||||||
// 递归节点
|
|
||||||
kit.Map(root["list"], "", func(index int, value map[string]interface{}) {
|
|
||||||
b.draw(m, value, depth+1, width, x+b.GetWidths(strings.Repeat(" ", width[depth])), y, block)
|
|
||||||
y += kit.Int(kit.Chain(value, "meta.height")) * b.GetHeights()
|
|
||||||
})
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// 表
|
|
||||||
type Table struct {
|
|
||||||
data [][]string
|
|
||||||
max map[int]int
|
|
||||||
Block
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Table) Init(m *ctx.Message, arg ...string) Chart {
|
|
||||||
// 解析数据
|
|
||||||
b.max = map[int]int{}
|
|
||||||
for _, v := range mis.Split(arg[0], "\n") {
|
|
||||||
l := mis.Split(v)
|
|
||||||
for i, v := range l {
|
|
||||||
switch data := mis.Parse(nil, "", mis.Split(v)...).(type) {
|
|
||||||
case map[string]interface{}:
|
|
||||||
v = kit.Select("", data["text"])
|
|
||||||
}
|
|
||||||
if len(v) > b.max[i] {
|
|
||||||
b.max[i] = len(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.data = append(b.data, l)
|
|
||||||
}
|
|
||||||
b.FontColor = kit.Select("white", arg, 1)
|
|
||||||
b.BackGround = kit.Select("red", arg, 2)
|
|
||||||
b.FontSize = kit.Int(kit.Select("24", arg, 3))
|
|
||||||
b.LineSize = kit.Int(kit.Select("12", arg, 4))
|
|
||||||
b.Padding = kit.Int(kit.Select("8", arg, 5))
|
|
||||||
b.Margin = kit.Int(kit.Select("8", arg, 6))
|
|
||||||
|
|
||||||
// 计算尺寸
|
|
||||||
width := 0
|
|
||||||
for _, v := range b.max {
|
|
||||||
width += b.GetWidths(strings.Repeat(" ", v))
|
|
||||||
}
|
|
||||||
b.Width = width
|
|
||||||
b.Height = len(b.data) * b.GetHeights()
|
|
||||||
|
|
||||||
m.Log("info", "data %v", kit.Formats(b.data))
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
func (b *Table) Draw(m *ctx.Message, x, y int) Chart {
|
|
||||||
b.Width, b.Height = 0, 0
|
|
||||||
for n, line := range b.data {
|
|
||||||
for i, text := range line {
|
|
||||||
l := 0
|
|
||||||
for j := 0; j < i; j++ {
|
|
||||||
l += b.GetWidths(strings.Repeat(" ", b.max[i]))
|
|
||||||
}
|
|
||||||
block := &Block{
|
|
||||||
BackGround: kit.Select(b.BackGround),
|
|
||||||
FontColor: kit.Select(b.FontColor),
|
|
||||||
FontSize: b.FontSize,
|
|
||||||
LineSize: b.LineSize,
|
|
||||||
Padding: b.Padding,
|
|
||||||
Margin: b.Margin,
|
|
||||||
Width: b.GetWidth(strings.Repeat(" ", b.max[i])),
|
|
||||||
}
|
|
||||||
|
|
||||||
switch data := mis.Parse(nil, "", mis.Split(text)...).(type) {
|
|
||||||
case map[string]interface{}:
|
|
||||||
text = kit.Select(text, data["text"])
|
|
||||||
block.Data(data)
|
|
||||||
}
|
|
||||||
block.Init(m, text).Draw(m, x+l, y+n*b.GetHeights())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
@ -1,547 +0,0 @@
|
|||||||
package wiki
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gomarkdown/markdown"
|
|
||||||
mis "github.com/shylinux/toolkits"
|
|
||||||
|
|
||||||
"contexts/ctx"
|
|
||||||
"contexts/web"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"path"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"text/template"
|
|
||||||
)
|
|
||||||
|
|
||||||
type opt struct {
|
|
||||||
font_size int
|
|
||||||
font_color string
|
|
||||||
background string
|
|
||||||
padding int
|
|
||||||
margin int
|
|
||||||
}
|
|
||||||
|
|
||||||
func show(m *ctx.Message, str string) (res []string) {
|
|
||||||
miss := []int{}
|
|
||||||
list := mis.Split(str, "\n")
|
|
||||||
for _, line := range list {
|
|
||||||
dep := 0
|
|
||||||
loop:
|
|
||||||
for _, v := range []rune(line) {
|
|
||||||
switch v {
|
|
||||||
case ' ':
|
|
||||||
dep++
|
|
||||||
case '\t':
|
|
||||||
dep += 4
|
|
||||||
default:
|
|
||||||
break loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(miss) > 0 {
|
|
||||||
if miss[len(miss)-1] > dep {
|
|
||||||
for i := len(miss) - 1; i >= 0; i-- {
|
|
||||||
if miss[i] < dep {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
m.Log("show", "pop %d %v %v", dep, mis.Format(miss), line)
|
|
||||||
res = append(res, "]", "}")
|
|
||||||
miss = miss[:i]
|
|
||||||
}
|
|
||||||
m.Log("show", "push %d %v %v", dep, mis.Format(miss), line)
|
|
||||||
miss = append(miss, dep)
|
|
||||||
} else if miss[len(miss)-1] < dep {
|
|
||||||
m.Log("show", "push %d %v %v", dep, mis.Format(miss), line)
|
|
||||||
miss = append(miss, dep)
|
|
||||||
} else {
|
|
||||||
res = append(res, "]", "}")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
m.Log("show", "push %d %v", dep, mis.Format(miss))
|
|
||||||
miss = append(miss, dep)
|
|
||||||
}
|
|
||||||
|
|
||||||
word := mis.Split(line)
|
|
||||||
res = append(res, "{", "meta", "{", "text")
|
|
||||||
res = append(res, word...)
|
|
||||||
res = append(res, "}", "list", "[")
|
|
||||||
|
|
||||||
}
|
|
||||||
m.Log("haha", "%v %v", str, res)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func size(m *ctx.Message, root map[string]interface{}, depth int, width map[int]int) int {
|
|
||||||
text := kit.Format(kit.Chain(root, "meta.text"))
|
|
||||||
if len(text) > width[depth] {
|
|
||||||
width[depth] = len(text)
|
|
||||||
}
|
|
||||||
|
|
||||||
if list, ok := root["list"].([]interface{}); !ok || len(list) == 0 {
|
|
||||||
kit.Chain(root, "meta.height", 1)
|
|
||||||
m.Log("fuck", "size %v %d", kit.Chain(root, "meta.text"), 1)
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
height := 0
|
|
||||||
kit.Map(root["list"], "", func(index int, value map[string]interface{}) {
|
|
||||||
height += size(m, value, depth+1, width)
|
|
||||||
})
|
|
||||||
kit.Chain(root, "meta.height", height)
|
|
||||||
m.Log("fuck", "size %v %d", kit.Chain(root, "meta.text"), height)
|
|
||||||
return height
|
|
||||||
}
|
|
||||||
func draw(m *ctx.Message, root map[string]interface{}, depth int, width map[int]int, x int, y int, opt *opt) {
|
|
||||||
meta := root["meta"].(map[string]interface{})
|
|
||||||
m.Log("fuck", "draw %v %d", meta["text"], y)
|
|
||||||
height := kit.Int(meta["height"])
|
|
||||||
p := (height - 1) * (opt.font_size + opt.margin + opt.padding)
|
|
||||||
|
|
||||||
m.Echo(`<rect x="%d" y="%d" width="%d" height="%d" fill="%s"/>`,
|
|
||||||
x, y+p/2, width[depth]*opt.font_size/2+opt.padding, opt.font_size+opt.padding, kit.Select(opt.background, meta["bg"]))
|
|
||||||
m.Echo(`<text x="%d" y="%d" font-size="%d" text-anchor="middle" fill="%s">%v</text>`,
|
|
||||||
x+width[depth]*opt.font_size/2/2+opt.padding/2, y+p/2+opt.font_size-opt.padding/2, opt.font_size, kit.Select(opt.font_color, meta["fg"]), meta["text"])
|
|
||||||
|
|
||||||
kit.Map(root["list"], "", func(index int, value map[string]interface{}) {
|
|
||||||
draw(m, value, depth+1, width, x+width[depth]*opt.font_size/2+opt.margin+opt.padding, y, opt)
|
|
||||||
y += kit.Int(kit.Chain(value, "meta.height")) * (opt.font_size + opt.margin + opt.padding)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "wiki", Help: "文档中心",
|
|
||||||
Caches: map[string]*ctx.Cache{},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"login": {Name: "login", Value: map[string]interface{}{"check": "false", "meta": map[string]interface{}{
|
|
||||||
"script": "usr/script",
|
|
||||||
}}, Help: "用户登录"},
|
|
||||||
"componet": {Name: "componet", Value: map[string]interface{}{
|
|
||||||
"index": []interface{}{
|
|
||||||
map[string]interface{}{"name": "wiki",
|
|
||||||
"tmpl": "head", "metas": []interface{}{map[string]interface{}{
|
|
||||||
"name": "viewport", "content": "width=device-width, initial-scale=0.7, user-scalable=no",
|
|
||||||
}}, "favicon": "favicon.ico", "styles": []interface{}{
|
|
||||||
"example.css", "wiki.css",
|
|
||||||
}},
|
|
||||||
map[string]interface{}{"name": "header",
|
|
||||||
"tmpl": "fieldset", "view": "Header", "init": "initHeader",
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "tree",
|
|
||||||
"tmpl": "fieldset", "view": "Tree", "init": "initTree",
|
|
||||||
"ctx": "web.wiki", "cmd": "tree",
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "text",
|
|
||||||
"tmpl": "fieldset", "view": "Text", "init": "initText",
|
|
||||||
"ctx": "web.wiki", "cmd": "text",
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "footer",
|
|
||||||
"tmpl": "fieldset", "view": "Footer", "init": "initFooter",
|
|
||||||
},
|
|
||||||
map[string]interface{}{"name": "tail",
|
|
||||||
"tmpl": "tail", "scripts": []interface{}{
|
|
||||||
"toolkit.js", "context.js", "example.js", "wiki.js",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, Help: "组件列表"},
|
|
||||||
|
|
||||||
"level": {Name: "level", Value: "usr/local/wiki", Help: "文档路径"},
|
|
||||||
"class": {Name: "class", Value: "", Help: "文档目录"},
|
|
||||||
"favor": {Name: "favor", Value: "index.md", Help: "默认文档"},
|
|
||||||
|
|
||||||
"story": {Name: "story", Value: map[string]interface{}{
|
|
||||||
"data": map[string]interface{}{},
|
|
||||||
"node": map[string]interface{}{},
|
|
||||||
"head": map[string]interface{}{},
|
|
||||||
}, Help: "故事会"},
|
|
||||||
|
|
||||||
"template": {Name: "template", Value: map[string]interface{}{
|
|
||||||
"list": []interface{}{
|
|
||||||
`{{define "raw"}}{{.|results}}{{end}}`,
|
|
||||||
`{{define "title"}}{{.|results}}{{end}}`,
|
|
||||||
`{{define "chapter"}}{{.|results}}{{end}}`,
|
|
||||||
`{{define "section"}}{{.|results}}{{end}}`,
|
|
||||||
`{{define "block"}}<div>{{.|results}}<div>{{end}}`,
|
|
||||||
},
|
|
||||||
}, Help: "故事会"},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"tree": {Name: "tree", Help: "目录", Form: map[string]int{"level": 1, "class": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Cmdy("nfs.dir", path.Join(m.Confx("level"), m.Confx("class", arg, 0)),
|
|
||||||
"time", "size", "line", "file", "dir_sort", "time", "time_r").Set("result")
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"text": {Name: "text", Help: "文章", Form: map[string]int{"level": 1, "class": 1, "favor": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
which := m.Cmdx("nfs.path", path.Join(m.Confx("level"), m.Confx("class", arg, 1), m.Confx("favor", arg, 0)))
|
|
||||||
|
|
||||||
tmpl := template.New("render").Funcs(*ctx.LocalCGI(m, c))
|
|
||||||
m.Confm("template", "list", func(index int, value string) { tmpl = template.Must(tmpl.Parse(value)) })
|
|
||||||
tmpl = template.Must(tmpl.ParseGlob(path.Join(m.Cmdx("nfs.path", m.Conf("route", "template_dir")), "/*.tmpl")))
|
|
||||||
tmpl = template.Must(tmpl.ParseGlob(path.Join(m.Cmdx("nfs.path", m.Conf("route", "template_dir")), m.Cap("route"), "/*.tmpl")))
|
|
||||||
tmpl = template.Must(tmpl.ParseFiles(which))
|
|
||||||
for i, v := range tmpl.Templates() {
|
|
||||||
m.Log("info", "%v, %v", i, v.Name())
|
|
||||||
}
|
|
||||||
m.Optionv("title", map[string]int{})
|
|
||||||
m.Optionv("tmpl", tmpl)
|
|
||||||
m.Option("render", "")
|
|
||||||
|
|
||||||
buffer := bytes.NewBuffer([]byte{})
|
|
||||||
m.Assert(tmpl.ExecuteTemplate(buffer, m.Option("filename", path.Base(which)), m))
|
|
||||||
if f, p, e := kit.Create(path.Join("var/tmp/file", which)); e == nil {
|
|
||||||
defer f.Close()
|
|
||||||
f.Write(buffer.Bytes())
|
|
||||||
m.Log("info", "save %v", p)
|
|
||||||
}
|
|
||||||
data := markdown.ToHTML(buffer.Bytes(), nil, nil)
|
|
||||||
m.Echo(string(data))
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"note": {Name: "note file|favor|commit", Help: "笔记", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if len(arg) == 0 {
|
|
||||||
m.Cmd("tree")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch arg[0] {
|
|
||||||
case "favor", "commit":
|
|
||||||
m.Cmd("story", arg[0], arg[1:])
|
|
||||||
default:
|
|
||||||
m.Cmd(kit.Select("tree", "text", strings.HasSuffix(arg[0], ".md")), arg[0])
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
|
|
||||||
"story": {Name: "story favor|commit|branch|remote story scene enjoy happy", Help: "故事会", Hand: func(m *ctx.Message, c *ctx.Context, cmd string, arg ...string) (e error) {
|
|
||||||
switch arg[0] {
|
|
||||||
case "favor":
|
|
||||||
if len(arg) < 4 {
|
|
||||||
m.Cmdy("ssh.data", "show", arg[1:])
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
head := kit.Hashs(arg[2], arg[4])
|
|
||||||
prev := m.Conf(cmd, []string{"head", head, "node"})
|
|
||||||
m.Cmdy("ssh.data", "insert", arg[1], "story", arg[2], "scene", arg[3], "enjoy", arg[4], "node", prev)
|
|
||||||
|
|
||||||
case "commit":
|
|
||||||
head := kit.Hashs(arg[1], arg[3])
|
|
||||||
prev := m.Conf(cmd, []string{"head", head, "node"})
|
|
||||||
m.Log("info", "head: %v %#v", head, prev)
|
|
||||||
|
|
||||||
if len(arg) > 4 {
|
|
||||||
data := kit.Hashs(arg[4])
|
|
||||||
m.Log("info", "data: %v %v", data, arg[4])
|
|
||||||
if m.Conf(cmd, []string{"node", prev, "data"}) != data {
|
|
||||||
m.Conf(cmd, []string{"data", data}, arg[4])
|
|
||||||
|
|
||||||
meta := map[string]interface{}{
|
|
||||||
"time": m.Time(),
|
|
||||||
"story": arg[1],
|
|
||||||
"scene": arg[2],
|
|
||||||
"enjoy": arg[3],
|
|
||||||
"data": data,
|
|
||||||
"prev": prev,
|
|
||||||
}
|
|
||||||
node := kit.Hashs(kit.Format(meta))
|
|
||||||
m.Log("info", "node: %v %v", node, meta)
|
|
||||||
m.Conf(cmd, []string{"node", node}, meta)
|
|
||||||
|
|
||||||
m.Log("info", "head: %v %v", head, node)
|
|
||||||
m.Conf(cmd, []string{"head", head, "node"}, node)
|
|
||||||
m.Echo("%v", kit.Formats(meta))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for prev != "" {
|
|
||||||
node := m.Confm(cmd, []string{"node", prev})
|
|
||||||
m.Push("node", kit.Short(prev, 6))
|
|
||||||
m.Push("time", node["time"])
|
|
||||||
m.Push("data", m.Conf(cmd, []string{"data", kit.Format(node["data"])}))
|
|
||||||
prev = kit.Format(node["prev"])
|
|
||||||
}
|
|
||||||
m.Table()
|
|
||||||
return
|
|
||||||
|
|
||||||
case "branch":
|
|
||||||
m.Confm(cmd, "head", func(key string, value map[string]interface{}) {
|
|
||||||
node := kit.Format(value["node"])
|
|
||||||
m.Push("key", kit.Short(key, 6))
|
|
||||||
m.Push("story", m.Conf(cmd, []string{"node", node, "story"}))
|
|
||||||
m.Push("scene", m.Conf(cmd, []string{"node", node, "scene"}))
|
|
||||||
m.Push("enjoy", m.Conf(cmd, []string{"node", node, "enjoy"}))
|
|
||||||
m.Push("node", kit.Short(value["node"], 6))
|
|
||||||
})
|
|
||||||
m.Table()
|
|
||||||
case "remote":
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"index": {Name: "index name|hash", Help: "索引", Hand: func(m *ctx.Message, c *ctx.Context, cmd string, arg ...string) (e error) {
|
|
||||||
scene := ""
|
|
||||||
if hash := m.Conf("story", []string{"head", kit.Hashs(m.Option("filename"), arg[0]), "node"}); hash != "" {
|
|
||||||
arg[0] = hash
|
|
||||||
} else if hash := m.Conf("story", []string{"head", arg[0], "node"}); hash != "" {
|
|
||||||
arg[0] = hash
|
|
||||||
}
|
|
||||||
if hash := m.Conf("story", []string{"node", arg[0], "data"}); hash != "" {
|
|
||||||
scene = m.Conf("story", []string{"node", arg[0], "scene"})
|
|
||||||
arg[0] = hash
|
|
||||||
}
|
|
||||||
if data := m.Conf("story", []string{"data", arg[0]}); data != "" {
|
|
||||||
arg[0] = data
|
|
||||||
}
|
|
||||||
if scene != "" {
|
|
||||||
m.Cmdy(scene, "", arg[0])
|
|
||||||
} else {
|
|
||||||
m.Echo(arg[0])
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"table": {Name: "table name data", Help: "表格", Hand: func(m *ctx.Message, c *ctx.Context, cmd string, arg ...string) (e error) {
|
|
||||||
if len(arg) < 2 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
m.Option("scene", cmd)
|
|
||||||
m.Option("enjoy", arg[0])
|
|
||||||
m.Option("happy", arg[1])
|
|
||||||
m.Option("render", cmd)
|
|
||||||
|
|
||||||
head := []string{}
|
|
||||||
for i, l := range strings.Split(strings.TrimSpace(arg[1]), "\n") {
|
|
||||||
if i == 0 {
|
|
||||||
head = kit.Split(l, ' ', 100)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for j, v := range kit.Split(l, ' ', 100) {
|
|
||||||
m.Push(head[j], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"order": {Name: "order", Help: "列表", Hand: func(m *ctx.Message, c *ctx.Context, cmd string, arg ...string) (e error) {
|
|
||||||
if len(arg) < 2 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
m.Option("scene", cmd)
|
|
||||||
m.Option("enjoy", arg[0])
|
|
||||||
m.Option("happy", arg[1])
|
|
||||||
m.Option("render", cmd)
|
|
||||||
|
|
||||||
for _, l := range strings.Split(strings.TrimSpace(arg[1]), "\n") {
|
|
||||||
m.Push("list", l)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"refer": {Name: "refer", Help: "链接地址", Hand: func(m *ctx.Message, c *ctx.Context, cmd string, arg ...string) (e error) {
|
|
||||||
if len(arg) == 1 {
|
|
||||||
cmd, arg = arg[0], arg[1:]
|
|
||||||
for _, l := range strings.Split(strings.TrimSpace(cmd), "\n") {
|
|
||||||
if l = strings.TrimSpace(l); len(l) > 0 {
|
|
||||||
arg = append(arg, kit.Split(l, ' ', 2)...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Set("option", "render", "order")
|
|
||||||
for i := 0; i < len(arg)-1; i += 2 {
|
|
||||||
m.Push("list", fmt.Sprintf(`%s: <a href="%s" target="_blank">%s</a>`, arg[i], arg[i+1], arg[i+1]))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"favor": {Name: "favor type tab", Help: "链接地址", Hand: func(m *ctx.Message, c *ctx.Context, cmd string, arg ...string) (e error) {
|
|
||||||
msg := m.Cmd("ssh.data", "show", "tip", "", "1000", "0", "tab", arg[1])
|
|
||||||
|
|
||||||
switch arg[0] {
|
|
||||||
case "script":
|
|
||||||
m.Set("option", "render", "code")
|
|
||||||
if b, e := ioutil.ReadFile(path.Join(m.Conf("login", "meta.script"), arg[1])); e == nil {
|
|
||||||
m.Echo(string(b))
|
|
||||||
}
|
|
||||||
|
|
||||||
case "li":
|
|
||||||
m.Set("option", "render", "order")
|
|
||||||
msg.Table(func(index int, value map[string]string) {
|
|
||||||
m.Push("list", fmt.Sprintf(`%s: <a href="%s" target="_blank">%s</a>`, value["note"], value["word"], value["word"]))
|
|
||||||
})
|
|
||||||
|
|
||||||
case "sh":
|
|
||||||
m.Set("option", "render", "code")
|
|
||||||
m.Echo("#! /bin/sh\n")
|
|
||||||
m.Echo("# %v\n", arg[1])
|
|
||||||
m.Echo("\n")
|
|
||||||
msg.Table(func(index int, value map[string]string) {
|
|
||||||
m.Echo("# %d %v\n%v\n\n", index, value["note"], value["word"])
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"shell": {Name: "shell dir cmd", Help: "命令行", Form: map[string]int{"style": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Option("render", "code")
|
|
||||||
m.Echo("$ %v\n", strings.Join(arg[1:], " "))
|
|
||||||
m.Cmdy("cli.system", "cmd_dir", arg[0], "bash", "-c", strings.Join(arg[1:], " "))
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"chart": {Name: "chart type text", Help: "绘图", Form: map[string]int{"style": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Option("render", "raw")
|
|
||||||
var chart Chart
|
|
||||||
switch arg[0] {
|
|
||||||
case "block":
|
|
||||||
chart = &Block{}
|
|
||||||
case "chain":
|
|
||||||
chart = &Chain{}
|
|
||||||
case "table":
|
|
||||||
chart = &Table{}
|
|
||||||
}
|
|
||||||
arg[1] = strings.TrimSpace(arg[1])
|
|
||||||
|
|
||||||
chart.Init(m, arg[1:]...)
|
|
||||||
m.Echo(`<svg vertion="1.1" xmlns="http://www.w3.org/2000/svg" width="%d", height="%d" style="%s">`,
|
|
||||||
chart.GetWidth(), chart.GetHeight(), m.Option("style"))
|
|
||||||
m.Echo("\n")
|
|
||||||
chart.Draw(m, 0, 0)
|
|
||||||
m.Echo(`</svg>`)
|
|
||||||
m.Echo("\n")
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
|
|
||||||
"title": {Name: "title text", Help: "一级标题", Hand: func(m *ctx.Message, c *ctx.Context, cmd string, arg ...string) (e error) {
|
|
||||||
ns := strings.Split(m.Conf("runtime", "node.name"), "-")
|
|
||||||
m.Set("option", "render", cmd).Echo(kit.Select(ns[len(ns)-1], arg, 0))
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"chapter": {Name: "chaper text", Help: "二级标题", Hand: func(m *ctx.Message, c *ctx.Context, cmd string, arg ...string) (e error) {
|
|
||||||
prefix := ""
|
|
||||||
if title, ok := m.Optionv("title").(map[string]int); ok {
|
|
||||||
title["chapter"]++
|
|
||||||
title["section"] = 0
|
|
||||||
prefix = strconv.Itoa(title["chapter"]) + " "
|
|
||||||
}
|
|
||||||
m.Set("option", "render", cmd).Echo(prefix + kit.Select("", arg, 0))
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"section": {Name: "section text", Help: "三级标题", Hand: func(m *ctx.Message, c *ctx.Context, cmd string, arg ...string) (e error) {
|
|
||||||
prefix := ""
|
|
||||||
if title, ok := m.Optionv("title").(map[string]int); ok {
|
|
||||||
title["section"]++
|
|
||||||
prefix = strconv.Itoa(title["chapter"]) + "." + strconv.Itoa(title["section"]) + " "
|
|
||||||
}
|
|
||||||
m.Set("option", "render", cmd).Echo(prefix + kit.Select("", arg, 0))
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
|
|
||||||
"run": {Name: "run", Help: "便签", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Option("render", "raw")
|
|
||||||
m.Cmdy(arg)
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"time": {Name: "time", Help: "便签", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Cmdy("cli.time", "show").Set("append")
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
|
|
||||||
"svg": {Name: "svg", Help: "绘图", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
data := map[string]interface{}{"meta": map[string]interface{}{"text": "chat"}, "list": []interface{}{
|
|
||||||
map[string]interface{}{"meta": map[string]interface{}{"text": "ocean"}},
|
|
||||||
map[string]interface{}{"meta": map[string]interface{}{"text": "river"}},
|
|
||||||
map[string]interface{}{"meta": map[string]interface{}{"text": "dream"}, "list": []interface{}{
|
|
||||||
map[string]interface{}{"meta": map[string]interface{}{"text": "zsh"}, "list": []interface{}{
|
|
||||||
map[string]interface{}{"meta": map[string]interface{}{"text": "auto.sh"}},
|
|
||||||
}},
|
|
||||||
map[string]interface{}{"meta": map[string]interface{}{"text": "tmux"}},
|
|
||||||
map[string]interface{}{"meta": map[string]interface{}{"text": "docker"}},
|
|
||||||
map[string]interface{}{"meta": map[string]interface{}{"text": "git"}},
|
|
||||||
map[string]interface{}{"meta": map[string]interface{}{"text": "vim"}, "list": []interface{}{
|
|
||||||
map[string]interface{}{"meta": map[string]interface{}{"text": "auto.vim"}},
|
|
||||||
}},
|
|
||||||
}},
|
|
||||||
map[string]interface{}{"meta": map[string]interface{}{"text": "storm"}},
|
|
||||||
map[string]interface{}{"meta": map[string]interface{}{"text": "steam"}},
|
|
||||||
}}
|
|
||||||
|
|
||||||
opt := &opt{
|
|
||||||
font_size: kit.Int(kit.Select("60", arg, 0)),
|
|
||||||
font_color: kit.Select("red", arg, 1),
|
|
||||||
background: kit.Select("green", arg, 2),
|
|
||||||
padding: 10,
|
|
||||||
margin: 20,
|
|
||||||
}
|
|
||||||
if len(arg) > 3 {
|
|
||||||
data = mis.Parse(nil, "", show(m, arg[3])...).(map[string]interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
max := map[int]int{}
|
|
||||||
num := size(m, data, 0, max)
|
|
||||||
width := 0
|
|
||||||
for _, v := range max {
|
|
||||||
width += v*opt.font_size/2 + opt.margin
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Echo(`<svg vertion="1.1" xmlns="http://www.w3.org/2000/svg" width="%d", height="%d">`,
|
|
||||||
width, num*(opt.font_size+opt.padding+opt.margin)-opt.margin)
|
|
||||||
draw(m, data, 0, max, 0, 0, opt)
|
|
||||||
m.Echo(`</svg>`)
|
|
||||||
|
|
||||||
// m.Echo(`<rect width="100%" height="100%" fill="red"/>`)
|
|
||||||
// m.Echo(`<circle cx="150" cy="100" r="80" fill="green"/>`)
|
|
||||||
// m.Echo(`<text x="150" y="100" font-size="60" text-anchor="middle" fill="black">SVG</text>`)
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"xls": {Name: "xls", Help: "表格", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
switch len(arg) {
|
|
||||||
case 0:
|
|
||||||
m.Cmdy("ssh.data", "show", "xls")
|
|
||||||
m.Meta["append"] = []string{"id", "title"}
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
var data map[int]map[int]string
|
|
||||||
what := m.Cmd("ssh.data", "show", "xls", arg[0], "format", "object").Append("content")
|
|
||||||
json.Unmarshal([]byte(what), &data)
|
|
||||||
|
|
||||||
max, n := 0, 0
|
|
||||||
for i, v := range data {
|
|
||||||
if i > n {
|
|
||||||
n = i
|
|
||||||
}
|
|
||||||
for i := range v {
|
|
||||||
if i > max {
|
|
||||||
max = i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Log("info", "m: %d n: %d", max, n)
|
|
||||||
|
|
||||||
for k := 0; k < n+2; k++ {
|
|
||||||
for i := 0; i < max+2; i++ {
|
|
||||||
m.Push(kit.Format(k), kit.Format(data[k][i]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
m.Cmdy("ssh.data", "insert", "xls", "title", arg[0], "content", arg[1])
|
|
||||||
|
|
||||||
default:
|
|
||||||
data := map[int]map[int]string{}
|
|
||||||
what := m.Cmd("ssh.data", "show", "xls", arg[0], "format", "object").Append("content")
|
|
||||||
json.Unmarshal([]byte(what), &data)
|
|
||||||
|
|
||||||
for i := 1; i < len(arg)-2; i += 3 {
|
|
||||||
if _, ok := data[kit.Int(arg[i])]; !ok {
|
|
||||||
data[kit.Int(arg[i])] = make(map[int]string)
|
|
||||||
}
|
|
||||||
data[kit.Int(arg[i])][kit.Int(arg[i+1])] = arg[i+2]
|
|
||||||
}
|
|
||||||
m.Cmdy("ssh.data", "update", "xls", arg[0], "content", kit.Format(data))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
web.Index.Register(Index, &web.WEB{Context: Index})
|
|
||||||
}
|
|
@ -1,83 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
|
||||||
"toolkit"
|
|
||||||
)
|
|
||||||
|
|
||||||
var files = ".*\\.(xml|html|css|js)$"
|
|
||||||
var words = "[[:^ascii:]]+"
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if len(os.Args) == 1 {
|
|
||||||
fmt.Println("usage", os.Args[0], "dirs [files [words]]")
|
|
||||||
fmt.Println("在目录dirs中,查找匹配files的文件,并查找匹配words的单词")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(os.Args) > 2 {
|
|
||||||
files = os.Args[2]
|
|
||||||
}
|
|
||||||
if len(os.Args) > 3 {
|
|
||||||
words = os.Args[3]
|
|
||||||
}
|
|
||||||
|
|
||||||
word, e := regexp.Compile(words)
|
|
||||||
kit.Check(e)
|
|
||||||
// out, e := os.Create(os.Args[2])
|
|
||||||
// kit.Check(e)
|
|
||||||
out := os.Stdout
|
|
||||||
|
|
||||||
total := 0
|
|
||||||
count := 0
|
|
||||||
chars := 0
|
|
||||||
kit.DirWalk(os.Args[1], func(file string) {
|
|
||||||
s, _ := os.Stat(file)
|
|
||||||
if s.IsDir() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if m, e := regexp.MatchString(files, file); !kit.Check(e) || !m {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
f, e := os.Open(file)
|
|
||||||
kit.Check(e)
|
|
||||||
bio := bufio.NewReader(f)
|
|
||||||
|
|
||||||
fmt.Fprintln(out, kit.FmtSize(s.Size()), file)
|
|
||||||
line := 0
|
|
||||||
|
|
||||||
cs := 0
|
|
||||||
for i := 1; true; i++ {
|
|
||||||
l, e := bio.ReadString('\n')
|
|
||||||
if e == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
kit.Check(e)
|
|
||||||
if i == 1 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
a := word.FindAllString(l, 20)
|
|
||||||
for _, v := range a {
|
|
||||||
n := len([]rune(v))
|
|
||||||
fmt.Fprintf(out, "l:%d c:%d %s\n", i, n, v)
|
|
||||||
total++
|
|
||||||
line++
|
|
||||||
chars += n
|
|
||||||
cs += n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt.Fprintln(out, "lines:", line, "chars:", cs, file)
|
|
||||||
fmt.Fprintln(out)
|
|
||||||
if line > 0 {
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
})
|
|
||||||
fmt.Fprintln(out, "files:", count, "lines:", total, "chars:", chars, os.Args[1])
|
|
||||||
return
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
// 数据层
|
|
||||||
_ "contexts/mdb" //数据中心
|
|
||||||
_ "contexts/nfs" //存储中心
|
|
||||||
_ "contexts/ssh" //集群中心
|
|
||||||
_ "contexts/tcp" //网络中心
|
|
||||||
// 控制层
|
|
||||||
_ "contexts/gdb" //调试中心
|
|
||||||
_ "contexts/lex" //词法中心
|
|
||||||
_ "contexts/log" //日志中心
|
|
||||||
_ "contexts/yac" //语法中心
|
|
||||||
// 服务层
|
|
||||||
_ "contexts/aaa" //认证中心
|
|
||||||
_ "contexts/cli" //管理中心
|
|
||||||
c "contexts/ctx" //模块中心
|
|
||||||
_ "contexts/web" //应用中心
|
|
||||||
|
|
||||||
// 应用层
|
|
||||||
_ "examples/chat" //会议中心
|
|
||||||
_ "examples/code" //代码中心
|
|
||||||
_ "examples/mall" //交易中心
|
|
||||||
_ "examples/team" //团队中心
|
|
||||||
_ "examples/wiki" //文档中心
|
|
||||||
|
|
||||||
// 应用层
|
|
||||||
_ "examples/chat/feishu" //飞书
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
c.Start()
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/cli"
|
|
||||||
"contexts/ctx"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "test", Help: "测试工具",
|
|
||||||
Caches: map[string]*ctx.Cache{},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"_index": &ctx.Config{Name: "index", Value: []interface{}{
|
|
||||||
map[string]interface{}{"name": "demo", "help": "demo",
|
|
||||||
"tmpl": "componet", "view": "componet", "init": "",
|
|
||||||
"type": "public", "ctx": "demo", "cmd": "demo",
|
|
||||||
"args": []interface{}{}, "inputs": []interface{}{
|
|
||||||
map[string]interface{}{"type": "text", "name": "pod", "value": "hello world"},
|
|
||||||
map[string]interface{}{"type": "button", "value": "执行"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"demo": {Name: "demo", Help: "demo", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Echo(kit.Select("hello world", arg, 0))
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Print(cli.Index.Plugin(Index, os.Args[1:]))
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
|
|
||||||
Script["context/index.js"] = function(field, option, output) {
|
|
||||||
return {}
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
|
|
||||||
kit project "项目" private \
|
|
||||||
select "" values "plugin review submit trends trend stats stat init" action auto \
|
|
||||||
text "" name see imports plugin_see action auto \
|
|
||||||
feature detail "加载" "复制" "下载" \
|
|
||||||
exports see name see \
|
|
||||||
button "执行" action auto \
|
|
||||||
button "返回" cb Last
|
|
||||||
|
|
||||||
kit compile "编译" private \
|
|
||||||
select "" values "plugin restart windows darwin linux self all" action auto \
|
|
||||||
text "" name see imports plugin_see \
|
|
||||||
button "编译"
|
|
||||||
|
|
||||||
kit publish "发布" private \
|
|
||||||
text "" name see imports plugin_see \
|
|
||||||
button "发布"
|
|
||||||
|
|
||||||
kit upgrade "升级" private "_:cli.upgrade" \
|
|
||||||
text "" name pod imports plugin_pod \
|
|
||||||
select "" values "script plugin restart package system portal bench" action auto \
|
|
||||||
text "" name see imports plugin_see \
|
|
||||||
button "升级"
|
|
||||||
|
|
||||||
kit missyou "任务" private "_:cli.missyou" \
|
|
||||||
text "" name pod imports plugin_pod \
|
|
||||||
text "" name you view long \
|
|
||||||
text "" name see imports plugin_see \
|
|
||||||
button "行动" action auto \
|
|
||||||
exports you you "" "" status you_status
|
|
||||||
|
|
||||||
kit pod "设备" private "_:ssh.remote" \
|
|
||||||
text "" name pod imports plugin_pod \
|
|
||||||
button "查看" action auto \
|
|
||||||
button "返回" cb Last \
|
|
||||||
exports pod node pod
|
|
||||||
|
|
||||||
kit ctx "模块" private "_:context" _ _ list \
|
|
||||||
text "" name pod imports plugin_pod action auto \
|
|
||||||
text "cli" name ctx imports plugin_ctx action auto \
|
|
||||||
button "查看" \
|
|
||||||
exports ctx names
|
|
||||||
|
|
||||||
kit cmd "命令" private "_:context" _ _ command \
|
|
||||||
text "" name pod imports plugin_pod \
|
|
||||||
text "cli" name ctx imports plugin_ctx \
|
|
||||||
text "date" name cmd imports plugin_cmd \
|
|
||||||
button "执行" \
|
|
||||||
button "返回" cb Last \
|
|
||||||
exports cmd cmd
|
|
||||||
|
|
||||||
kit dir "目录" private "_:nfs.dir" _ _ time size line path \
|
|
||||||
text "" name pod imports plugin_pod action auto \
|
|
||||||
text "usr/local" name path action auto view long \
|
|
||||||
button "浏览" action auto \
|
|
||||||
button "返回" cb Last \
|
|
||||||
exports dir "" dir
|
|
||||||
|
|
||||||
fun wss "推送" private \
|
|
||||||
text "" name wss imports plugin_wss \
|
|
||||||
text "" name cmd view long \
|
|
||||||
button "推送" \
|
|
||||||
button "返回" cb Last \
|
|
||||||
exports wss key
|
|
||||||
|
|
||||||
if $2 == ""
|
|
||||||
copy web.wss
|
|
||||||
else
|
|
||||||
copy web.wss _ sync
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1 +0,0 @@
|
|||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
fieldset.item.docker div.output {
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/cli"
|
|
||||||
"contexts/ctx"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: `docker`, Help: `plugin`,
|
|
||||||
Caches: map[string]*ctx.Cache{},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"_index": &ctx.Config{Name: "index", Value: []interface{}{
|
|
||||||
map[string]interface{}{"name": "demo", "help": "demo",
|
|
||||||
"tmpl": "componet", "view": "", "init": "",
|
|
||||||
"type": "public", "ctx": "demo", "cmd": "demo",
|
|
||||||
"args": []interface{}{}, "inputs": []interface{}{
|
|
||||||
map[string]interface{}{"type": "text", "name": "pod", "value": "hello world"},
|
|
||||||
map[string]interface{}{"type": "button", "value": "执行"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"demo": {Name: "demo", Help: "demo", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Echo(kit.Select("hello world", arg, 0))
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Print(cli.Index.Plugin(Index, os.Args[1:]))
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
Script["docker/index.js"] = function(field, option, output) {return {
|
|
||||||
}}
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
|||||||
|
|
||||||
kit dir "目录" private "_:web.code.zsh" "@pod" \
|
|
||||||
text "" name dir imports plugin_path action auto \
|
|
||||||
select "" name cmd values "list find tail grep init" action auto \
|
|
||||||
text "" name txt \
|
|
||||||
exports path path \
|
|
||||||
feature display editor \
|
|
||||||
button "搜索" action auto \
|
|
||||||
button "返回" cb Last
|
|
||||||
|
|
||||||
kit clip "粘贴板" private "web.code.tmux" "" "buffer" \
|
|
||||||
text "" name buffer action auto \
|
|
||||||
text "" name txt \
|
|
||||||
exports buffer buffer \
|
|
||||||
button "查看" action auto \
|
|
||||||
button "返回" cb Last
|
|
||||||
|
|
||||||
kit tmux "终端" private "web.code.tmux" \
|
|
||||||
text "" name session imports plugin_session action auto \
|
|
||||||
text "" name window imports plugin_window action auto \
|
|
||||||
text "" name pane imports plugin_pane view char action auto \
|
|
||||||
exports session session "" window window "" pane pane "" \
|
|
||||||
button "查看" action auto \
|
|
||||||
button "返回" cb Last
|
|
||||||
|
|
||||||
kit tmuxs "终端" private "web.code.tmux" \
|
|
||||||
text "" name session imports plugin_session \
|
|
||||||
select "" name cmd values "favor pane cmd"\
|
|
||||||
text "" name arg \
|
|
||||||
button "执行"
|
|
||||||
|
|
||||||
kit image "镜像" private "web.code.docker" "image" \
|
|
||||||
text "" name pos \
|
|
||||||
text "" name tag \
|
|
||||||
exports IMAGE_ID IMAGE_ID "" REPOSITORY REPOSITORY "" TAG TAG "" \
|
|
||||||
feature detail "运行" "清理" "删除" "创建" \
|
|
||||||
button "查看"
|
|
||||||
|
|
||||||
kit volume "存储" private "web.code.docker" "volume" \
|
|
||||||
text "" name arg imports plugin_VOLUME_NAME \
|
|
||||||
exports VOLUME_NAME VOLUME_NAME \
|
|
||||||
button "查看"
|
|
||||||
|
|
||||||
kit network "网络" private "web.code.docker" "network" \
|
|
||||||
text "" name arg imports plugin_NETWORK_ID action auto \
|
|
||||||
exports NETWORK_ID NETWORK_ID \
|
|
||||||
button "查看"
|
|
||||||
|
|
||||||
kit container "容器" private "web.code.docker" "container" \
|
|
||||||
text "" name arg imports plugin_CONTAINER_ID \
|
|
||||||
feature detail "进入" "停止" "启动" "重启" "清理" "修改" "删除" \
|
|
||||||
exports CONTAINER_ID CONTAINER_ID "" CONTAINER_NAME NAMES "" \
|
|
||||||
button "查看" action auto
|
|
||||||
|
|
||||||
kit command "命令" private "web.code.docker" "command" \
|
|
||||||
text "" name tag imports plugin_CONTAINER_ID \
|
|
||||||
select "" name pkg values "apk apt yum" \
|
|
||||||
select "" name cmd values "base" \
|
|
||||||
text "" name arg view long \
|
|
||||||
button "执行"
|
|
||||||
|
|
||||||
kit git "记录" private "_:web.code.zsh" "@you"\
|
|
||||||
text "usr/local" name dir imports plugin_git_path action auto \
|
|
||||||
select "git" name cmd values git \
|
|
||||||
select "status" name cmd values "diff status commit branch remote pull push sum init" action auto \
|
|
||||||
text "" name txt \
|
|
||||||
exports branch branch "" git_path path "" \
|
|
||||||
button "查看" action auto \
|
|
||||||
button "返回" cb Last
|
|
||||||
|
|
||||||
kit vim "编辑器" private "web.code.vim" \
|
|
||||||
select "bufs" name cmd values editor values prune values opens values cmds values txts values bufs values regs values marks values tags values fixs \
|
|
||||||
button "查看" action auto
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
fieldset.item.dream div.output {
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/cli"
|
|
||||||
"contexts/ctx"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: `dream`, Help: `plugin`,
|
|
||||||
Caches: map[string]*ctx.Cache{},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"_index": &ctx.Config{Name: "index", Value: []interface{}{
|
|
||||||
map[string]interface{}{"name": "demo", "help": "demo",
|
|
||||||
"tmpl": "componet", "view": "", "init": "",
|
|
||||||
"type": "public", "ctx": "demo", "cmd": "demo",
|
|
||||||
"args": []interface{}{}, "inputs": []interface{}{
|
|
||||||
map[string]interface{}{"type": "text", "name": "pod", "value": "hello world"},
|
|
||||||
map[string]interface{}{"type": "button", "value": "执行"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"demo": {Name: "demo", Help: "demo", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Echo(kit.Select("hello world", arg, 0))
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Print(cli.Index.Plugin(Index, os.Args[1:]))
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
Script["dream/index.js"] = function(field, option, output) {return {
|
|
||||||
}}
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
kit share "梦想主题" private "web.code.dream" list \
|
|
||||||
button "查看"
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/cli"
|
|
||||||
"contexts/ctx"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "test", Help: "测试工具",
|
|
||||||
Caches: map[string]*ctx.Cache{},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"_index": &ctx.Config{Name: "index", Value: []interface{}{
|
|
||||||
map[string]interface{}{"name": "demo", "help": "demo",
|
|
||||||
"tmpl": "componet", "view": "componet", "init": "",
|
|
||||||
"type": "public", "ctx": "demo", "cmd": "demo",
|
|
||||||
"args": []interface{}{}, "inputs": []interface{}{
|
|
||||||
map[string]interface{}{"type": "text", "name": "pod", "value": "hello world"},
|
|
||||||
map[string]interface{}{"type": "button", "value": "执行"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"demo": {Name: "demo", Help: "demo", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Echo(kit.Select("hello world", arg, 0))
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Print(cli.Index.Plugin(Index, os.Args[1:]))
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
Plugin["favor/index.js"] = function(field, option, output) {return {
|
|
||||||
share: function(event) {var plugin = field.Plugin
|
|
||||||
plugin.Run(event, ["share", option.txt.value], function(msg) {
|
|
||||||
kit.AppendChilds(output, [{img: [msg.result.join("")]}])
|
|
||||||
typeof cb == "function" && cb({})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}}
|
|
@ -1,61 +0,0 @@
|
|||||||
|
|
||||||
fun qrcode "二维码" "index.js" public \
|
|
||||||
text "" name txt view long \
|
|
||||||
button "生成" cb share
|
|
||||||
|
|
||||||
append qrcode ($1 || $referer)
|
|
||||||
end
|
|
||||||
|
|
||||||
kit macro "脚本宏" "macro.js" public \
|
|
||||||
text "" name mac imports plugin_mac action auto \
|
|
||||||
button "查看" \
|
|
||||||
button "全部" cb "all" \
|
|
||||||
button "录制" cb "Record" \
|
|
||||||
button "运行" cb "Replay" \
|
|
||||||
exports mac name
|
|
||||||
|
|
||||||
kit sys "命令行" public "ssh._route" _ "nfs.source" \
|
|
||||||
text "" name pod imports plugin_pod \
|
|
||||||
button "运行" \
|
|
||||||
textarea "" view long \
|
|
||||||
exports mac name
|
|
||||||
|
|
||||||
fun salary "工资单" public \
|
|
||||||
text "9000" label total \
|
|
||||||
text "9000" label base \
|
|
||||||
button "计算"
|
|
||||||
|
|
||||||
let total = $1 || $2
|
|
||||||
let base = $2 || $1
|
|
||||||
|
|
||||||
let house = $base * 120 / 1000
|
|
||||||
let old = $base * 80 / 1000
|
|
||||||
let tread = $base * 20 / 1000
|
|
||||||
let job = $base * 2 / 1000
|
|
||||||
let get = $total - $house - $old - $tread - $job
|
|
||||||
|
|
||||||
let tax = 0
|
|
||||||
let rest = $get
|
|
||||||
let list = [85000 45 60000 35 40000 30 30000 25 17000 20 8000 10 5000 3]
|
|
||||||
for i amount percent in list
|
|
||||||
if $rest > $amount
|
|
||||||
let tax = $tax + ($rest - $amount) * $percent / 100
|
|
||||||
let rest = $amount
|
|
||||||
end
|
|
||||||
end
|
|
||||||
let rest = $get - $tax
|
|
||||||
|
|
||||||
append "公积金" $house
|
|
||||||
append "养老保险" $old
|
|
||||||
append "医疗保险" $tread
|
|
||||||
append "失业保险" $job
|
|
||||||
append "个税" $tax
|
|
||||||
append "结余" $rest
|
|
||||||
end
|
|
||||||
|
|
||||||
kit svg "绘图" public "web.wiki.svg" \
|
|
||||||
text "download/usr/script/teacherInfo.svg" name svg view long \
|
|
||||||
feature display svg \
|
|
||||||
button "查看"
|
|
||||||
|
|
||||||
|
|
@ -1 +0,0 @@
|
|||||||
|
|
@ -1,33 +0,0 @@
|
|||||||
Plugin["favor/macro.js"] = function(field, option, output) {return {
|
|
||||||
Record: function() {
|
|
||||||
if (confirm("run script "+option.mac.value)) {
|
|
||||||
page.script("record", option.mac.value)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Replay: function() {
|
|
||||||
if (confirm("run script "+option.mac.value)) {
|
|
||||||
page.script("replay", option.mac.value)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
all: function() {var plugin = field.Plugin
|
|
||||||
option.mac.value = "", plugin.Runs(window.event, function() {
|
|
||||||
page.Sync("plugin_"+plugin.exports[0]).set(plugin.onexport[plugin.exports[2]||""]("", "name", {name: ""}))
|
|
||||||
})
|
|
||||||
},
|
|
||||||
Run: function(event, args, cb) {var plugin = field.Plugin
|
|
||||||
var script = page.script()
|
|
||||||
if (args[0] && !script[args[0]]) {
|
|
||||||
return confirm("create script "+args[0]) && page.script("create", args[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin.msg = args[0]? ({append: ["index", "script"],
|
|
||||||
index: kit.List(script[args[0]], function(item, index) {return index+""}),
|
|
||||||
script: kit.List(script[args[0]], function(item) {return item.join(" ")}),
|
|
||||||
|
|
||||||
}): ({append: ["name", "count"],
|
|
||||||
name: kit.Item(script),
|
|
||||||
count: kit.Item(script, function(key, list) {return list.length+""}),
|
|
||||||
|
|
||||||
}), plugin.display("table", cb)
|
|
||||||
},
|
|
||||||
}}
|
|
@ -1,3 +0,0 @@
|
|||||||
fieldset.item.feature div.output {
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/cli"
|
|
||||||
"contexts/ctx"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: `feature`, Help: `plugin`,
|
|
||||||
Caches: map[string]*ctx.Cache{},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"_index": &ctx.Config{Name: "index", Value: []interface{}{
|
|
||||||
map[string]interface{}{"name": "demo", "help": "demo",
|
|
||||||
"tmpl": "componet", "view": "", "init": "",
|
|
||||||
"type": "public", "ctx": "demo", "cmd": "demo",
|
|
||||||
"args": []interface{}{}, "inputs": []interface{}{
|
|
||||||
map[string]interface{}{"type": "text", "name": "pod", "value": "hello world"},
|
|
||||||
map[string]interface{}{"type": "button", "value": "执行"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"demo": {Name: "demo", Help: "demo", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Echo(kit.Select("hello world", arg, 0))
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Print(cli.Index.Plugin(Index, os.Args[1:]))
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
Plugin["feature/index.js"] = function(field, option, output) {return {
|
|
||||||
}}
|
|
@ -1,42 +0,0 @@
|
|||||||
fun date "每一天" "index.js" "index.css" protected \
|
|
||||||
text "love" name "table" imports plugin_table view tiny \
|
|
||||||
text "2019-10-16" name "起始时间" \
|
|
||||||
text "" name "截止时间" init date \
|
|
||||||
button "日历" action auto \
|
|
||||||
button "记录" cb data \
|
|
||||||
button "展示" cb show \
|
|
||||||
exports index ""
|
|
||||||
|
|
||||||
if $2 == "" || $3 == ""
|
|
||||||
copy skip ssh.data show _ fields id when where what
|
|
||||||
else
|
|
||||||
copy skip cli.date $2 nature $3 space true format '<span class="%s">%s</span>' "s20060102"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
kit progress "任务进度" public "_:web.team.task" "@you" progress \
|
|
||||||
text "task" name table \
|
|
||||||
text "30" name limit \
|
|
||||||
text "0" name offset \
|
|
||||||
feature detail action finish cancel prepare \
|
|
||||||
button "查看" action auto
|
|
||||||
|
|
||||||
kit create "创建任务" public "_:web.team.task" "@you" create \
|
|
||||||
text "task" name table \
|
|
||||||
select "3" name level values 1 values 2 values 3 values 4 values 5 \
|
|
||||||
select "" name class values add values opt values fix \
|
|
||||||
select "" name status values prepare values action values finish values cancel \
|
|
||||||
text "" name begin_time init date width "108px" before br \
|
|
||||||
text "" name close_time init date width "108px" \
|
|
||||||
text "" name target view long before br \
|
|
||||||
textarea "" name detail half "4" \
|
|
||||||
button "添加" before br
|
|
||||||
|
|
||||||
kit select "查看任务" public "_:web.team.task" "@you" \
|
|
||||||
text "task" name table imports pluing_table \
|
|
||||||
text "" name index imports plugin_task_id action auto \
|
|
||||||
button "查看" action auto \
|
|
||||||
button "返回" cb Last \
|
|
||||||
feature detail "修改" "复制" "下载" \
|
|
||||||
exports task_id id
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
|||||||
|
|
||||||
fieldset.item.love.date table td.today {
|
|
||||||
border:solid 2px red;
|
|
||||||
}
|
|
||||||
fieldset.item.love.date table td {
|
|
||||||
text-align:center;
|
|
||||||
min-width:40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldset.item.love.days div.day {
|
|
||||||
margin:8px;
|
|
||||||
border:solid 2px cyan;
|
|
||||||
padding:8px;
|
|
||||||
opacity:0;
|
|
||||||
float:left;
|
|
||||||
}
|
|
||||||
fieldset.item.love.days span.what {
|
|
||||||
font-size:24px;
|
|
||||||
}
|
|
||||||
fieldset.item.love.days span.day0 {
|
|
||||||
font-size:32px;
|
|
||||||
color:red;
|
|
||||||
}
|
|
||||||
fieldset.item.love.days span.day1 {
|
|
||||||
font-size:32px;
|
|
||||||
color:green;
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldset.item.love.media table td {
|
|
||||||
text-align:center;
|
|
||||||
min-width:60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldset.item.love.pics img {
|
|
||||||
border:solid 2px red;
|
|
||||||
margin:10px;
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/cli"
|
|
||||||
"contexts/ctx"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "test", Help: "测试工具",
|
|
||||||
Caches: map[string]*ctx.Cache{},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"_index": &ctx.Config{Name: "index", Value: []interface{}{
|
|
||||||
map[string]interface{}{"name": "demo", "help": "demo",
|
|
||||||
"tmpl": "componet", "view": "", "init": "",
|
|
||||||
"type": "public", "ctx": "demo", "cmd": "demo",
|
|
||||||
"args": []interface{}{}, "inputs": []interface{}{
|
|
||||||
map[string]interface{}{"type": "text", "name": "pod", "value": "hello world"},
|
|
||||||
map[string]interface{}{"type": "button", "value": "执行"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"demo": {Name: "demo", Help: "demo", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Echo(kit.Select("hello world", arg, 0))
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Print(cli.Index.Plugin(Index, os.Args[1:]))
|
|
||||||
}
|
|
@ -1,78 +0,0 @@
|
|||||||
Plugin["love/index.js"] = function(field, option, output) {return {
|
|
||||||
data: function(event) {var plugin = field.Plugin
|
|
||||||
plugin.Run(event, [option.table.value], function(msg) {
|
|
||||||
plugin.ondaemon(msg)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
show: function(event) {var plugin = field.Plugin
|
|
||||||
plugin.Check(event, undefined, function(msg) {
|
|
||||||
plugin.Run(event, [option.table.value], function(msg) {
|
|
||||||
kit.List(msg.Table(), function(line) {
|
|
||||||
kit.Selector(output, ".s"+line.when.split(" ")[0].split("-").join(""), function(item) {
|
|
||||||
kit.classList.add(item.parentNode, "select")
|
|
||||||
item.parentNode.title = line.what
|
|
||||||
plugin.ontoast(line.what, line.where)
|
|
||||||
})
|
|
||||||
}, 200)
|
|
||||||
}, true)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
show_after: function(msg) {
|
|
||||||
kit.Selector(output, ".s"+ kit.time().split(" ")[0].split("-").join(""), function(item) {
|
|
||||||
kit.classList.add(item.parentNode, "today")
|
|
||||||
})
|
|
||||||
},
|
|
||||||
onexport: {"": function(value, name, line) {var plugin = field.Plugin
|
|
||||||
switch (field.Meta.name) {
|
|
||||||
case "days": plugin.flash(line, function(list) {
|
|
||||||
return kit.AppendChilds(output, list)
|
|
||||||
}); break
|
|
||||||
case "date":
|
|
||||||
plugin.Check(event, undefined, function(msg) {
|
|
||||||
kit.Selector(output, ".s"+line.when.split(" ")[0].split("-").join(""), function(item) {
|
|
||||||
kit.classList.add(item.parentNode, "select")
|
|
||||||
item.parentNode.title = line.what
|
|
||||||
})
|
|
||||||
})
|
|
||||||
break
|
|
||||||
case "detail":
|
|
||||||
kit.Change(event.target, function(value) {
|
|
||||||
plugin.Run(event, ["update", option.table.value, option.index.value, line.key, value], function(msg) {
|
|
||||||
kit.Log("ok")
|
|
||||||
})
|
|
||||||
})
|
|
||||||
break
|
|
||||||
}
|
|
||||||
return line.id
|
|
||||||
}},
|
|
||||||
flash: function(line, cb, index, array) {var plugin = field.Plugin
|
|
||||||
var now = new Date()
|
|
||||||
var day = new Date(line.when)
|
|
||||||
var mis = parseInt((day.getTime() - now.getTime()) / 1000 / 3600 / 24)
|
|
||||||
if (array && index == array.length-1) {
|
|
||||||
mis = 999999
|
|
||||||
}
|
|
||||||
|
|
||||||
var list = kit.Span()
|
|
||||||
list.span(["距", "day"], line.when.split(" ")[0])
|
|
||||||
list.span(["在", "day"], line.where)
|
|
||||||
list.span([line.what, "what"])
|
|
||||||
list.span(mis>0? "还有": "过去", [mis, mis>0? "day1": "day0"], "天")
|
|
||||||
|
|
||||||
kit.Opacity(cb([{text: [list.join(""), "div", "day"]}]).last)
|
|
||||||
},
|
|
||||||
Order: function(t, cb, cbs) {var plugin = field.Plugin
|
|
||||||
kit.List(plugin.msg.Table().concat([{when: "9999-01-08", what: "最后一次爱你", where: "北京市"}]), function(line, index, array) {
|
|
||||||
plugin.flash(line, cb, index, array)
|
|
||||||
}, t, cbs)
|
|
||||||
},
|
|
||||||
Flash: function(event) {var plugin = field.Plugin
|
|
||||||
plugin.Order(1000, function(list) {
|
|
||||||
return kit.AppendChilds(output, list)
|
|
||||||
}, function() {
|
|
||||||
output.innerHTML = "", plugin.Order(400, function(list) {
|
|
||||||
return kit.AppendChild(output, list)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}}
|
|
@ -1,103 +0,0 @@
|
|||||||
|
|
||||||
fun date "每一天" "index.js" "index.css" protected \
|
|
||||||
text "love" name "table" imports plugin_table view tiny \
|
|
||||||
text "2019-07-08" name "起始时间" \
|
|
||||||
text "" name "截止时间" init date \
|
|
||||||
button "日历" action auto \
|
|
||||||
button "记录" cb data \
|
|
||||||
button "展示" cb show \
|
|
||||||
exports index ""
|
|
||||||
|
|
||||||
if $2 == "" || $3 == ""
|
|
||||||
copy skip ssh.data show _ fields id when where what
|
|
||||||
else
|
|
||||||
copy skip cli.date $2 nature $3 space true format '<span class="%s">%s</span>' "s20060102"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
fun maps "每一面" "maps.js" "index.css" protected \
|
|
||||||
text "love" name table imports plugin_table \
|
|
||||||
text "" name when init date \
|
|
||||||
text "" name what view long \
|
|
||||||
button "本地" cb Current \
|
|
||||||
text "北京市" name city view tiny \
|
|
||||||
text "弘源首著" name where \
|
|
||||||
button "搜索" cb Search \
|
|
||||||
button "记录" cb Record \
|
|
||||||
button "展示" cb Flashs \
|
|
||||||
exports index ""
|
|
||||||
|
|
||||||
if $2 == "" || $3 == ""
|
|
||||||
copy skip ssh.data show _
|
|
||||||
else
|
|
||||||
copy ssh.data insert _ when _ what _ city _ where _
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
fun days "每一次" "index.js" "index.css" protected \
|
|
||||||
text "love" name table imports plugin_table \
|
|
||||||
text "" name when init date \
|
|
||||||
text "" name what view long \
|
|
||||||
button "记录" \
|
|
||||||
button "展示" cb Flash \
|
|
||||||
exports index ""
|
|
||||||
|
|
||||||
if $2 == "" || $3 == ""
|
|
||||||
copy skip ssh.data show _ fields id when where what
|
|
||||||
else
|
|
||||||
copy ssh.data insert _ when _ what __
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
fun detail "详情" "index.js" protected \
|
|
||||||
text "love" name table imports plugin_table \
|
|
||||||
text "1" name index imports plugin_index action auto view tiny \
|
|
||||||
button "查看"
|
|
||||||
if $1 == "update"
|
|
||||||
copy ssh.data
|
|
||||||
else
|
|
||||||
copy ssh.data show
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
kit append "扩展" "index.js" protected "ssh.data" update _ _ extra \
|
|
||||||
text "love" name table imports plugin_table \
|
|
||||||
text "1" name index imports plugin_index action auto view tiny \
|
|
||||||
text "" name field \
|
|
||||||
text "" name value \
|
|
||||||
button "添加"
|
|
||||||
|
|
||||||
kit pics "图片" "pics.js" "index.css" private "ssh.data" show \
|
|
||||||
text "image" name table imports plugin_table \
|
|
||||||
upfile "" name upload \
|
|
||||||
button "上传" cb upload \
|
|
||||||
button "记录" \
|
|
||||||
button "展示" cb show
|
|
||||||
|
|
||||||
fun delay "以后告诉你" protected \
|
|
||||||
text "delay" name table imports plugin_table \
|
|
||||||
text "" name when init date\
|
|
||||||
text "" name what view long \
|
|
||||||
button "记下了"
|
|
||||||
|
|
||||||
if $2 == "" || $3 == ""
|
|
||||||
copy skip ssh.data show _
|
|
||||||
else
|
|
||||||
copy ssh.data insert _ when _ what __
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
fun media "娱乐" private \
|
|
||||||
text "media" name table imports plugin_table \
|
|
||||||
select "电影" values "电影" values "音乐" values "电视剧" \
|
|
||||||
text "" name title \
|
|
||||||
text "" name link view long \
|
|
||||||
button "记下了"
|
|
||||||
|
|
||||||
if $2 == "" || $3 == "" || $4 == ""
|
|
||||||
copy skip ssh.data show $1 fields id type name link
|
|
||||||
else
|
|
||||||
copy ssh.data insert _ type _ name _ link __
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
|||||||
Plugin["love/maps.js"] = function(field, option, output) {
|
|
||||||
var id
|
|
||||||
return {
|
|
||||||
initMap: function() {var plugin = field.Plugin
|
|
||||||
!id && (id = plugin.id+"map"+plugin.ID())
|
|
||||||
|
|
||||||
var width = field.parentNode.clientWidth-40
|
|
||||||
kit.AppendChilds(output, [{type: "div", data: {id: id}, style: {width: width+"px", height: width*(kit.device.isMobile? 7: 3)/5}}])
|
|
||||||
|
|
||||||
map = new BMap.Map(id)
|
|
||||||
map.addControl(new BMap.NavigationControl())
|
|
||||||
map.addControl(new BMap.ScaleControl())
|
|
||||||
map.addControl(new BMap.OverviewMapControl())
|
|
||||||
map.addControl(new BMap.MapTypeControl())
|
|
||||||
return map
|
|
||||||
},
|
|
||||||
Current: function() {
|
|
||||||
var geo = new BMap.Geolocation()
|
|
||||||
geo.getCurrentPosition(function(p) {
|
|
||||||
option.city.value = p.address.city
|
|
||||||
option.where.value = kit.Value(kit.Value(p.address.street, "")+kit.Value(p.address.street_number, ""), p.address.city)
|
|
||||||
map.centerAndZoom(p.point, map.getZoom())
|
|
||||||
})
|
|
||||||
},
|
|
||||||
Search: function() {var plugin = field.Plugin
|
|
||||||
plugin.initMap()
|
|
||||||
var g = new BMap.Geocoder()
|
|
||||||
g.getPoint(option.where.value, function(p) {
|
|
||||||
kit.Log("where", p)
|
|
||||||
if (!p) {alert("not found"); return}
|
|
||||||
map.centerAndZoom(p, 18)
|
|
||||||
}, option.city.value)
|
|
||||||
},
|
|
||||||
Record: function() {var plugin = field.Plugin
|
|
||||||
function trunc(value, len) {
|
|
||||||
len = kit.Value(len, 1000000)
|
|
||||||
return parseInt(value*len)/parseFloat(len)
|
|
||||||
}
|
|
||||||
var l = map.getCenter()
|
|
||||||
plugin.Run(event, [option.table.value, option.when.value, option.what.value, option.city.value, option.where.value,
|
|
||||||
"longitude", trunc(l.lng), "latitude", trunc(l.lat), "scale", map.getZoom()])
|
|
||||||
},
|
|
||||||
Flashs: function() {var plugin = field.Plugin
|
|
||||||
plugin.initMap(), plugin.Run(event, [option.table.value], function(msg) {
|
|
||||||
kit.List(msg.Table(), plugin.place, 1000)
|
|
||||||
}, true)
|
|
||||||
},
|
|
||||||
place: function(line) {
|
|
||||||
var p = new BMap.Point(line.longitude, line.latitude)
|
|
||||||
map.centerAndZoom(p, line.scale)
|
|
||||||
|
|
||||||
var info = new BMap.InfoWindow(line.when+"<br/>"+line.where, {width: 200, height: 100, title: line.what})
|
|
||||||
map.openInfoWindow(info, map.getCenter())
|
|
||||||
|
|
||||||
output.style.opacity = 0
|
|
||||||
kit.Opacity(output)
|
|
||||||
},
|
|
||||||
onexport: {"": function(value, name, line) {var plugin = field.Plugin
|
|
||||||
plugin.initMap(), plugin.place(line)
|
|
||||||
return line.id
|
|
||||||
}},
|
|
||||||
}}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
|||||||
Plugin["love/pics.js"] = function(field, option, output) {return {
|
|
||||||
onexport: {"": function(value, name, line) {var plugin = field.Plugin
|
|
||||||
kit.AppendChilds(output, [{img: ["/download/"+line.hash], data: {width: output.clientWidth, onclick: function() {
|
|
||||||
plugin.display("table")
|
|
||||||
}}}])
|
|
||||||
}},
|
|
||||||
show: function() {var plugin = field.Plugin
|
|
||||||
var msg = plugin.msg
|
|
||||||
var width = output.clientWidth
|
|
||||||
output.innerHTML = "", kit.List(msg.Table(), function(line) {
|
|
||||||
kit.Opacity(kit.AppendChilds(output, [{img: ["/download/"+line.hash], data: {width: width, onclick: function(event) {
|
|
||||||
}}}]).last)
|
|
||||||
}, 1000, function() {
|
|
||||||
output.innerHTML = "", kit.List(msg.Table(), function(line) {
|
|
||||||
kit.Opacity(kit.AppendChild(output, [{img: ["/download/"+line.hash], data: {width: 200, onclick: function(event) {
|
|
||||||
plugin.ontoast({width: width, height: width*3/5+40,
|
|
||||||
text: {img: ["/download/"+line.hash], data: {width: width-20, onclick: function(event) {
|
|
||||||
plugin.ontoast()
|
|
||||||
}}}, button: ["确定"], cb: function() {
|
|
||||||
plugin.ontoast()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}}}]).last)
|
|
||||||
}, 500)
|
|
||||||
})
|
|
||||||
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
|||||||
fieldset.item.mind.xls div.output table td {
|
|
||||||
text-align:center;
|
|
||||||
min-width:16px;
|
|
||||||
height:16px;
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/cli"
|
|
||||||
"contexts/ctx"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "mind", Help: "思维导图",
|
|
||||||
Caches: map[string]*ctx.Cache{},
|
|
||||||
Configs: map[string]*ctx.Config{},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"doc": {Name: "doc", Help: "文档", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"xls": {Name: "xls", Help: "表格", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
switch len(arg) {
|
|
||||||
case 0:
|
|
||||||
m.Cmdy("ssh.data", "show", "xls")
|
|
||||||
m.Meta["append"] = []string{"id", "title"}
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
var data map[int]map[int]string
|
|
||||||
what := m.Cmd("ssh.data", "show", "xls", arg[0], "format", "object").Append("content")
|
|
||||||
json.Unmarshal([]byte(what), &data)
|
|
||||||
|
|
||||||
max, n := 0, 0
|
|
||||||
for i, v := range data {
|
|
||||||
if i > n {
|
|
||||||
n = i
|
|
||||||
}
|
|
||||||
for i := range v {
|
|
||||||
if i > max {
|
|
||||||
max = i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Log("info", "m: %d n: %d", m, n)
|
|
||||||
|
|
||||||
for k := 0; k < n + 2; k++ {
|
|
||||||
for i := 0; i < max + 2; i++ {
|
|
||||||
m.Push(kit.Format(k), kit.Format(data[k][i]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
m.Cmdy("ssh.data", "insert", "xls", "title", arg[0], "content", arg[1])
|
|
||||||
|
|
||||||
default:
|
|
||||||
data := map[int]map[int]string{}
|
|
||||||
what := m.Cmd("ssh.data", "show", "xls", arg[0], "format", "object").Append("content")
|
|
||||||
json.Unmarshal([]byte(what), &data)
|
|
||||||
|
|
||||||
for i := 1; i < len(arg) - 2; i += 3 {
|
|
||||||
if _, ok := data[kit.Int(arg[i])]; !ok {
|
|
||||||
data[kit.Int(arg[i])] = make(map[int]string)
|
|
||||||
}
|
|
||||||
data[kit.Int(arg[i])][kit.Int(arg[i+1])] = arg[i+2]
|
|
||||||
}
|
|
||||||
m.Cmdy("ssh.data", "update", "xls", arg[0], "content", kit.Format(data))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"ppt": {Name: "ppt", Help: "文稿", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Print(cli.Index.Plugin(Index, os.Args[1:]))
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
Plugin["mind/index.js"] = function(field, option, output) {return {
|
|
||||||
onfigure: shy(function(type, msg, cb) {if (msg.event && msg.event.type == "blur") {return}
|
|
||||||
var plugin = field.Plugin
|
|
||||||
output.innerHTML = "", msg.append && kit.OrderTable(kit.AppendTable(kit.AppendChild(output, "table"), msg.Table(), msg.append), "", function(event, value, name, line, index) {
|
|
||||||
if (name == "id") {
|
|
||||||
plugin.onexport(event, value, name, line)
|
|
||||||
|
|
||||||
} else {
|
|
||||||
var td = event.target
|
|
||||||
function submit(event) {
|
|
||||||
(td.innerText = event.target.value) != value && plugin.Run(event, [option.title.value, name, index-1, event.target.value], plugin.Check)
|
|
||||||
}
|
|
||||||
|
|
||||||
kit.AppendChilds(td, [{type: "input", value: value, data: {onblur: submit, onkeyup: function(event) {
|
|
||||||
switch (event.key) {
|
|
||||||
case "Enter":
|
|
||||||
case "Tab":
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
event.stopPropagation()
|
|
||||||
event.preventDefault()
|
|
||||||
|
|
||||||
}, onkeydown: function(event) {
|
|
||||||
switch (event.key) {
|
|
||||||
case "Enter":
|
|
||||||
var s = td.parentNode[event.shiftKey?"previousSibling":"nextSibling"]
|
|
||||||
s && s.querySelector("td").click()
|
|
||||||
break
|
|
||||||
case "Tab":
|
|
||||||
if (event.shiftKey) {
|
|
||||||
if (td.previousSibling) {
|
|
||||||
td.previousSibling.click()
|
|
||||||
} else {
|
|
||||||
td.parentNode.previousSibling.querySelector("td").click()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (td.nextSibling) {
|
|
||||||
td.nextSibling.click()
|
|
||||||
} else {
|
|
||||||
td.parentNode.nextSibling.querySelector("td").click()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
event.stopPropagation()
|
|
||||||
event.preventDefault()
|
|
||||||
}}}]).first.focus()
|
|
||||||
}
|
|
||||||
}), typeof cb == "function" && cb(msg)
|
|
||||||
}),
|
|
||||||
}}
|
|
@ -1,65 +0,0 @@
|
|||||||
kit xls "表格" "index.js" "index.css" private context find "web.wiki" xls \
|
|
||||||
text "" name title imports plugin_xls_id action auto \
|
|
||||||
text "" name content \
|
|
||||||
button "执行" \
|
|
||||||
button "返回" cb Last \
|
|
||||||
feature style "mind" \
|
|
||||||
exports xls_id id
|
|
||||||
|
|
||||||
kit dir "目录" private "ssh._route" _ "nfs.dir" _ time size line path \
|
|
||||||
text "" name pod imports plugin_pod action auto \
|
|
||||||
text "usr/local/redis-5.0.5/src" name dir imports plugin_dir action auto view long \
|
|
||||||
button "浏览" action auto \
|
|
||||||
button "返回" cb Last \
|
|
||||||
feature display editor \
|
|
||||||
exports dir "" dir
|
|
||||||
|
|
||||||
kit grep "搜索" public "cli.system" grep _ _ "-rn" "--color" cmd_parse cut 3 ":" "file line word" \
|
|
||||||
text "" name txt imports plugin_editor_word \
|
|
||||||
text "usr/local/redis-5.0.5" name dir view long \
|
|
||||||
button "搜索" \
|
|
||||||
exports dir file "" editor_file file "" editor_index line ""
|
|
||||||
|
|
||||||
fun mark "标签" public \
|
|
||||||
text "mark" name table \
|
|
||||||
text "" name file imports plugin_editor_file view long \
|
|
||||||
text "" name index imports plugin_editor_index view tiny \
|
|
||||||
text "" name word imports plugin_editor_word \
|
|
||||||
text "" name mark view long \
|
|
||||||
button "操作" \
|
|
||||||
exports dir file "" editor_index index "" editor_word word
|
|
||||||
|
|
||||||
if $5 == ""
|
|
||||||
copy skip ssh.data show _
|
|
||||||
else
|
|
||||||
copy ssh.data insert _ file _ index _ word _ mark _
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
fun blog "博客" public \
|
|
||||||
text "" name tag \
|
|
||||||
text "" name url view long \
|
|
||||||
button "保存" action auto
|
|
||||||
|
|
||||||
if $2 == ""
|
|
||||||
copy skip ssh.data show blog
|
|
||||||
else
|
|
||||||
copy ssh.data insert blog tag _ url _
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
fun note "记事本" public \
|
|
||||||
text "" name you imports plugin_you action auto \
|
|
||||||
text "" name tip imports plugin_tip view long action auto \
|
|
||||||
button "查看" action auto \
|
|
||||||
button "返回" cb Last \
|
|
||||||
exports tip file tip \
|
|
||||||
feature display inner
|
|
||||||
|
|
||||||
if $2 == "" || $2 ~ ".*/$"
|
|
||||||
copy ssh._route _ context wiki tree __ level local/wiki
|
|
||||||
else
|
|
||||||
copy ssh._route _ context wiki text __ level local/wiki
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1 +0,0 @@
|
|||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
fieldset.item.redis div.output {
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/cli"
|
|
||||||
"contexts/ctx"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: `redis`, Help: `plugin`,
|
|
||||||
Caches: map[string]*ctx.Cache{},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"_index": &ctx.Config{Name: "index", Value: []interface{}{
|
|
||||||
map[string]interface{}{"name": "demo", "help": "demo",
|
|
||||||
"tmpl": "componet", "view": "", "init": "",
|
|
||||||
"type": "public", "ctx": "demo", "cmd": "demo",
|
|
||||||
"args": []interface{}{}, "inputs": []interface{}{
|
|
||||||
map[string]interface{}{"type": "text", "name": "pod", "value": "hello world"},
|
|
||||||
map[string]interface{}{"type": "button", "value": "执行"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"demo": {Name: "demo", Help: "demo", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Echo(kit.Select("hello world", arg, 0))
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Print(cli.Index.Plugin(Index, os.Args[1:]))
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
Script["redis/index.js"] = function(field, option, output) {return {
|
|
||||||
}}
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
|||||||
fun download "下载" public \
|
|
||||||
text "redis-5.0.5.tar.gz" name src view long \
|
|
||||||
button "下载"
|
|
||||||
|
|
||||||
let local = "usr/local/"
|
|
||||||
let path = $local + $1 - ".tar.gz"
|
|
||||||
if $(path $path)
|
|
||||||
return $path
|
|
||||||
end
|
|
||||||
|
|
||||||
let src = "http://download.redis.io/releases/" + $1
|
|
||||||
let usr = $local + $1
|
|
||||||
web.get method GET "" $src save $usr
|
|
||||||
|
|
||||||
tar xvf $usr -C $local
|
|
||||||
make -C $path
|
|
||||||
return $path
|
|
||||||
end
|
|
||||||
|
|
||||||
kit dir "目录" public "nfs.dir" _ time size line path \
|
|
||||||
text "usr/local/redis-5.0.5" name dir imports plugin_dir action auto view long \
|
|
||||||
button "浏览" action auto \
|
|
||||||
button "返回" cb Last \
|
|
||||||
feature display editor \
|
|
||||||
exports dir "" dir
|
|
||||||
|
|
||||||
kit grep "搜索" public "nfs.grep" search _ _ "-rn" "--color" cmd_parse cut 3 ":" "file line word" \
|
|
||||||
text "" name txt imports plugin_editor_word \
|
|
||||||
text "usr/local/redis-5.0.5" name dir view long \
|
|
||||||
button "搜索" \
|
|
||||||
exports dir file "" editor_file file "" editor_index line ""
|
|
||||||
|
|
||||||
fun mark "标签" public \
|
|
||||||
text "mark" name table \
|
|
||||||
text "" name file imports plugin_editor_file view long \
|
|
||||||
text "" name index imports plugin_editor_index view tiny \
|
|
||||||
text "" name word imports plugin_editor_word \
|
|
||||||
text "" name mark view long \
|
|
||||||
button "操作" \
|
|
||||||
exports dir file "" editor_index index "" editor_word word
|
|
||||||
|
|
||||||
if $5 == ""
|
|
||||||
copy skip ssh.data show _
|
|
||||||
else
|
|
||||||
copy ssh.data insert _ file _ index _ word _ mark _
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
fun hello world "" "" public \
|
|
||||||
text "" \
|
|
||||||
button "执行"
|
|
||||||
copy pwd
|
|
||||||
|
|
||||||
end
|
|
@ -1,198 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/cli"
|
|
||||||
"contexts/ctx"
|
|
||||||
_ "contexts/nfs"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"fmt"
|
|
||||||
"math"
|
|
||||||
"math/rand"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Merge(left []int, right []int) []int {
|
|
||||||
result := make([]int, 0, len(left)+len(right))
|
|
||||||
for len(left) > 0 || len(right) > 0 {
|
|
||||||
if len(right) == 0 || (len(left) > 0 && (left[0] < right[0])) {
|
|
||||||
result, left = append(result, left[0]), left[1:]
|
|
||||||
} else {
|
|
||||||
result, right = append(result, right[0]), right[1:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
func MergeSort(m *ctx.Message, level int, data []int) []int {
|
|
||||||
if len(data) < 2 {
|
|
||||||
m.Add("append", kit.Format(level), fmt.Sprintf("[][]"))
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
middle := len(data) / 2
|
|
||||||
m.Add("append", kit.Format(level), fmt.Sprintf("%v%v", data[:middle], data[middle:]))
|
|
||||||
return Merge(MergeSort(m, level+1, data[:middle]), MergeSort(m, level+1, data[middle:]))
|
|
||||||
}
|
|
||||||
func QuickSort(m *ctx.Message, level int, data []int, left int, right int) {
|
|
||||||
if left >= right {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
p, l, r := left, left+1, right
|
|
||||||
for l < r {
|
|
||||||
for ; p < r && data[p] < data[r]; r-- {
|
|
||||||
}
|
|
||||||
if p < r {
|
|
||||||
p, data[p], data[r] = r, data[r], data[p]
|
|
||||||
}
|
|
||||||
for ; l < p && data[l] < data[p]; l++ {
|
|
||||||
}
|
|
||||||
if l < p {
|
|
||||||
p, data[l], data[p] = l, data[p], data[l]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Add("append", kit.Format(level), fmt.Sprintf("%v%v", data[left:p+1], data[p+1:right+1]))
|
|
||||||
QuickSort(m, level+1, data, left, p)
|
|
||||||
QuickSort(m, level+1, data, p+1, right)
|
|
||||||
}
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "sort", Help: "sort code",
|
|
||||||
Caches: map[string]*ctx.Cache{},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"data": &ctx.Config{Name: "data", Value: map[string]interface{}{
|
|
||||||
"seed": []int{47, 59, 81, 40, 56, 0, 94, 11, 18, 25},
|
|
||||||
}},
|
|
||||||
"_index": &ctx.Config{Name: "index", Value: []interface{}{
|
|
||||||
map[string]interface{}{"componet_name": "select", "componet_help": "选择排序",
|
|
||||||
"componet_tmpl": "componet", "componet_view": "componet", "componet_init": "",
|
|
||||||
"componet_type": "public", "componet_ctx": "sort", "componet_cmd": "select",
|
|
||||||
"componet_args": []interface{}{}, "inputs": []interface{}{
|
|
||||||
map[string]interface{}{"type": "text", "name": "pod", "imports": "plugin_pod"},
|
|
||||||
map[string]interface{}{"type": "button", "value": "执行"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"_init": &ctx.Command{Name: "_init", Help: "_init", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if len(arg) > 0 {
|
|
||||||
keys := []string{}
|
|
||||||
for key, _ := range c.Commands {
|
|
||||||
if !strings.HasPrefix(key, "_") && !strings.HasPrefix(key, "/") {
|
|
||||||
keys = append(keys, key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
list := []interface{}{}
|
|
||||||
for _, key := range keys {
|
|
||||||
cmd := c.Commands[key]
|
|
||||||
|
|
||||||
list = append(list, map[string]interface{}{"componet_name": cmd.Name, "componet_help": cmd.Help,
|
|
||||||
"componet_tmpl": "componet", "componet_view": "", "componet_init": "",
|
|
||||||
"componet_ctx": "cli." + arg[0], "componet_cmd": key,
|
|
||||||
"componet_args": []interface{}{"@text", "@total"}, "inputs": []interface{}{
|
|
||||||
map[string]interface{}{"type": "input"},
|
|
||||||
map[string]interface{}{"type": "button", "value": "show"},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Confv("ssh.componet", arg[0], list)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"data": &ctx.Command{Name: "data", Help: "data", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
data := []int{}
|
|
||||||
for i := 0; i < kit.Int(kit.Select("10", arg, 0)); i++ {
|
|
||||||
data = append(data, rand.Intn(kit.Int(kit.Select("100", arg, 1))))
|
|
||||||
}
|
|
||||||
m.Confv("data", "seed", data)
|
|
||||||
m.Echo("data: %v", data)
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"select": &ctx.Command{Name: "select", Help: "select", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
data := append([]int{}, m.Confv("data", "seed").([]int)...)
|
|
||||||
|
|
||||||
m.Echo("data: %v\n", data)
|
|
||||||
for i := 0; i < len(data)-1; i++ {
|
|
||||||
for j := i + 1; j < len(data); j++ {
|
|
||||||
if data[j] < data[i] {
|
|
||||||
data[i], data[j] = data[j], data[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Echo("data: %d %v %v\n", i, data[:i+1], data[i+1:])
|
|
||||||
}
|
|
||||||
m.Echo("data: %v\n", data)
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"insert": &ctx.Command{Name: "insert", Help: "insert", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
data := append([]int{}, m.Confv("data", "seed").([]int)...)
|
|
||||||
|
|
||||||
m.Echo("data: %v\n", data)
|
|
||||||
for i, j := 1, 0; i < len(data); i++ {
|
|
||||||
tmp := data[i]
|
|
||||||
for j = i - 1; j >= 0; j-- {
|
|
||||||
if data[j] < tmp {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
data[j+1] = data[j]
|
|
||||||
}
|
|
||||||
data[j+1] = tmp
|
|
||||||
m.Echo("data: %d %v %v\n", i, data[:i+1], data[i+1:])
|
|
||||||
}
|
|
||||||
m.Echo("data: %v\n", data)
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"bubble": &ctx.Command{Name: "bubble", Help: "bubble", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
data := append([]int{}, m.Confv("data", "seed").([]int)...)
|
|
||||||
m.Echo("data: %v\n", data)
|
|
||||||
for i := 1; i < len(data); i++ {
|
|
||||||
finish := true
|
|
||||||
for j := 0; j < len(data)-i; j++ {
|
|
||||||
if data[j] > data[j+1] {
|
|
||||||
finish, data[j], data[j+1] = false, data[j+1], data[j]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if finish {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
m.Echo("data: %d %v %v\n", i, data[:len(data)-i], data[len(data)-i:])
|
|
||||||
}
|
|
||||||
m.Echo("data: %v\n", data)
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"quick": &ctx.Command{Name: "quick", Help: "quick", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
data := append([]int{}, m.Confv("data", "seed").([]int)...)
|
|
||||||
m.Echo("data: %v\n", data)
|
|
||||||
QuickSort(m, 0, data, 0, len(data)-1)
|
|
||||||
for i := 0; i < len(data); i++ {
|
|
||||||
meta, ok := m.Meta[kit.Format(i)]
|
|
||||||
if !ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
m.Echo("data: %v %v\n", i, meta)
|
|
||||||
}
|
|
||||||
m.Echo("data: %v\n", data)
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"merge": &ctx.Command{Name: "merge", Help: "merge", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
data := append([]int{}, m.Confv("data", "seed").([]int)...)
|
|
||||||
m.Echo("data: %v\n", data)
|
|
||||||
data = MergeSort(m, 0, data)
|
|
||||||
for i := 0; int(math.Exp2(float64(i))) < len(data); i++ {
|
|
||||||
meta, ok := m.Meta[kit.Format(i)]
|
|
||||||
if !ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
m.Echo("data: %v %v\n", i, meta)
|
|
||||||
}
|
|
||||||
m.Echo("data: %v\n", data)
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Print(cli.Index.Plugin(Index, os.Args[1:]))
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/cli"
|
|
||||||
"contexts/ctx"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "test", Help: "测试工具",
|
|
||||||
Caches: map[string]*ctx.Cache{},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"_index": &ctx.Config{Name: "index", Value: []interface{}{
|
|
||||||
map[string]interface{}{"name": "demo", "help": "demo",
|
|
||||||
"tmpl": "componet", "view": "componet", "init": "",
|
|
||||||
"type": "public", "ctx": "demo", "cmd": "demo",
|
|
||||||
"args": []interface{}{}, "inputs": []interface{}{
|
|
||||||
map[string]interface{}{"type": "text", "name": "pod", "value": "hello world"},
|
|
||||||
map[string]interface{}{"type": "button", "value": "执行"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"demo": {Name: "demo", Help: "demo", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Echo(kit.Select("hello world", arg, 0))
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Print(cli.Index.Plugin(Index, os.Args[1:]))
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
Plugin["storage/index.js"] = function(field, option, output) {return {
|
|
||||||
}}
|
|
@ -1,41 +0,0 @@
|
|||||||
|
|
||||||
fun clip "剪切板" public \
|
|
||||||
text "" name you imports plugin_you action auto \
|
|
||||||
text "" name tag \
|
|
||||||
text "" name txt view long \
|
|
||||||
button "保存" action auto
|
|
||||||
|
|
||||||
if $3 == ""
|
|
||||||
copy skip ssh._route _ data show clip
|
|
||||||
else
|
|
||||||
copy ssh._route _ data insert clip tag _ txt _
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
kit data "数据库" public "ssh.data" show \
|
|
||||||
text "" name table imports plugin_table action auto view long \
|
|
||||||
text "" name index imports plugin_index action auto \
|
|
||||||
button "查看" action auto \
|
|
||||||
button "返回" cb Last \
|
|
||||||
exports table table "" index id ""
|
|
||||||
|
|
||||||
kit save "导出" private "ssh.data" export \
|
|
||||||
text "love" name table imports plugin_table \
|
|
||||||
button "导出"
|
|
||||||
|
|
||||||
kit load "导入" private "ssh.data" import \
|
|
||||||
text "love" name table imports plugin_table \
|
|
||||||
text "etc/list.csv" name file \
|
|
||||||
button "导入"
|
|
||||||
|
|
||||||
kit push "上传" private "web./download/" \
|
|
||||||
upfile "" name upload \
|
|
||||||
button "上传" cb upload \
|
|
||||||
button "查看"
|
|
||||||
|
|
||||||
kit git "版本" private "ssh._route" _ "nfs.git" __ \
|
|
||||||
text "" name pod imports plugin_pod action auto \
|
|
||||||
select "" values status values diff commit values values log values init action auto \
|
|
||||||
text "" name txt action auto \
|
|
||||||
button "查看"
|
|
||||||
|
|
@ -1 +0,0 @@
|
|||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
fieldset.item.story div.output {
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/cli"
|
|
||||||
"contexts/ctx"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: `story`, Help: `plugin`,
|
|
||||||
Caches: map[string]*ctx.Cache{},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"_index": &ctx.Config{Name: "index", Value: []interface{}{
|
|
||||||
map[string]interface{}{"name": "demo", "help": "demo",
|
|
||||||
"tmpl": "componet", "view": "", "init": "",
|
|
||||||
"type": "public", "ctx": "demo", "cmd": "demo",
|
|
||||||
"args": []interface{}{}, "inputs": []interface{}{
|
|
||||||
map[string]interface{}{"type": "text", "name": "pod", "value": "hello world"},
|
|
||||||
map[string]interface{}{"type": "button", "value": "执行"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"demo": {Name: "demo", Help: "demo", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Echo(kit.Select("hello world", arg, 0))
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Print(cli.Index.Plugin(Index, os.Args[1:]))
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
Plugin["story/index.js"] = function(field, option, output) {return {
|
|
||||||
}}
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
|||||||
kit share "共享" public "web.chat.share" \
|
|
||||||
select "" name kind values "wiki file" \
|
|
||||||
text "miss.md" name story imports plugin_story view long \
|
|
||||||
button "共享"
|
|
||||||
|
|
||||||
kit note "记事本" public "_:web.wiki.note" "@you" \
|
|
||||||
text "miss.md" name story imports path view long action auto \
|
|
||||||
button "查看" action auto \
|
|
||||||
button "返回" cb Last \
|
|
||||||
exports story file \
|
|
||||||
feature display inner
|
|
||||||
|
|
||||||
kit favor "收藏夹" public "_:web.wiki.story" "@you" favor \
|
|
||||||
text "see" name table imports plugin_story_table action auto \
|
|
||||||
text "" name index imports plugin_story_id view tiny action auto \
|
|
||||||
feature detail "修改" "复制" "下载" \
|
|
||||||
exports story_table table "" story_id id "" \
|
|
||||||
button "记录" action auto \
|
|
||||||
button "返回" cb Last
|
|
||||||
|
|
||||||
kit commit "记录" public "_:web.wiki.story" "@you" commit \
|
|
||||||
text "miss.md" name story imports plugin_story \
|
|
||||||
text "table" name sence \
|
|
||||||
text "hello" name enjoy \
|
|
||||||
textarea "" name happy half 4 \
|
|
||||||
button "提交"
|
|
||||||
|
|
||||||
kit branch "分支" public "ssh._route" _ "web.wiki.story" branch \
|
|
||||||
text "" name dream imports plugin_you \
|
|
||||||
button "查看"
|
|
||||||
|
|
||||||
kit remote "仓库" public "ssh._route" _ "web.wiki.story" remote \
|
|
||||||
text "" name dream imports plugin_you \
|
|
||||||
button "查看"
|
|
||||||
|
|
||||||
kit xls "表格" "index.js" "index.css" private "web.wiki.xls" \
|
|
||||||
text "" name scene imports plugin_xls_id action auto \
|
|
||||||
text "" name content \
|
|
||||||
button "执行" \
|
|
||||||
button "返回" cb Last \
|
|
||||||
feature style "mind" \
|
|
||||||
exports xls_id id
|
|
||||||
|
|
||||||
kit chart "图表" public "web.wiki.chart" \
|
|
||||||
select "" name kind values "chain block" action auto \
|
|
||||||
textarea "" name happy half 4 height "200px" \
|
|
||||||
select "" name kind values "white red yellow green blue black" action auto \
|
|
||||||
select "" name kind values "black blue green yellow red white" action auto \
|
|
||||||
feature display inner \
|
|
||||||
button "查看"
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
fieldset.item.task div.output {
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/cli"
|
|
||||||
"contexts/ctx"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: `task`, Help: `plugin`,
|
|
||||||
Caches: map[string]*ctx.Cache{},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"_index": &ctx.Config{Name: "index", Value: []interface{}{
|
|
||||||
map[string]interface{}{"name": "demo", "help": "demo",
|
|
||||||
"tmpl": "componet", "view": "", "init": "",
|
|
||||||
"type": "public", "ctx": "demo", "cmd": "demo",
|
|
||||||
"args": []interface{}{}, "inputs": []interface{}{
|
|
||||||
map[string]interface{}{"type": "text", "name": "pod", "value": "hello world"},
|
|
||||||
map[string]interface{}{"type": "button", "value": "执行"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"demo": {Name: "demo", Help: "demo", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Echo(kit.Select("hello world", arg, 0))
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Print(cli.Index.Plugin(Index, os.Args[1:]))
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
Script["task/index.js"] = function(field, option, output) {return {
|
|
||||||
}}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
|||||||
kit task "任务" public "web.team.task" \
|
|
||||||
text "task" name table \
|
|
||||||
text "" name title \
|
|
||||||
text "" name content \
|
|
||||||
button "执行"
|
|
||||||
|
|
||||||
kit salary "工资" public "web.mall.salary" \
|
|
||||||
text "salary" name table \
|
|
||||||
text "2019-10" name month init month \
|
|
||||||
text "" name total \
|
|
||||||
text "" name base \
|
|
||||||
text "" name tax \
|
|
||||||
button "执行"
|
|
||||||
|
|
@ -1,293 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/cli"
|
|
||||||
"contexts/ctx"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Input(m *ctx.Message, file string, input chan []string) {
|
|
||||||
f, e := os.Open(file)
|
|
||||||
m.Assert(e)
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
nline := 0
|
|
||||||
for bio := bufio.NewScanner(f); nline < kit.Int(m.Confx("limit")) && bio.Scan(); {
|
|
||||||
word := strings.Split(bio.Text(), " ")
|
|
||||||
if len(word) != 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
uri := word[0][len(m.Conf("prefix0")) : len(word[0])-1]
|
|
||||||
arg := word[1][len(m.Conf("prefix1")) : len(word[1])-1]
|
|
||||||
if len(arg) > m.Confi("nskip") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
input <- []string{fmt.Sprintf("%d", nline), uri, arg}
|
|
||||||
if nline++; nline%kit.Int(m.Confx("nsleep")) == 0 {
|
|
||||||
fmt.Printf("nline:%d sleep 1s...\n", nline)
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Output(m *ctx.Message, output <-chan []string) {
|
|
||||||
os.MkdirAll(m.Conf("outdir"), 0777)
|
|
||||||
|
|
||||||
files := map[string]*os.File{}
|
|
||||||
for {
|
|
||||||
data, ok := <-output
|
|
||||||
if !ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
uri := data[1]
|
|
||||||
if files[uri] == nil {
|
|
||||||
f, _ := os.Create(path.Join(m.Conf("outdir"), strings.Replace(uri, "/", "_", -1)+".txt"))
|
|
||||||
defer f.Close()
|
|
||||||
files[uri] = f
|
|
||||||
}
|
|
||||||
for _, v := range data {
|
|
||||||
fmt.Fprintf(files[uri], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Process(m *ctx.Message, file string, cb func(*ctx.Message, *http.Client, []string, chan []string)) (int32, time.Duration) {
|
|
||||||
nline, begin := int32(0), time.Now()
|
|
||||||
input := make(chan []string, kit.Int(m.Confx("nread")))
|
|
||||||
output := make(chan []string, kit.Int(m.Confx("nwrite")))
|
|
||||||
|
|
||||||
go Input(m, file, input)
|
|
||||||
go Output(m, output)
|
|
||||||
|
|
||||||
wg := sync.WaitGroup{}
|
|
||||||
for i := 0; i < m.Confi("nwork"); i++ {
|
|
||||||
go func(msg *ctx.Message) {
|
|
||||||
wg.Add(1)
|
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
for {
|
|
||||||
word, ok := <-input
|
|
||||||
if !ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
atomic.AddInt32(&nline, 1)
|
|
||||||
cb(msg, &http.Client{Timeout: kit.Duration(m.Conf("timeout"))}, word, output)
|
|
||||||
}
|
|
||||||
}(m.Spawn())
|
|
||||||
}
|
|
||||||
runtime.Gosched()
|
|
||||||
wg.Wait()
|
|
||||||
close(output)
|
|
||||||
return nline, time.Since(begin)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Compare(b1 []byte, b2 []byte) bool {
|
|
||||||
if len(b1) != len(b2) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if bytes.Compare(b1, b2) == 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
var d1, d2 interface{}
|
|
||||||
json.Unmarshal(b1, &d1)
|
|
||||||
json.Unmarshal(b2, &d2)
|
|
||||||
s1, _ := json.Marshal(d1)
|
|
||||||
s2, _ := json.Marshal(d2)
|
|
||||||
if bytes.Compare(s1, s2) == 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "test", Help: "测试工具",
|
|
||||||
Caches: map[string]*ctx.Cache{},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"nread": {Name: "nread", Help: "读取Channel长度", Value: 1},
|
|
||||||
"nwork": {Name: "nwork", Help: "协程数量", Value: 20},
|
|
||||||
"limit": {Name: "limit", Help: "请求数量", Value: 100},
|
|
||||||
"nskip": {Name: "nskip", Help: "请求限长", Value: 100},
|
|
||||||
"nsleep": {Name: "nsleep", Help: "阻塞时长", Value: "10000"},
|
|
||||||
"nwrite": {Name: "nwrite", Help: "输出Channel长度", Value: 1},
|
|
||||||
"outdir": {Name: "outdir", Help: "输出目录", Value: "tmp"},
|
|
||||||
|
|
||||||
"timeout": {Name: "timeout", Help: "请求超时", Value: "10s"},
|
|
||||||
"prefix0": {Name: "prefix0", Help: "请求前缀", Value: "uri["},
|
|
||||||
"prefix1": {Name: "prefix1", Help: "参数前缀", Value: "request_param["},
|
|
||||||
|
|
||||||
"_index": &ctx.Config{Name: "index", Value: []interface{}{
|
|
||||||
map[string]interface{}{"componet_name": "status", "componet_help": "状态",
|
|
||||||
"componet_tmpl": "componet", "componet_view": "Company", "componet_init": "",
|
|
||||||
"componet_type": "private", "componet_ctx": "test", "componet_cmd": "diff",
|
|
||||||
"componet_args": []interface{}{}, "inputs": []interface{}{
|
|
||||||
map[string]interface{}{"type": "text", "name": "pod", "imports": "plugin_pod"},
|
|
||||||
map[string]interface{}{"type": "select", "name": "sub", "values": []interface{}{"status", ""}},
|
|
||||||
map[string]interface{}{"type": "button", "value": "执行"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"diff": {Name: "diff file server1 server2", Form: map[string]int{"nsleep": 1}, Help: "接口对比工具", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if len(arg) < 3 {
|
|
||||||
m.Echo("usage: %v", "diff file server1 server2")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var diff, same, error int32 = 0, 0, 0
|
|
||||||
api := map[string]int{}
|
|
||||||
mu := sync.Mutex{}
|
|
||||||
|
|
||||||
nline, cost := Process(m, arg[0], func(msg *ctx.Message, client *http.Client, word []string, output chan []string) {
|
|
||||||
key, uri, args := word[0], word[1], word[2]
|
|
||||||
mu.Lock()
|
|
||||||
api[uri]++
|
|
||||||
mu.Unlock()
|
|
||||||
|
|
||||||
begin := time.Now()
|
|
||||||
res1, e1 := client.Post(arg[1]+uri, "application/json", bytes.NewReader([]byte(args)))
|
|
||||||
t1 := time.Since(begin)
|
|
||||||
|
|
||||||
begin = time.Now()
|
|
||||||
res2, e2 := client.Post(arg[2]+uri, "application/json", bytes.NewReader([]byte(args)))
|
|
||||||
t2 := time.Since(begin)
|
|
||||||
|
|
||||||
size1, size2 := 0, 0
|
|
||||||
result := "error"
|
|
||||||
var t3, t4 time.Duration
|
|
||||||
if e1 != nil || e2 != nil {
|
|
||||||
atomic.AddInt32(&error, 1)
|
|
||||||
fmt.Printf("%v %d cost: %v/%v error: %v %v\n", key, error, t1, t2, e1, e2)
|
|
||||||
|
|
||||||
} else if res1.StatusCode != http.StatusOK || res2.StatusCode != http.StatusOK {
|
|
||||||
atomic.AddInt32(&error, 1)
|
|
||||||
fmt.Printf("%v %d %s %s cost: %v/%v error: %v %v\n", key, error, "error", uri, t1, t2, res1.StatusCode, res2.StatusCode)
|
|
||||||
|
|
||||||
} else {
|
|
||||||
begin = time.Now()
|
|
||||||
b1, _ := ioutil.ReadAll(res1.Body)
|
|
||||||
b2, _ := ioutil.ReadAll(res2.Body)
|
|
||||||
t3 = time.Since(begin)
|
|
||||||
|
|
||||||
begin = time.Now()
|
|
||||||
var num int32
|
|
||||||
if Compare(b1, b2) {
|
|
||||||
atomic.AddInt32(&same, 1)
|
|
||||||
num = same
|
|
||||||
result = "same"
|
|
||||||
|
|
||||||
} else {
|
|
||||||
atomic.AddInt32(&diff, 1)
|
|
||||||
num = diff
|
|
||||||
result = "diff"
|
|
||||||
|
|
||||||
result1 := []string{
|
|
||||||
fmt.Sprintf("index:%v uri:", key),
|
|
||||||
fmt.Sprintf(uri),
|
|
||||||
fmt.Sprintf(" arguments:"),
|
|
||||||
fmt.Sprintf(args),
|
|
||||||
}
|
|
||||||
|
|
||||||
result1 = append(result1, "\n")
|
|
||||||
result1 = append(result1, "\n")
|
|
||||||
result1 = append(result1, "result0:")
|
|
||||||
result1 = append(result1, string(b1))
|
|
||||||
result1 = append(result1, "\n")
|
|
||||||
result1 = append(result1, "\n")
|
|
||||||
result1 = append(result1, "result1:")
|
|
||||||
result1 = append(result1, string(b2))
|
|
||||||
result1 = append(result1, "\n")
|
|
||||||
result1 = append(result1, "\n")
|
|
||||||
output <- result1
|
|
||||||
}
|
|
||||||
size1 = len(b1)
|
|
||||||
size2 = len(b2)
|
|
||||||
t4 = time.Since(begin)
|
|
||||||
fmt.Printf("%v %d %s %s size: %v/%v cost: %v/%v diff: %v/%v\n", key, num, result, uri, len(b1), len(b2), t1, t2, t3, t4)
|
|
||||||
}
|
|
||||||
|
|
||||||
mu.Lock()
|
|
||||||
m.Add("append", "uri", uri)
|
|
||||||
m.Add("append", "time1", t1/1000000)
|
|
||||||
m.Add("append", "time2", t2/1000000)
|
|
||||||
m.Add("append", "time3", t3/1000000)
|
|
||||||
m.Add("append", "time4", t4/1000000)
|
|
||||||
m.Add("append", "size1", size1)
|
|
||||||
m.Add("append", "size2", size2)
|
|
||||||
m.Add("append", "action", result)
|
|
||||||
mu.Unlock()
|
|
||||||
})
|
|
||||||
|
|
||||||
fmt.Printf("\n\nnuri: %v nreq: %v same: %v diff: %v error: %v cost: %v\n\n", len(api), nline, same, diff, error, cost)
|
|
||||||
|
|
||||||
m.Sort("time1", "int").Table()
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"cost": {Name: "cost file server nroute", Help: "接口耗时测试", Form: map[string]int{"nwork": 1, "limit": 1, "nsleep": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
var success int32 = 0
|
|
||||||
var times time.Duration
|
|
||||||
mu := sync.Mutex{}
|
|
||||||
limit := kit.Int(m.Confx("limit"))
|
|
||||||
nline := 0
|
|
||||||
_, cost := Process(m, arg[0], func(msg *ctx.Message, client *http.Client, word []string, output chan []string) {
|
|
||||||
key, uri, args := word[0], word[1], word[2]
|
|
||||||
for _, host := range arg[1:] {
|
|
||||||
fmt.Printf("%v/%v post: %v\t%v\n", key, limit, host+uri, args)
|
|
||||||
|
|
||||||
begin := time.Now()
|
|
||||||
res, err := client.Post(host+uri, "application/json", bytes.NewReader([]byte(args)))
|
|
||||||
if res.StatusCode == http.StatusOK {
|
|
||||||
io.Copy(ioutil.Discard, res.Body)
|
|
||||||
atomic.AddInt32(&success, 1)
|
|
||||||
} else {
|
|
||||||
fmt.Printf("%v/%v error: %v\n", key, limit, err)
|
|
||||||
}
|
|
||||||
t := time.Since(begin)
|
|
||||||
times += t
|
|
||||||
|
|
||||||
mu.Lock()
|
|
||||||
nline++
|
|
||||||
m.Add("append", "host", host)
|
|
||||||
m.Add("append", "uri", uri)
|
|
||||||
m.Add("append", "cost", t/1000000)
|
|
||||||
mu.Unlock()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
m.Sort("cost", "int_r")
|
|
||||||
m.Echo("\n\nnclient: %v nreq: %v success: %v time: %v average: %vms",
|
|
||||||
m.Confx("nwork"), nline, success, cost, int(times)/int(nline)/1000000)
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"cmd": {Name: "cmd file", Help: "生成测试命令", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
str := kit.Select("./hey -n 10000 -c 100 -m POST -T \"application/json\" -d '%s' http://127.0.0.1:6363%s\n", arg, 1)
|
|
||||||
Process(m, arg[0], func(msg *ctx.Message, client *http.Client, word []string, output chan []string) {
|
|
||||||
m.Echo(str, word[2], word[1])
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Print(cli.Index.Plugin(Index, os.Args[1:]))
|
|
||||||
}
|
|
@ -1,253 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/cli"
|
|
||||||
"contexts/ctx"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "tmux", Help: "终端管理",
|
|
||||||
Caches: map[string]*ctx.Cache{},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"mux": &ctx.Config{Name: "mux", Value: map[string]interface{}{
|
|
||||||
"cmd_timeout": "100ms",
|
|
||||||
"view": map[string]interface{}{
|
|
||||||
"session": []interface{}{
|
|
||||||
"session_id",
|
|
||||||
"session_name",
|
|
||||||
"session_windows",
|
|
||||||
"session_height",
|
|
||||||
"session_width",
|
|
||||||
"session_created_string",
|
|
||||||
},
|
|
||||||
"window": []interface{}{
|
|
||||||
"window_id",
|
|
||||||
"window_name",
|
|
||||||
"window_panes",
|
|
||||||
"window_height",
|
|
||||||
"window_width",
|
|
||||||
},
|
|
||||||
"pane": []interface{}{
|
|
||||||
"pane_id",
|
|
||||||
"pane_index",
|
|
||||||
"pane_tty",
|
|
||||||
"pane_height",
|
|
||||||
"pane_width",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"bind": map[string]interface{}{
|
|
||||||
"0": map[string]interface{}{},
|
|
||||||
"1": map[string]interface{}{
|
|
||||||
"x": []interface{}{"kill-session"},
|
|
||||||
},
|
|
||||||
"2": map[string]interface{}{
|
|
||||||
"x": []interface{}{"kill-window"},
|
|
||||||
"s": []interface{}{"swap-window", "-s"},
|
|
||||||
"e": []interface{}{"rename-window"},
|
|
||||||
},
|
|
||||||
"3": map[string]interface{}{
|
|
||||||
"x": []interface{}{"kill-pane"},
|
|
||||||
"b": []interface{}{"break-pane"},
|
|
||||||
"h": []interface{}{"split-window", "-h"},
|
|
||||||
"v": []interface{}{"split-window", "-v"},
|
|
||||||
|
|
||||||
"r": []interface{}{"send-keys"},
|
|
||||||
"p": []interface{}{"pipe-pane"},
|
|
||||||
"g": []interface{}{"capture-pane", "-p"},
|
|
||||||
|
|
||||||
"s": []interface{}{"swap-pane", "-d", "-s"},
|
|
||||||
"mh": []interface{}{"move-pane", "-h", "-s"},
|
|
||||||
"mv": []interface{}{"move-pane", "-v", "-s"},
|
|
||||||
|
|
||||||
"H": []interface{}{"resize-pane", "-L"},
|
|
||||||
"L": []interface{}{"resize-pane", "-R"},
|
|
||||||
"J": []interface{}{"resize-pane", "-D"},
|
|
||||||
"K": []interface{}{"resize-pane", "-U"},
|
|
||||||
"Z": []interface{}{"resize-pane", "-Z"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, Help: "文档管理"},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"mux": &ctx.Command{Name: "mux [session [window [pane]]] args...", Help: "终端管理", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
// 会话列表
|
|
||||||
if len(arg) == 0 {
|
|
||||||
view := kit.View([]string{"session"}, m.Confm("mux", "view"))
|
|
||||||
for _, row := range strings.Split(strings.TrimSpace(m.Cmdx("cli.system", "tmux", "list-sessions", "-F", fmt.Sprintf("#{%s}", strings.Join(view, "},#{")))), "\n") {
|
|
||||||
for j, col := range strings.Split(row, ",") {
|
|
||||||
m.Add("append", view[j], col)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i, k := range m.Meta["append"] {
|
|
||||||
if strings.HasPrefix(k, "session_") {
|
|
||||||
x := strings.TrimPrefix(k, "session_")
|
|
||||||
m.Meta["append"][i] = x
|
|
||||||
m.Meta[x] = m.Meta[k]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Table()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if v := m.Confv("mux", []string{"bind", "0", arg[0]}); v != nil {
|
|
||||||
m.Cmdy("cli.system", "tmux", v, arg[1:])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//窗口列表
|
|
||||||
if len(arg) == 1 {
|
|
||||||
view := kit.View([]string{"window"}, m.Confm("mux", "view"))
|
|
||||||
for _, row := range strings.Split(strings.TrimSpace(m.Cmdx("cli.system", "tmux", "list-windows", "-t", arg[0], "-F", fmt.Sprintf("#{%s}", strings.Join(view, "},#{")))), "\n") {
|
|
||||||
for j, col := range strings.Split(row, ",") {
|
|
||||||
m.Add("append", view[j], col)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i, k := range m.Meta["append"] {
|
|
||||||
if strings.HasPrefix(k, "window_") {
|
|
||||||
x := strings.TrimPrefix(k, "window_")
|
|
||||||
m.Meta["append"][i] = x
|
|
||||||
m.Meta[x] = m.Meta[k]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Table()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch arg[1] {
|
|
||||||
// 创建会话
|
|
||||||
case "create":
|
|
||||||
m.Cmdy("cli.system", "tmux", "new-session", "-s", arg[0], arg[2:], "-d", "cmd_env", "TMUX", "")
|
|
||||||
return
|
|
||||||
// 检查会话
|
|
||||||
case "exist":
|
|
||||||
m.Cmdy("cli.system", "tmux", "has-session", "-t", arg[0])
|
|
||||||
return
|
|
||||||
// 会话操作
|
|
||||||
default:
|
|
||||||
if v := m.Confv("mux", []string{"bind", "1", arg[1]}); v != nil {
|
|
||||||
m.Cmdy("cli.system", "tmux", v, "-t", arg[0], arg[2:])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
target := fmt.Sprintf("%s:%s", arg[0], arg[1])
|
|
||||||
// 面板列表
|
|
||||||
if len(arg) == 2 {
|
|
||||||
view := kit.View([]string{"pane"}, m.Confm("mux", "view"))
|
|
||||||
for _, row := range strings.Split(strings.TrimSpace(m.Cmdx("cli.system", "tmux", "list-panes", "-t", target, "-F", fmt.Sprintf("#{%s}", strings.Join(view, "},#{")))), "\n") {
|
|
||||||
for j, col := range strings.Split(row, ",") {
|
|
||||||
m.Add("append", view[j], col)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i, k := range m.Meta["append"] {
|
|
||||||
if strings.HasPrefix(k, "pane_") {
|
|
||||||
x := strings.TrimPrefix(k, "pane_")
|
|
||||||
m.Meta["append"][i] = x
|
|
||||||
m.Meta[x] = m.Meta[k]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Table()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch arg[2] {
|
|
||||||
// 创建窗口
|
|
||||||
case "create":
|
|
||||||
m.Cmdy("cli.system", "tmux", "new-window", "-t", arg[0], "-n", arg[1], arg[3:])
|
|
||||||
return
|
|
||||||
// 窗口操作
|
|
||||||
default:
|
|
||||||
if v := m.Confv("mux", []string{"bind", "2", arg[2]}); v != nil {
|
|
||||||
m.Cmdy("cli.system", "tmux", v, arg[3:], "-t", target)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 面板内容
|
|
||||||
if target = fmt.Sprintf("%s:%s.%s", arg[0], arg[1], arg[2]); len(arg) == 3 {
|
|
||||||
m.Cmdy("cli.system", "tmux", "capture-pane", "-t", target, "-p")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch arg[3] {
|
|
||||||
case "split":
|
|
||||||
ls := strings.Split(m.Cmdx("cli.system", "tmux", "capture-pane", "-t", target, "-p"), "\n")
|
|
||||||
for i := 1; i < len(ls)-1; i++ {
|
|
||||||
for j, v := range strings.Split(ls[i], " ") {
|
|
||||||
m.Push(kit.Format(j), v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Table()
|
|
||||||
|
|
||||||
case "run":
|
|
||||||
m.Cmd("cli.system", "tmux", "send-keys", "-t", target, "clear", "Enter")
|
|
||||||
time.Sleep(kit.Duration(m.Conf("mux", "cmd_timeout")))
|
|
||||||
prompt := strings.TrimSpace(m.Cmdx("cli.system", "tmux", "capture-pane", "-t", target, "-p"))
|
|
||||||
m.Log("info", "wait for prompt %v", prompt)
|
|
||||||
|
|
||||||
m.Cmd("cli.system", "tmux", "send-keys", "-t", target, strings.Join(arg[4:], " "), "Enter")
|
|
||||||
for i := 0; i < 1000; i++ {
|
|
||||||
time.Sleep(kit.Duration(m.Conf("mux", "cmd_timeout")))
|
|
||||||
list := strings.Split(m.Cmdx("cli.system", "tmux", "capture-pane", "-t", target, "-p"), "\n")
|
|
||||||
m.Log("info", "current %v", list)
|
|
||||||
for j := len(list) - 1; j >= 0; j-- {
|
|
||||||
if list[j] != "" {
|
|
||||||
if list[j] == prompt {
|
|
||||||
i = 1000
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if v := m.Confv("mux", []string{"bind", "3", arg[3]}); v != nil {
|
|
||||||
switch arg[3] {
|
|
||||||
case "r":
|
|
||||||
m.Cmd("cli.system", "tmux", "send-keys", "-t", target, "clear", "Enter")
|
|
||||||
m.Cmd("cli.system", "tmux", "clear-history", "-t", target)
|
|
||||||
time.Sleep(kit.Duration("10ms"))
|
|
||||||
|
|
||||||
m.Cmd("cli.system", "tmux", "send-keys", "-t", target, strings.Join(arg[4:], " "), "Enter")
|
|
||||||
time.Sleep(kit.Duration(m.Conf("mux", "cmd_timeout")))
|
|
||||||
m.Cmdy("cli.system", "tmux", "capture-pane", "-t", target, "-p", "-S", "-1000")
|
|
||||||
case "p":
|
|
||||||
m.Cmdy("cli.system", "tmux", "pipe-pane", "-t", target, arg[4:])
|
|
||||||
default:
|
|
||||||
m.Cmdy("cli.system", "tmux", v, arg[4:], "-t", target)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Cmdy("cli.system", "tmux", "send-keys", "-t", target, arg[3:])
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"buf": &ctx.Command{Name: "buf", Help: "缓存管理", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
if len(arg) > 0 {
|
|
||||||
msg := m.Cmd(".buf")
|
|
||||||
arg[0] = msg.Meta[msg.Meta["append"][0]][0]
|
|
||||||
}
|
|
||||||
|
|
||||||
switch len(arg) {
|
|
||||||
case 0:
|
|
||||||
m.Cmdy("cli.system", "tmux", "list-buffer", "cmd_parse", "cut", 3, ":", "cur bytes text")
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
m.Cmdy("cli.system", "tmux", "set-buffer", "-b", arg[0], arg[1])
|
|
||||||
fallthrough
|
|
||||||
case 1:
|
|
||||||
m.Cmdy("cli.system", "tmux", "show-buffer", "-b", arg[0])
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Print(cli.Index.Plugin(Index, os.Args[1:]))
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
Plugin["tmux/index.js"] = function(field, option, output) {return {
|
|
||||||
}}
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
|||||||
|
|
||||||
kit buffer "粘贴板" private buf \
|
|
||||||
text "0" name index imports plugin_tmux_bindex action auto \
|
|
||||||
text "" name txt action auto \
|
|
||||||
button "查看" action auto \
|
|
||||||
button "返回" cb Last \
|
|
||||||
exports tmux_bindex cur
|
|
||||||
|
|
||||||
fun list "列表" "" "" private \
|
|
||||||
text "docker" name table imports plugin_table \
|
|
||||||
text "" name txt \
|
|
||||||
text "" name cmd view long \
|
|
||||||
button "记录" \
|
|
||||||
exports tmux_cmd cmd
|
|
||||||
|
|
||||||
if $2 == "" || $3 == ""
|
|
||||||
copy skip ssh.data show _ fields id txt cmd
|
|
||||||
else
|
|
||||||
copy ssh.data insert _ txt _ cmd __
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
kit session "会话" private mux \
|
|
||||||
button "查看" action auto \
|
|
||||||
exports tmux_sess name
|
|
||||||
|
|
||||||
kit windows "窗口" private mux \
|
|
||||||
text "context" imports plugin_tmux_sess action auto \
|
|
||||||
button "查看" \
|
|
||||||
exports tmux_wins name
|
|
||||||
|
|
||||||
kit pane "面板" private mux \
|
|
||||||
text "context" imports plugin_tmux_sess \
|
|
||||||
text "docker" imports plugin_tmux_wins action auto \
|
|
||||||
button "查看" \
|
|
||||||
exports tmux_pane index
|
|
||||||
|
|
||||||
kit view "内容" private mux \
|
|
||||||
text "context" imports plugin_tmux_sess \
|
|
||||||
text "docker" imports plugin_tmux_wins \
|
|
||||||
text "4" imports plugin_tmux_pane action auto view tiny \
|
|
||||||
button "查看"
|
|
||||||
|
|
||||||
kit cmd "命令" private mux _ _ _ r \
|
|
||||||
text "context" imports plugin_tmux_sess \
|
|
||||||
text "docker" imports plugin_tmux_wins \
|
|
||||||
text "4" imports plugin_tmux_pane view tiny \
|
|
||||||
text "pwd" view full imports plugin_tmux_cmd \
|
|
||||||
button "执行"
|
|
||||||
|
|
||||||
kit list "内容" private mux _ _ _ split \
|
|
||||||
text "context" imports plugin_tmux_sess \
|
|
||||||
text "docker" imports plugin_tmux_wins \
|
|
||||||
text "4" imports plugin_tmux_pane action auto view tiny \
|
|
||||||
button "查看"
|
|
||||||
|
|
||||||
kit json "解析" private "nfs.json" \
|
|
||||||
text "" view full \
|
|
||||||
button "执行"
|
|
||||||
|
|
@ -1 +0,0 @@
|
|||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
fieldset.item.vim div.output {
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/cli"
|
|
||||||
"contexts/ctx"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: `vim`, Help: `plugin`,
|
|
||||||
Caches: map[string]*ctx.Cache{},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"_index": &ctx.Config{Name: "index", Value: []interface{}{
|
|
||||||
map[string]interface{}{"name": "demo", "help": "demo",
|
|
||||||
"tmpl": "componet", "view": "", "init": "",
|
|
||||||
"type": "public", "ctx": "demo", "cmd": "demo",
|
|
||||||
"args": []interface{}{}, "inputs": []interface{}{
|
|
||||||
map[string]interface{}{"type": "text", "name": "pod", "value": "hello world"},
|
|
||||||
map[string]interface{}{"type": "button", "value": "执行"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"demo": {Name: "demo", Help: "demo", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Echo(kit.Select("hello world", arg, 0))
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Print(cli.Index.Plugin(Index, os.Args[1:]))
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
Script["vim/index.js"] = function(field, option, output) {return {
|
|
||||||
}}
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
|||||||
|
|
||||||
kit tips "便签" private "_:web.code.favor" "@you" list \
|
|
||||||
text "tip" name table view tiny \
|
|
||||||
text "" name index imports plugin_vim_favor view tiny action auto \
|
|
||||||
text "" name limit view tiny \
|
|
||||||
text "" name offend view tiny \
|
|
||||||
feature detail "修改" "复制" "下载" \
|
|
||||||
exports vim_favor id \
|
|
||||||
button "查看" action auto \
|
|
||||||
button "返回" cb Last
|
|
||||||
|
|
||||||
kit favor "收藏" private "_:web.code.favor" "@you" post \
|
|
||||||
text "tip" name table view tiny \
|
|
||||||
text "" name tab \
|
|
||||||
text "" name note \
|
|
||||||
text "" name word imports plugin_vim_word \
|
|
||||||
text "" name file imports plugin_vim_file \
|
|
||||||
text "" name line imports plugin_vim_line view tiny \
|
|
||||||
text "" name col imports plugin_vim_col view tiny \
|
|
||||||
button "添加"
|
|
||||||
|
|
||||||
kit editor "编辑器" private "web.code.login" list vim \
|
|
||||||
text "" name vim_sid action auto \
|
|
||||||
text "" name dream imports plugin_you \
|
|
||||||
text "" name topic imports plugin_see \
|
|
||||||
feature detail "prune" "复制" "下载" \
|
|
||||||
exports vim_sid sid \
|
|
||||||
button "查看" action auto \
|
|
||||||
button "返回" cb Last
|
|
||||||
|
|
||||||
kit opens "文件记录" private "web.code.trend" list "vim.opens" \
|
|
||||||
text "" name index imports plugin_vim_opens view tiny action auto \
|
|
||||||
text "" name limit view tiny \
|
|
||||||
text "" name offend view tiny \
|
|
||||||
exports vim_opens id "" vim_file file \
|
|
||||||
button "查看" action auto \
|
|
||||||
button "返回" cb Last
|
|
||||||
|
|
||||||
kit cmds "命令记录" private "web.code.trend" list "vim.cmds" \
|
|
||||||
text "" name index imports plugin_vim_cmds view tiny action auto \
|
|
||||||
text "" name limit view tiny \
|
|
||||||
text "" name offend view tiny \
|
|
||||||
exports vim_cmds id "" vim_file file \
|
|
||||||
button "查看" action auto \
|
|
||||||
button "返回" cb Last
|
|
||||||
|
|
||||||
kit txts "插入记录" private "web.code.trend" list "vim.txts" \
|
|
||||||
text "" name index imports plugin_vim_txts view tiny action auto \
|
|
||||||
text "" name limit view tiny \
|
|
||||||
text "" name offend view tiny \
|
|
||||||
exports vim_txts id "" vim_word word "" vim_file file "" vim_line line "" vim_col col "" \
|
|
||||||
button "查看" action auto \
|
|
||||||
button "返回" cb Last
|
|
||||||
|
|
||||||
kit bufs "文件缓存" private "web.code.state" list vim bufs \
|
|
||||||
text "" name vim_sid action auto \
|
|
||||||
text "tag" name match view tiny \
|
|
||||||
text "" name value view tiny \
|
|
||||||
exports vim_file file "" vim_line line \
|
|
||||||
button "查看" action auto
|
|
||||||
|
|
||||||
kit regs "粘贴缓存" private "web.code.state" list vim regs \
|
|
||||||
text "" name vim_sid action auto \
|
|
||||||
text "reg" name match view tiny \
|
|
||||||
text "" name value view tiny \
|
|
||||||
exports vim_word word \
|
|
||||||
button "查看" action auto
|
|
||||||
|
|
||||||
kit marks "文件标记" private "web.code.state" list vim marks \
|
|
||||||
text "" name vim_sid action auto \
|
|
||||||
text "mark" name match view tiny \
|
|
||||||
text "" name value view tiny \
|
|
||||||
exports vim_file file "" vim_line line "" vim_col col "" \
|
|
||||||
button "查看" action auto
|
|
||||||
|
|
||||||
kit tags "语法标记" private "web.code.state" list vim tags \
|
|
||||||
text "" name vim_sid action auto \
|
|
||||||
text "tag" name match view tiny \
|
|
||||||
text "" name value view tiny \
|
|
||||||
exports vim_file file "" vim_line line "" vim_word tag "" \
|
|
||||||
button "查看" action auto
|
|
||||||
|
|
||||||
kit fixs "项目索引" private "web.code.state" list vim fixs \
|
|
||||||
text "" name vim_sid action auto \
|
|
||||||
text "files" name value view tiny \
|
|
||||||
text "" name value view tiny \
|
|
||||||
exports vim_file file "" vim_line line "" vim_word word "" \
|
|
||||||
button "查看" action auto
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
|||||||
fieldset.item.demo div.output {
|
|
||||||
}
|
|
@ -1,238 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/cli"
|
|
||||||
"contexts/ctx"
|
|
||||||
"contexts/web"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"crypto/sha1"
|
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
|
||||||
"encoding/xml"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"sort"
|
|
||||||
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Marshal(m *ctx.Message, meta string) string {
|
|
||||||
b, e := xml.Marshal(struct {
|
|
||||||
CreateTime int64
|
|
||||||
FromUserName string
|
|
||||||
ToUserName string
|
|
||||||
MsgType string
|
|
||||||
Content string
|
|
||||||
XMLName xml.Name `xml:"xml"`
|
|
||||||
}{
|
|
||||||
time.Now().Unix(),
|
|
||||||
m.Option("selfname"), m.Option("username"),
|
|
||||||
meta, strings.Join(m.Meta["result"], ""), xml.Name{},
|
|
||||||
})
|
|
||||||
m.Assert(e)
|
|
||||||
m.Set("append").Set("result").Echo(string(b))
|
|
||||||
return string(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "weixin", Help: "微信后台",
|
|
||||||
Caches: map[string]*ctx.Cache{},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"chat": &ctx.Config{Name: "chat", Value: map[string]interface{}{
|
|
||||||
"appid": "", "appmm": "", "token": "", "site": "https://shylinux.com",
|
|
||||||
"auth": "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=STATE#wechat_redirect",
|
|
||||||
"access": map[string]interface{}{"token": "", "expire": 0, "url": "/cgi-bin/token?grant_type=client_credential"},
|
|
||||||
"ticket": map[string]interface{}{"value": "", "expire": 0, "url": "/cgi-bin/ticket/getticket?type=jsapi"},
|
|
||||||
}, Help: "聊天记录"},
|
|
||||||
"mp": &ctx.Config{Name: "chat", Value: map[string]interface{}{
|
|
||||||
"appid": "", "appmm": "", "token": "", "site": "https://shylinux.com",
|
|
||||||
"auth": "/sns/jscode2session?grant_type=authorization_code",
|
|
||||||
"tool_path": "/Applications/wechatwebdevtools.app/Contents/MacOS/cli",
|
|
||||||
"project_path": "/Users/shaoying/context/usr/client/mp",
|
|
||||||
}, Help: "聊天记录"},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"access": &ctx.Command{Name: "access", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Option("format", "object")
|
|
||||||
m.Option("temp_expire", "1")
|
|
||||||
now := kit.Int(time.Now().Unix())
|
|
||||||
|
|
||||||
access := m.Confm("chat", "access")
|
|
||||||
if kit.Int(access["expire"]) < now {
|
|
||||||
msg := m.Cmd("web.get", "wexin", access["url"], "appid", m.Conf("chat", "appid"), "secret", m.Conf("chat", "appmm"), "temp", "data")
|
|
||||||
access["token"] = msg.Append("access_token")
|
|
||||||
access["expire"] = int(msg.Appendi("expires_in")) + now
|
|
||||||
}
|
|
||||||
m.Echo("%v", access["token"])
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"ticket": &ctx.Command{Name: "ticket", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Option("format", "object")
|
|
||||||
m.Option("temp_expire", "1")
|
|
||||||
now := kit.Int(time.Now().Unix())
|
|
||||||
|
|
||||||
ticket := m.Confm("chat", "ticket")
|
|
||||||
if kit.Int(ticket["expire"]) < now {
|
|
||||||
msg := m.Cmd("web.get", "wexin", ticket["url"], "access_token", m.Cmdx(".access"), "temp", "data")
|
|
||||||
ticket["value"] = msg.Append("ticket")
|
|
||||||
ticket["expire"] = int(msg.Appendi("expires_in")) + now
|
|
||||||
}
|
|
||||||
m.Echo("%v", ticket["value"])
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"js_token": &ctx.Command{Name: "js_token", Help: "zhihu", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
nonce := []string{
|
|
||||||
"jsapi_ticket=" + m.Cmdx(".ticket"),
|
|
||||||
"noncestr=" + m.Append("nonce", "what"),
|
|
||||||
"timestamp=" + m.Append("timestamp", kit.Int(time.Now())),
|
|
||||||
"url=" + m.Append("url", m.Conf("chat", "site")+m.Option("index_url")),
|
|
||||||
}
|
|
||||||
sort.Strings(nonce)
|
|
||||||
h := sha1.Sum([]byte(strings.Join(nonce, "&")))
|
|
||||||
|
|
||||||
m.Append("signature", hex.EncodeToString(h[:]))
|
|
||||||
m.Append("appid", m.Conf("chat", "appid"))
|
|
||||||
m.Append("remote_ip", m.Option("remote_ip"))
|
|
||||||
m.Append("auth2.0", fmt.Sprintf(m.Conf("chat", "auth"), m.Conf("chat", "appid"),
|
|
||||||
url.QueryEscape(fmt.Sprintf("%s%s", m.Conf("chat", "site"), m.Option("index_url"))), kit.Select("snsapi_base", m.Option("scope"))))
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
|
|
||||||
"/chat": &ctx.Command{Name: "user", Help: "应用示例", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
// 信息验证
|
|
||||||
nonce := []string{m.Option("timestamp"), m.Option("nonce"), m.Conf("chat", "token")}
|
|
||||||
sort.Strings(nonce)
|
|
||||||
h := sha1.Sum([]byte(strings.Join(nonce, "")))
|
|
||||||
if hex.EncodeToString(h[:]) == m.Option("signature") {
|
|
||||||
// m.Echo(m.Option("echostr"))
|
|
||||||
} else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解析数据
|
|
||||||
var data struct {
|
|
||||||
MsgId int64
|
|
||||||
CreateTime int64
|
|
||||||
ToUserName string
|
|
||||||
FromUserName string
|
|
||||||
MsgType string
|
|
||||||
Content string
|
|
||||||
}
|
|
||||||
r := m.Optionv("request").(*http.Request)
|
|
||||||
m.Assert(xml.NewDecoder(r.Body).Decode(&data))
|
|
||||||
m.Option("username", data.FromUserName)
|
|
||||||
m.Option("selfname", data.ToUserName)
|
|
||||||
|
|
||||||
// 创建会话
|
|
||||||
m.Option("sessid", m.Cmdx("aaa.user", "session", "select"))
|
|
||||||
m.Option("bench", m.Cmdx("aaa.sess", "bench", "select"))
|
|
||||||
|
|
||||||
m.Option("current_ctx", kit.Select("chat", m.Magic("bench", "current_ctx")))
|
|
||||||
|
|
||||||
switch data.MsgType {
|
|
||||||
case "text":
|
|
||||||
m.Echo(web.Merge(m, map[string]interface{}{"path": "chat"}, m.Conf("chat", "site"), "sessid", m.Option("sessid")))
|
|
||||||
if !m.Cmds("aaa.auth", "username", m.Option("usernmae"), "data", "chat.default") && m.Option("username") != m.Conf("runtime", "work.name") {
|
|
||||||
if m.Cmds("ssh.work", "share", m.Option("username")) {
|
|
||||||
m.Cmd("aaa.auth", "username", m.Option("username"), "data", "nickname", "someone")
|
|
||||||
m.Cmds("aaa.auth", "username", m.Option("username"), "data", "chat.default", m.Spawn().Cmdx(".ocean", "spawn", "", m.Option("username")+"@"+m.Conf("runtime", "work.name")))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Marshal(m, "text")
|
|
||||||
return
|
|
||||||
// 执行命令
|
|
||||||
cmd := strings.Split(data.Content, " ")
|
|
||||||
if !m.Cmds("aaa.work", m.Option("bench"), "right", data.FromUserName, "chat", cmd[0]) {
|
|
||||||
m.Echo("no right %s %s", "chat", cmd[0])
|
|
||||||
} else if m.Cmdy("cli.source", data.Content); m.Appends("redirect") {
|
|
||||||
}
|
|
||||||
Marshal(m, "text")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"share": &ctx.Command{Name: "share", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Echo("%s?bench=%s&sessid=%s", m.Conf("chat", "site"), m.Option("bench"), m.Option("sessid"))
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"check": &ctx.Command{Name: "check", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
sort.Strings(arg)
|
|
||||||
h := sha1.Sum([]byte(strings.Join(arg, "")))
|
|
||||||
if hex.EncodeToString(h[:]) == m.Option("signature") {
|
|
||||||
m.Echo("true")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
|
|
||||||
"/mp": &ctx.Command{Name: "/mp", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
// 用户登录
|
|
||||||
if m.Options("code") {
|
|
||||||
m.Option("format", "object")
|
|
||||||
msg := m.Cmd("web.get", "wexin", m.Conf("mp", "auth"), "js_code", m.Option("code"), "appid", m.Conf("mp", "appid"), "secret", m.Conf("mp", "appmm"), "parse", "json", "temp", "data")
|
|
||||||
|
|
||||||
// 创建会话
|
|
||||||
if !m.Options("sessid") {
|
|
||||||
m.Cmd("aaa.sess", m.Option("sessid", m.Cmdx("aaa.sess", "mp", "ip", "what")), msg.Append("openid"), "ppid", "what")
|
|
||||||
defer func() {
|
|
||||||
m.Set("result").Echo(m.Option("sessid"))
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Magic("session", "user.openid", msg.Append("openid"))
|
|
||||||
m.Magic("session", "user.expires_in", kit.Int(msg.Append("expires_in"), time.Now()))
|
|
||||||
m.Magic("session", "user.session_key", msg.Append("session_key"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用户信息
|
|
||||||
if m.Options("userInfo") && m.Options("rawData") {
|
|
||||||
h := sha1.Sum([]byte(strings.Join([]string{m.Option("rawData"), kit.Format(m.Magic("session", "user.session_key"))}, "")))
|
|
||||||
if hex.EncodeToString(h[:]) == m.Option("signature") {
|
|
||||||
var info interface{}
|
|
||||||
json.Unmarshal([]byte(m.Option("userInfo")), &info)
|
|
||||||
m.Log("info", "user %v %v", m.Option("sessid"), info)
|
|
||||||
|
|
||||||
m.Magic("session", "user.info", info)
|
|
||||||
m.Magic("session", "user.encryptedData", m.Option("encryptedData"))
|
|
||||||
m.Magic("session", "user.iv", m.Option("iv"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.Option("username", m.Magic("session", "user.openid")) == "" || m.Option("cmd") == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.Option("username") == "o978M0XIrcmco28CU1UbPgNxIL78" {
|
|
||||||
m.Option("username", "shy")
|
|
||||||
}
|
|
||||||
if m.Option("username") == "o978M0ff_Y76hFu1FPLif6hFfmsM" {
|
|
||||||
m.Option("username", "shy")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建空间
|
|
||||||
if !m.Options("bench") && m.Option("bench", m.Cmd("aaa.sess", m.Option("sessid"), "bench").Append("key")) == "" {
|
|
||||||
m.Option("bench", m.Cmdx("aaa.work", m.Option("sessid"), "mp"))
|
|
||||||
}
|
|
||||||
m.Option("current_ctx", kit.Select("chat", m.Magic("bench", "current_ctx")))
|
|
||||||
|
|
||||||
// 执行命令
|
|
||||||
cmd := kit.Trans(m.Optionv("cmd"))
|
|
||||||
if !m.Cmds("aaa.work", m.Option("bench"), "right", m.Option("username"), "mp", cmd[0]) {
|
|
||||||
m.Echo("no right %s %s", "chat", cmd[0])
|
|
||||||
} else if m.Cmdy(cmd); m.Appends("redirect") {
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
"mp": &ctx.Command{Name: "mp", Help: "talk", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Cmdy("cli.system", m.Conf("mp", "tool_path"), arg, m.Conf("mp", "project_path"), "cmd_active", "true")
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var Target = &web.WEB{Context: Index}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Print(cli.Index.Plugin(Index, os.Args[1:]))
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
Plugin["weixin/index.js"] = function(field, option, output) {return {
|
|
||||||
}}
|
|
@ -1,5 +0,0 @@
|
|||||||
fun hello world "" "" public \
|
|
||||||
text "" \
|
|
||||||
button "执行"
|
|
||||||
copy pwd
|
|
||||||
end
|
|
@ -1,3 +0,0 @@
|
|||||||
fieldset.item.zsh div.output {
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"contexts/cli"
|
|
||||||
"contexts/ctx"
|
|
||||||
"toolkit"
|
|
||||||
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: `zsh`, Help: `plugin`,
|
|
||||||
Caches: map[string]*ctx.Cache{},
|
|
||||||
Configs: map[string]*ctx.Config{
|
|
||||||
"_index": &ctx.Config{Name: "index", Value: []interface{}{
|
|
||||||
map[string]interface{}{"name": "demo", "help": "demo",
|
|
||||||
"tmpl": "componet", "view": "", "init": "",
|
|
||||||
"type": "public", "ctx": "demo", "cmd": "demo",
|
|
||||||
"args": []interface{}{}, "inputs": []interface{}{
|
|
||||||
map[string]interface{}{"type": "text", "name": "pod", "value": "hello world"},
|
|
||||||
map[string]interface{}{"type": "button", "value": "执行"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"demo": {Name: "demo", Help: "demo", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
m.Echo(kit.Select("hello world", arg, 0))
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Print(cli.Index.Plugin(Index, os.Args[1:]))
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
Script["zsh/index.js"] = function(field, option, output) {return {
|
|
||||||
}}
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
|||||||
|
|
||||||
kit file "文件" private "_:web.code.favor" "@you" file \
|
|
||||||
text "file" name table view tiny \
|
|
||||||
text "" name index imports plugin_zsh_block action auto view tiny \
|
|
||||||
text "" name limit view tiny \
|
|
||||||
text "" name offend view tiny \
|
|
||||||
exports zsh_block id \
|
|
||||||
button "查看" action auto \
|
|
||||||
button "返回" cb Last
|
|
||||||
|
|
||||||
kit tips "便签" private "_:web.code.favor" "@you" list \
|
|
||||||
text "tip" name table view tiny \
|
|
||||||
text "" name index imports plugin_zsh_favor view tiny action auto \
|
|
||||||
text "" name limit view tiny \
|
|
||||||
text "" name offend view tiny \
|
|
||||||
feature detail "修改" "复制" "下载" \
|
|
||||||
exports zsh_favor id \
|
|
||||||
button "查看" action auto \
|
|
||||||
button "返回" cb Last
|
|
||||||
|
|
||||||
kit favor "收藏" private "_:web.code.favor" "@you" post \
|
|
||||||
text "tip" name table view tiny \
|
|
||||||
text "" name tab \
|
|
||||||
text "" name note \
|
|
||||||
text "" name word imports plugin_zsh_cmd \
|
|
||||||
button "添加"
|
|
||||||
|
|
||||||
kit terminal "终端" private "web.code.login" list zsh \
|
|
||||||
text "" name zsh_sid action auto \
|
|
||||||
text "" name dream imports plugin_you \
|
|
||||||
text "" name topic imports plugin_see \
|
|
||||||
feature detail "prune" "修改" "复制" "下载" \
|
|
||||||
exports zsh_sid sid \
|
|
||||||
button "查看" action auto \
|
|
||||||
button "返回" cb Last
|
|
||||||
|
|
||||||
kit history "命令" private "web.code.trend" list "zsh.history" \
|
|
||||||
text "" name index imports plugin_zsh_history view tiny action auto \
|
|
||||||
text "" name limit view tiny \
|
|
||||||
text "" name offend view tiny \
|
|
||||||
exports zsh_history id "" zsh_cmd cmd "" \
|
|
||||||
button "查看" action auto \
|
|
||||||
button "返回" cb Last
|
|
||||||
|
|
||||||
kit free "内存" private "web.code.trend" list "zsh.free" \
|
|
||||||
text "" name index imports plugin_zsh_free view tiny action auto \
|
|
||||||
text "" name limit view tiny \
|
|
||||||
text "" name offend view tiny \
|
|
||||||
exports zsh_free id \
|
|
||||||
button "查看" action auto \
|
|
||||||
button "返回" cb Last
|
|
||||||
|
|
||||||
kit env "环境" private "web.code.state" list zsh env \
|
|
||||||
text "" name zsh_sid action auto \
|
|
||||||
text "name" name match view tiny \
|
|
||||||
text "" name value view tiny \
|
|
||||||
button "查看" action auto
|
|
||||||
|
|
||||||
kit ps "进程" private "web.code.state" list zsh ps \
|
|
||||||
text "" name zsh_sid action auto \
|
|
||||||
text "PPID" name match view tiny \
|
|
||||||
text "" name value view tiny \
|
|
||||||
button "查看" action auto
|
|
||||||
|
|
||||||
kit df "磁盘" private "web.code.state" list zsh df \
|
|
||||||
text "" name zsh_sid action auto \
|
|
||||||
text "fs" name match view tiny \
|
|
||||||
text "" name value view tiny \
|
|
||||||
button "查看" action auto
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
|||||||
package wuhan
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/shylinux/icebergs"
|
|
||||||
"github.com/shylinux/icebergs/core/team"
|
|
||||||
"github.com/shylinux/toolkits"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Index = &ice.Context{Name: "wuhan", Help: "武汉加油",
|
|
||||||
Caches: map[string]*ice.Cache{},
|
|
||||||
Configs: map[string]*ice.Config{
|
|
||||||
"wuhan": {Name: "wuhan", Help: "武汉", Value: kit.Data(kit.MDB_SHORT, "name")},
|
|
||||||
},
|
|
||||||
Commands: map[string]*ice.Command{
|
|
||||||
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
|
|
||||||
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
|
|
||||||
|
|
||||||
"wuhan": {Name: "wuhan", Help: "武汉", Meta: kit.Dict(
|
|
||||||
"display", "china",
|
|
||||||
), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
||||||
data := kit.UnMarshal(m.Cmdx(ice.WEB_SPIDE, "shy", "raw", "GET", "https://view.inews.qq.com/g2/getOnsInfo?name=wuwei_ww_area_counts"))
|
|
||||||
m.Option("title", kit.Format("疫情分布\n%s", m.Time()))
|
|
||||||
|
|
||||||
suspect := map[string]int{}
|
|
||||||
confirm := map[string]int{}
|
|
||||||
dead := map[string]int{}
|
|
||||||
deal := map[string]int{}
|
|
||||||
|
|
||||||
kit.Fetch(kit.UnMarshal(kit.Value(data, "data").(string)), func(index int, value map[string]interface{}) {
|
|
||||||
area := kit.Select(kit.Format(value["country"]), kit.Format(value["area"]))
|
|
||||||
suspect[area] += kit.Int(value["suspect"])
|
|
||||||
confirm[area] += kit.Int(value["confirm"])
|
|
||||||
dead[area] += kit.Int(value["dead"])
|
|
||||||
deal[area] += kit.Int(value["deal"])
|
|
||||||
})
|
|
||||||
|
|
||||||
for k, v := range suspect {
|
|
||||||
m.Push("name", k)
|
|
||||||
m.Push("suspect", v)
|
|
||||||
m.Push("confirm", confirm[k])
|
|
||||||
m.Push("dead", dead[k])
|
|
||||||
m.Push("deal", deal[k])
|
|
||||||
m.Push("value", confirm[k])
|
|
||||||
}
|
|
||||||
m.Sort("confirm", "int_r")
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() { team.Index.Register(Index, nil) }
|
|
@ -1 +0,0 @@
|
|||||||
# {{title "wuhan"}}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user