From f5a2880e6c8af9220d308794fa5236010e071d2d Mon Sep 17 00:00:00 2001 From: shylinux Date: Sat, 8 Sep 2018 06:25:31 +0800 Subject: [PATCH] vps add record --- src/contexts/ctx.go | 5 ++ src/contexts/web/web.go | 149 ++++++++++++++++++++++++---------- usr/template/common/wiki.html | 18 ++-- usr/wiki/context.md | 28 +++++++ usr/wiki/golang.md | 11 +++ 5 files changed, 163 insertions(+), 48 deletions(-) create mode 100644 usr/wiki/context.md create mode 100644 usr/wiki/golang.md diff --git a/src/contexts/ctx.go b/src/contexts/ctx.go index 3b8afeb3..190d7a3f 100644 --- a/src/contexts/ctx.go +++ b/src/contexts/ctx.go @@ -98,6 +98,11 @@ func Chain(m *Message, data interface{}, args ...interface{}) interface{} { // { } i = -2 continue + case []interface{}: + keys = []string{} + for _, v := range arg { + keys = append(keys, fmt.Sprintf("%v", v)) + } case []string: keys = arg keys = strings.Split(strings.Join(arg, "."), ".") diff --git a/src/contexts/web/web.go b/src/contexts/web/web.go index 53d20aff..bcc13006 100644 --- a/src/contexts/web/web.go +++ b/src/contexts/web/web.go @@ -91,35 +91,67 @@ func (web *WEB) Merge(m *ctx.Message, uri string, arg ...string) string { // {{{ func (web *WEB) Trans(m *ctx.Message, key string, hand func(*ctx.Message, *ctx.Context, string, ...string)) { // {{{ web.HandleFunc(key, func(w http.ResponseWriter, r *http.Request) { msg := m.Spawn() - msg.Option("method", r.Method) - msg.Option("path", r.URL.Path) - msg.Option("referer", r.Header.Get("Referer")) + msg.TryCatch(msg, true, func(msg *ctx.Message) { + msg.Option("method", r.Method) + msg.Option("path", r.URL.Path) + msg.Option("referer", r.Header.Get("Referer")) - for _, v := range r.Cookies() { - msg.Option(v.Name, v.Value) - } - for k, v := range r.Form { - msg.Add("option", k, v) - } - - msg.Log("cmd", "%s [] %v", key, msg.Meta["option"]) - msg.Put("option", "request", r).Put("option", "response", w) - hand(msg, msg.Target(), msg.Option("path")) - - switch { - case msg.Has("directory"): - http.ServeFile(w, r, msg.Append("directory")) - case msg.Has("redirect"): - http.Redirect(w, r, msg.Append("redirect"), http.StatusFound) - case msg.Has("template"): - msg.Spawn().Cmd("/render", msg.Meta["template"]) - case msg.Has("append"): - msg.Spawn().Copy(msg, "result").Copy(msg, "append").Cmd("/json") - default: - for _, v := range msg.Meta["result"] { - w.Write([]byte(v)) + remote := r.RemoteAddr + if r.Header.Get("X-Real-Ip") != "" { + remote = r.Header.Get("X-Real-Ip") } - } + + count := 1 + if m.Confv("record", []interface{}{r.URL.Path}) == nil { + m.Confv("record", []interface{}{r.URL.Path}, map[string]interface{}{ + "remote": map[string]interface{}{remote: map[string]interface{}{"time": time.Now().Format("2006/01/02 15:04:05")}}, + "count": count, + }) + } else { + switch v := m.Confv("record", []interface{}{r.URL.Path, "count"}).(type) { + case int: + count = v + case float64: + count = int(v) + default: + count = 0 + } + + if m.Confv("record", []interface{}{r.URL.Path, "remote", remote}) == nil { + m.Confv("record", []interface{}{r.URL.Path, "count"}, count+1) + } else { + msg.Option("last_record_time", m.Confv("record", []interface{}{r.URL.Path, "remote", remote, "time"})) + } + m.Confv("record", []interface{}{r.URL.Path, "remote", remote}, map[string]interface{}{"time": time.Now().Format("2006/01/02 15:04:05")}) + } + msg.Option("record_count", count) + + for _, v := range r.Cookies() { + msg.Option(v.Name, v.Value) + } + for k, v := range r.Form { + msg.Add("option", k, v) + } + + msg.Log("cmd", "%s [] %v", key, msg.Meta["option"]) + msg.Put("option", "request", r).Put("option", "response", w) + hand(msg, msg.Target(), msg.Option("path")) + + switch { + case msg.Has("directory"): + http.ServeFile(w, r, msg.Append("directory")) + case msg.Has("redirect"): + http.Redirect(w, r, msg.Append("redirect"), http.StatusFound) + case msg.Has("template"): + msg.Spawn().Cmd("/render", msg.Meta["template"]) + case msg.Has("append"): + msg.Spawn().Copy(msg, "result").Copy(msg, "append").Cmd("/json") + default: + for _, v := range msg.Meta["result"] { + w.Write([]byte(v)) + } + } + }) }) } @@ -248,18 +280,20 @@ func (web *WEB) Start(m *ctx.Message, arg ...string) bool { // {{{ web.Configs["logheaders"] = &ctx.Config{Name: "日志输出报文头(yes/no)", Value: "no", Help: "日志输出报文头"} m.Capi("nserve", 1) - // yac := m.Sess("tags", m.Sess("yac").Cmd("scan")) - // yac.Cmd("train", "void", "void", "[\t ]+") - // yac.Cmd("train", "other", "other", "[^\n]+") - // yac.Cmd("train", "key", "key", "[A-Za-z_][A-Za-z_0-9]*") - // yac.Cmd("train", "code", "struct", "struct", "key", "\\{") - // yac.Cmd("train", "code", "struct", "\\}", "key", ";") - // yac.Cmd("train", "code", "struct", "typedef", "struct", "key", "key", ";") - // yac.Cmd("train", "code", "function", "key", "\\*", "key", "(", "other") - // yac.Cmd("train", "code", "function", "key", "key", "(", "other") - // yac.Cmd("train", "code", "variable", "struct", "key", "key", "other") - // yac.Cmd("train", "code", "define", "#define", "key", "other") - // + yac := m.Sess("tags", m.Sess("yac").Cmd("scan")) + yac.Cmd("train", "void", "void", "[\t ]+") + yac.Cmd("train", "other", "other", "[^\n]+") + yac.Cmd("train", "key", "key", "[A-Za-z_][A-Za-z_0-9]*") + yac.Cmd("train", "code", "def", "def", "key", "(", "other") + yac.Cmd("train", "code", "def", "class", "key", "other") + yac.Cmd("train", "code", "struct", "struct", "key", "\\{") + yac.Cmd("train", "code", "struct", "\\}", "key", ";") + yac.Cmd("train", "code", "struct", "typedef", "struct", "key", "key", ";") + yac.Cmd("train", "code", "function", "key", "\\*", "key", "(", "other") + yac.Cmd("train", "code", "function", "key", "key", "(", "other") + yac.Cmd("train", "code", "variable", "struct", "key", "key", "other") + yac.Cmd("train", "code", "define", "#define", "key", "other") + if m.Cap("protocol") == "https" { web.Caches["cert"] = &ctx.Cache{Name: "服务证书", Value: m.Conf("cert"), Help: "服务证书"} web.Caches["key"] = &ctx.Cache{Name: "服务密钥", Value: m.Conf("key"), Help: "服务密钥"} @@ -294,6 +328,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", "cmd": &ctx.Config{Name: "cmd", Value: "tmux", Help: "路由数量"}, "cert": &ctx.Config{Name: "cert", Value: "etc/cert.pem", Help: "路由数量"}, "key": &ctx.Config{Name: "key", Value: "etc/key.pem", Help: "路由数量"}, + "record": &ctx.Config{Name: "record", Value: map[string]interface{}{}, Help: "访问记录"}, "wiki_dir": &ctx.Config{Name: "wiki_dir", Value: "usr/wiki", Help: "路由数量"}, "wiki_list_show": &ctx.Config{Name: "wiki_list_show", Value: map[string]interface{}{ "md": true, @@ -1197,7 +1232,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", yac := m.Find("yac.parse4", true) - msg := m.Sess("nfs").Cmd("dir", path.Join(m.Conf("wiki_dir"), m.Option("dir")), "dir_name", "path") + msg := m.Sess("nfs").Cmd("dir", path.Join(m.Conf("wiki_dir"), "src", m.Option("dir")), "dir_name", "path") for i, v := range msg.Meta["filename"] { name := strings.TrimSpace(v) es := strings.Split(name, ".") @@ -1205,6 +1240,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", case "pyc", "o", "gz", "tar": continue case "c": + case "py": case "h": default: continue @@ -1248,7 +1284,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", } if key != "" { m.Confv("define", strings.Join([]string{key, "position", "-2"}, "."), map[string]interface{}{ - "file": strings.TrimPrefix(name, m.Confx("wiki_dir")), + "file": strings.TrimPrefix(name, m.Confx("wiki_dir")+"/src"), "line": line, "type": l.Result(1), }) @@ -1260,12 +1296,39 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", m.Log("fuck", "parse %s", time.Now().Format("2006-01-02 15:04:05")) }}, "/wiki_body": &ctx.Command{Name: "/wiki_body", Help: "维基", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if ls, e := ioutil.ReadFile(path.Join(m.Conf("wiki_dir"), m.Confx("which"))); e == nil { + which := path.Join(m.Conf("wiki_dir"), m.Confx("which")) + st, _ := os.Stat(which) + if ls, e := ioutil.ReadFile(which); e == nil { pre := false es := strings.Split(m.Confx("which"), ".") if len(es) > 0 { switch es[len(es)-1] { case "md": + m.Option("modify_count", 1) + m.Option("modify_time", st.ModTime().Format("2006/01/02 15:03:04")) + + switch v := m.Confv("record", []interface{}{m.Option("path"), "local", "modify_count"}).(type) { + case int: + if m.Confv("record", []interface{}{m.Option("path"), "local", "modify_time"}).(string) != m.Option("modify_time") { + m.Confv("record", []interface{}{m.Option("path"), "local", "modify_time"}, m.Option("modify_time")) + m.Confv("record", []interface{}{m.Option("path"), "local", "modify_count"}, v+1) + } + m.Option("modify_count", v+1) + case float64: + if m.Confv("record", []interface{}{m.Option("path"), "local", "modify_time"}).(string) != m.Option("modify_time") { + m.Confv("record", []interface{}{m.Option("path"), "local", "modify_time"}, m.Option("modify_time")) + m.Confv("record", []interface{}{m.Option("path"), "local", "modify_count"}, v+1) + } + m.Option("modify_count", v+1) + case nil: + m.Confv("record", []interface{}{m.Option("path"), "local"}, map[string]interface{}{ + "modify_count": m.Optioni("modify_count"), + "modify_time": m.Option("modify_time"), + }) + default: + m.Log("fuck", "5") + } + ls = markdown.ToHTML(ls, nil, nil) default: pre = true @@ -1288,7 +1351,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", if v, ok := m.Confv("define", m.Option("query")).(map[string]interface{}); ok { for _, val := range v["position"].([]interface{}) { value := val.(map[string]interface{}) - m.Add("append", "name", fmt.Sprintf("%v#hash_%v", value["file"], value["line"])) + m.Add("append", "name", fmt.Sprintf("src/%v#hash_%v", value["file"], value["line"])) } return } diff --git a/usr/template/common/wiki.html b/usr/template/common/wiki.html index 2ad8bb88..3369db90 100644 --- a/usr/template/common/wiki.html +++ b/usr/template/common/wiki.html @@ -172,7 +172,7 @@ function tags(event) { if (tag && tag.length > 0 && tags_list[tag]) { var position = tags_list[tag].position; if (position.length == 1) { - jumpto("/wiki"+position[0].file+"#hash_"+position[0].line); + jumpto("/wiki/src/"+position[0].file+"#hash_"+position[0].line); } else { jumpto("/wiki/?query="+encodeURIComponent(tag)); } @@ -217,9 +217,17 @@ window.onload = function() { padding:0px; height:16px; } +.record { + margin: 10px 40px; + /* float:right; */ +}
+ {{if option . "modify_time"|meta}} +
上次修订时间: {{option . "modify_time"|meta}} 修订次数: {{option . "modify_count"|meta}}
+ {{end}} +
上次阅读时间: {{option . "last_record_time"|meta}} 总访问量: {{option . "record_count"|meta}}
{{range option . "nline"|meta|list}} @@ -237,10 +245,10 @@ window.onload = function() {
    {{range $i, $v := append . "name"}} {{end}}
      diff --git a/usr/wiki/context.md b/usr/wiki/context.md new file mode 100644 index 00000000..e8460bf1 --- /dev/null +++ b/usr/wiki/context.md @@ -0,0 +1,28 @@ +## 简介 +context 是用 golang 开发的一款系统级应用。 + +- 一种新的应用框架,可以快速开发出各种实用工具。 +- 一种新的编程语言,可以用脚本编写各种业务应用。 +- 通过接口文本化,解除函数之间的硬性依赖,提高代码复用率。 +- 把每个函数当成一个服务来开发,把每个进程当一个集群来开发,实现微集群效应。 +- 每个函数既可以在浏览器中调用,也可以在命令行中调用,更可以当成库函数调用。 + +### 项目进度 +- 2017.11.01 项目启动 +- 2018.07.30 1.0 发布 + +### 相关链接 +- 开发者邮箱: +- 源码: +- 文档: + +### 源码安装 +首先安装好golang开发工具(参考: )。 +``` +$ git clone https://github.com/shylinux/context +$ cd context && make +$ bench +> pwd +> ls +``` + diff --git a/usr/wiki/golang.md b/usr/wiki/golang.md new file mode 100644 index 00000000..bd487b6b --- /dev/null +++ b/usr/wiki/golang.md @@ -0,0 +1,11 @@ +## 简介 +golang 是 google 开发的一种静态的强类型、编译型、并发型、并具有垃圾回收功能的编程语言。 + +- 既有编译语言的严谨与高效,又具有脚本语言的动态与灵活。 + +### 相关链接 +- 官网: +- 源码: + +### 源码安装 +可以去官网下载各种安装包(),直接进行安装。