From ca7c5dc8fe2fdb9b7dc09545d1740f8d7be71161 Mon Sep 17 00:00:00 2001 From: Azareal Date: Sun, 24 May 2020 08:24:23 +1000 Subject: [PATCH] wip hookgen --- cmd/hook_gen/main.go | 138 ++++++++++++++++++++++++++++++++++++++ cmd/hook_stub_gen/main.go | 110 ++++++++++++++++++++++++++++++ 2 files changed, 248 insertions(+) create mode 100644 cmd/hook_gen/main.go create mode 100644 cmd/hook_stub_gen/main.go diff --git a/cmd/hook_gen/main.go b/cmd/hook_gen/main.go new file mode 100644 index 00000000..86681c55 --- /dev/null +++ b/cmd/hook_gen/main.go @@ -0,0 +1,138 @@ +// +build hookgen + +package main // import "github.com/Azareal/Gosora/hook_gen" + +import ( + "fmt" + "log" + "os" + "bytes" + "strings" + "runtime/debug" + "text/template" + + _ "github.com/Azareal/Gosora/extend" + c "github.com/Azareal/Gosora/common" +) + +type HookVars struct { + Imports []string + Hooks []Hook +} + +type Hook struct { + Name string + Params string + Params2 string + Ret string + Type string + Any bool +} + +// TODO: Make sure all the errors in this file propagate upwards properly +func main() { + // Capture panics instead of closing the window at a superhuman speed before the user can read the message on Windows + defer func() { + if r := recover(); r != nil { + fmt.Println(r) + debug.PrintStack() + return + } + }() + + hooks := make(map[string]int) + for _, pl := range c.Plugins { + if len(pl.Meta.Hooks) > 0 { + for _, hook := range pl.Meta.Hooks { + hooks[hook]++ + } + continue + } + if pl.Init != nil { + if e := pl.Init(pl); e != nil { + log.Print("early plugin init err: ", e) + return + } + } + if pl.Hooks != nil { + log.Print("Hooks not nil for ", pl.UName) + for hook, _ := range pl.Hooks { + hooks[hook] += 1 + } + } + } + log.Printf("hooks: %+v\n", hooks) + + imports := []string{"net/http"} + hookVars := HookVars{imports,nil} + add := func(name, params, ret, htype string) { + var params2 string + first := true + for _, param := range strings.Split(params,",") { + if !first { + params2 += "," + } + pspl := strings.Split(strings.ReplaceAll(strings.TrimSpace(param)," "," ")," ") + params2 += pspl[0] + first = false + } + hookVars.Hooks = append(hookVars.Hooks, Hook{name, params, params2, ret, htype, hooks[name] > 0}) + } + vhookskip := func(name, params string) { + add(name,params,"(bool, RouteError)","VhookSkippable_") + } + vhookskip("forum_check_pre_perms","w http.ResponseWriter,r *http.Request,u *User,fid *int,h *Header") + vhookskip("router_after_filters","w http.ResponseWriter,r *http.Request,prefix string") + vhookskip("router_pre_route","w http.ResponseWriter,r *http.Request,u *User,prefix string") + vhookskip("route_forum_list_start","w http.ResponseWriter,r *http.Request,u *User,h *Header") + vhookskip("route_topic_list_start","w http.ResponseWriter,r *http.Request,u *User,h *Header") + vhooknoret := func(name, params string) { + add(name,params,"","Vhooks") + } + vhooknoret("router_end","w http.ResponseWriter,r *http.Request,u *User,prefix string,extraData string") + vhooknoret("topic_reply_row_assign","r *ReplyUser") + + fileData := `// Code generated by Gosora's Hook Generator. DO NOT EDIT. +/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */ +package common +import ({{range .Imports}} + "{{.}}"{{end}} +) +{{range .Hooks}} +func H_{{.Name}}_hook(t *HookTable, {{.Params}}) {{.Ret}} { {{if .Any}} + hook := t.{{.Type}}["{{.Name}}"] + if hook != nil { + {{if .Ret}}return {{end}}hook({{.Params2}}) + } {{end}} + {{if .Ret}}return false, nil{{end}} +}{{end}} +` + + tmpl := template.Must(template.New("hooks").Parse(fileData)) + var b bytes.Buffer + if e := tmpl.Execute(&b, hookVars); e != nil { + log.Fatal(e) + } + + writeFile("./common/gen_extend.go", string(b.Bytes())) + log.Println("Successfully generated the hooks") +} + +func writeFile(name, content string) { + f, err := os.Create(name) + if err != nil { + log.Fatal(err) + } + _, err = f.WriteString(content) + if err != nil { + log.Fatal(err) + } + err = f.Sync() + if err != nil { + log.Fatal(err) + } + err = f.Close() + if err != nil { + log.Fatal(err) + } +} \ No newline at end of file diff --git a/cmd/hook_stub_gen/main.go b/cmd/hook_stub_gen/main.go new file mode 100644 index 00000000..df9647cc --- /dev/null +++ b/cmd/hook_stub_gen/main.go @@ -0,0 +1,110 @@ +package main // import "github.com/Azareal/Gosora/hook_stub_gen" + +import ( + "fmt" + "log" + "os" + "bytes" + "strings" + "runtime/debug" + "text/template" +) + +type HookVars struct { + Imports []string + Hooks []Hook +} + +type Hook struct { + Name string + Params string + Params2 string + Ret string + Type string + Any bool +} + +// TODO: Make sure all the errors in this file propagate upwards properly +func main() { + // Capture panics instead of closing the window at a superhuman speed before the user can read the message on Windows + defer func() { + if r := recover(); r != nil { + fmt.Println(r) + debug.PrintStack() + return + } + }() + + imports := []string{"net/http"} + hookVars := HookVars{imports,nil} + add := func(name, params, ret, htype string) { + var params2 string + first := true + for _, param := range strings.Split(params,",") { + if !first { + params2 += "," + } + pspl := strings.Split(strings.ReplaceAll(strings.TrimSpace(param)," "," ")," ") + params2 += pspl[0] + first = false + } + hookVars.Hooks = append(hookVars.Hooks, Hook{name, params, params2, ret, htype, true}) + } + vhookskip := func(name, params string) { + add(name,params,"(bool, RouteError)","VhookSkippable_") + } + vhookskip("forum_check_pre_perms","w http.ResponseWriter,r *http.Request,u *User,fid *int,h *Header") + vhookskip("router_after_filters","w http.ResponseWriter,r *http.Request,prefix string") + vhookskip("router_pre_route","w http.ResponseWriter,r *http.Request,u *User,prefix string") + vhookskip("route_forum_list_start","w http.ResponseWriter,r *http.Request,u *User,h *Header") + vhookskip("route_topic_list_start","w http.ResponseWriter,r *http.Request,u *User,h *Header") + vhooknoret := func(name, params string) { + add(name,params,"","Vhooks") + } + vhooknoret("router_end","w http.ResponseWriter,r *http.Request,u *User,prefix string, extraData string") + vhooknoret("topic_reply_row_assign","r *ReplyUser") + + fileData := `// Code generated by Gosora's Hook Generator. DO NOT EDIT. +/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */ +package common +import ({{range .Imports}} + "{{.}}"{{end}} +) +{{range .Hooks}} +func H_{{.Name}}_hook(t *HookTable, {{.Params}}) {{.Ret}} { + {{if .Any}}hook := t.{{.Type}}["{{.Name}}"] + if hook != nil { + {{if .Ret}}return {{end}}hook({{.Params2}}) + } {{end}} + {{if .Ret}}return false, nil{{end}} +}{{end}} +` + + tmpl := template.Must(template.New("hooks").Parse(fileData)) + var b bytes.Buffer + if e := tmpl.Execute(&b, hookVars); e != nil { + log.Fatal(e) + } + + writeFile("./common/gen_extend.go", string(b.Bytes())) + log.Println("Successfully generated the hooks") +} + +func writeFile(name, content string) { + f, err := os.Create(name) + if err != nil { + log.Fatal(err) + } + _, err = f.WriteString(content) + if err != nil { + log.Fatal(err) + } + err = f.Sync() + if err != nil { + log.Fatal(err) + } + err = f.Close() + if err != nil { + log.Fatal(err) + } +} \ No newline at end of file