From f04743c7a55fae45804e15fb02d76ee7e60aafbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Tue, 10 Oct 2023 14:34:36 +0900 Subject: [PATCH] add: postopenapiof codegen --- codegen/postopenapiof/main.go | 51 ++++++++++++++++++++++++++++++++ http.go | 22 +++++++++++++- openapi.go | 25 ++++++++++++++++ openapi_channel.go | 14 +++++++++ openapi_codegen_postopenapiof.go | 23 ++++++++++++++ 5 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 codegen/postopenapiof/main.go create mode 100644 openapi_codegen_postopenapiof.go diff --git a/codegen/postopenapiof/main.go b/codegen/postopenapiof/main.go new file mode 100644 index 0000000..fdd54b5 --- /dev/null +++ b/codegen/postopenapiof/main.go @@ -0,0 +1,51 @@ +package main + +import ( + "os" + "strings" +) + +const head = `// Code generated by codegen/postopenapiof. DO NOT EDIT. + +package nano + +import ( + "io" + "unsafe" + + "github.com/pkg/errors" +) +` + +const template = ` +func (bot *Bot) postOpenAPIof[T any](ep string, body io.Reader) (*[T any], error) { + resp := &struct { + CodeMessageBase + [T any] + }{} + err := bot.PostOpenAPI(ep, resp, body) + if err != nil { + err = errors.Wrap(err, getCallerFuncName()) + return nil, err + } + return (*[T any])(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), nil +} +` + +func main() { + f, err := os.Create("openapi_codegen_postopenapiof.go") + if err != nil { + panic(err) + } + defer f.Close() + _, err = f.WriteString(head) + if err != nil { + panic(err) + } + for _, name := range os.Args[1:] { + _, err = f.WriteString(strings.ReplaceAll(template, "[T any]", name)) + if err != nil { + panic(err) + } + } +} diff --git a/http.go b/http.go index c1af5b8..ae36c60 100644 --- a/http.go +++ b/http.go @@ -1,14 +1,17 @@ package nano import ( + "bytes" + "encoding/json" "fmt" + "io" "net/http" "net/url" "reflect" "strings" ) -// NewHTTPEndpointGetRequestWithAuth 新建带鉴权头的 HTTP 请求 +// NewHTTPEndpointGetRequestWithAuth 新建带鉴权头的 HTTP GET 请求 func NewHTTPEndpointGetRequestWithAuth(ep string, auth string) (req *http.Request, err error) { req, err = http.NewRequest("GET", StandardAPI+ep, nil) if err != nil { @@ -18,6 +21,16 @@ func NewHTTPEndpointGetRequestWithAuth(ep string, auth string) (req *http.Reques return } +// NewHTTPEndpointPostRequestWithAuth 新建带鉴权头的 HTTP POST 请求 +func NewHTTPEndpointPostRequestWithAuth(ep string, auth string, body io.Reader) (req *http.Request, err error) { + req, err = http.NewRequest("POST", StandardAPI+ep, body) + if err != nil { + return + } + req.Header.Add("Authorization", auth) + return +} + // WriteHTTPQueryIfNotNil 如果非空则将请求添加到 baseurl 后 // // ex. WriteHTTPQueryIfNotNil("http://a.com/api", "a", 0, "b", 1, "c", 2) is http://a.com/api?b=1&c=2 @@ -51,3 +64,10 @@ func WriteHTTPQueryIfNotNil(baseurl string, queries ...any) string { } return sb.String()[:sb.Len()-1] } + +// WritePostBodyFromJSON 从 json 结构体 ptr 写入 bytes.Buffer, 忽略 error (内部使用不会出错) +func WritePostBodyFromJSON(ptr any) *bytes.Buffer { + buf := bytes.NewBuffer(make([]byte, 0, 1024)) + _ = json.NewEncoder(buf).Encode(ptr) + return buf +} diff --git a/openapi.go b/openapi.go index f531a78..8ef7ed9 100644 --- a/openapi.go +++ b/openapi.go @@ -2,6 +2,7 @@ package nano import ( "encoding/json" + "io" "net/http" "strconv" "unsafe" @@ -32,3 +33,27 @@ func (bot *Bot) GetOpenAPI(ep string, ptr any) error { } return nil } + +//go:generate go run codegen/postopenapiof/main.go Channel + +// PostOpenAPI 从 ep 得到 json 结构化数据返回值写到 ptr, ptr 必须在开头继承 CodeMessageBase +func (bot *Bot) PostOpenAPI(ep string, ptr any, body io.Reader) error { + req, err := NewHTTPEndpointPostRequestWithAuth(ep, bot.Authorization(), body) + if err != nil { + return errors.Wrap(err, getCallerFuncName()) + } + resp, err := http.DefaultClient.Do(req) + if err != nil { + return errors.Wrap(err, getCallerFuncName()) + } + defer resp.Body.Close() + err = json.NewDecoder(resp.Body).Decode(ptr) + if err != nil { + return errors.Wrap(err, getCallerFuncName()) + } + respbbase := (*CodeMessageBase)(*(*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(&ptr), unsafe.Sizeof(uintptr(0))))) + if respbbase.C != 0 { + return errors.Wrap(errors.New("code: "+strconv.Itoa(respbbase.C)+", msg: "+respbbase.M), getCallerFuncName()) + } + return nil +} diff --git a/openapi_channel.go b/openapi_channel.go index 842a3fb..56c8dde 100644 --- a/openapi_channel.go +++ b/openapi_channel.go @@ -34,3 +34,17 @@ func (bot *Bot) GetChannelsOfGuild(id string) (*ChannelArray, error) { func (bot *Bot) GetChannelByID(id string) (*Channel, error) { return bot.getOpenAPIofChannel("/channels/" + id) } + +// ChannelPost 子频道 post 操作所用对象 +type ChannelPost struct { + Name string `json:"name"` + Type int `json:"type"` + SubType int `json:"sub_type"` + Position int `json:"position"` + ParentID string `json:"parent_id"` + OwnerID string `json:"owner_id,omitempty"` + PrivateType int `json:"private_type"` + PrivateUserIds []string `json:"private_user_ids,omitempty"` + SpeakPermission int `json:"speak_permission,omitempty"` + ApplicationID string `json:"application_id,omitempty"` +} diff --git a/openapi_codegen_postopenapiof.go b/openapi_codegen_postopenapiof.go new file mode 100644 index 0000000..2c751b4 --- /dev/null +++ b/openapi_codegen_postopenapiof.go @@ -0,0 +1,23 @@ +// Code generated by codegen/postopenapiof. DO NOT EDIT. + +package nano + +import ( + "io" + "unsafe" + + "github.com/pkg/errors" +) + +func (bot *Bot) postOpenAPIofChannel(ep string, body io.Reader) (*Channel, error) { + resp := &struct { + CodeMessageBase + Channel + }{} + err := bot.PostOpenAPI(ep, resp, body) + if err != nil { + err = errors.Wrap(err, getCallerFuncName()) + return nil, err + } + return (*Channel)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), nil +}