1
0
mirror of https://github.com/fumiama/NanoBot.git synced 2026-06-06 11:10:24 +08:00

finish half of message

This commit is contained in:
源文雨
2023-10-11 17:50:57 +09:00
parent f2f6f52b8a
commit 64f912e856
20 changed files with 395 additions and 115 deletions

View File

@@ -22,12 +22,11 @@ func (bot *Bot) getOpenAPIof[T any](ep string) (*[T any], error) {
CodeMessageBase
[T any]
}{}
err := bot.GetOpenAPI(ep, resp)
err := bot.GetOpenAPI(ep, "", resp)
if err != nil {
err = errors.Wrap(err, getCallerFuncName())
return nil, err
}
return (*[T any])(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), nil
return (*[T any])(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), err
}
`

View File

@@ -23,12 +23,11 @@ func (bot *Bot) patchOpenAPIof[T any](ep string, body io.Reader) (*[T any], erro
CodeMessageBase
[T any]
}{}
err := bot.PatchOpenAPI(ep, resp, body)
err := bot.PatchOpenAPI(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
return (*[T any])(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), err
}
`

View File

@@ -18,17 +18,16 @@ import (
`
const template = `
func (bot *Bot) postOpenAPIof[T any](ep string, body io.Reader) (*[T any], error) {
func (bot *Bot) postOpenAPIof[T any](ep, contenttype string, body io.Reader) (*[T any], error) {
resp := &struct {
CodeMessageBase
[T any]
}{}
err := bot.PostOpenAPI(ep, resp, body)
err := bot.PostOpenAPI(ep, contenttype, 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
return (*[T any])(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), err
}
`

View File

@@ -23,12 +23,11 @@ func (bot *Bot) putOpenAPIof[T any](ep string, body io.Reader) (*[T any], error)
CodeMessageBase
[T any]
}{}
err := bot.PutOpenAPI(ep, resp, body)
err := bot.PutOpenAPI(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
return (*[T any])(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), err
}
`

7
go.mod
View File

@@ -2,4 +2,9 @@ module github.com/fumiama/NanoBot
go 1.20
require github.com/pkg/errors v0.9.1
require (
github.com/fumiama/go-base16384 v1.7.0
github.com/pkg/errors v0.9.1
)
require golang.org/x/text v0.3.7 // indirect

15
go.sum
View File

@@ -1,2 +1,17 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fumiama/go-base16384 v1.7.0 h1:6fep7XPQWxRlh4Hu+KsdH+6+YdUp+w6CwRXtMWSsXCA=
github.com/fumiama/go-base16384 v1.7.0/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@@ -5,9 +5,8 @@ import (
"strings"
)
// getCallerFuncName 获取调用者函数名
func getCallerFuncName() string {
pc, _, _, ok := runtime.Caller(2)
func getFuncNameWithSkip(n int) string {
pc, _, _, ok := runtime.Caller(n)
if !ok {
return ""
}
@@ -18,3 +17,13 @@ func getCallerFuncName() string {
}
return fullname[i:]
}
// getThisFuncName 获取正在执行的函数名
func getThisFuncName() string {
return getFuncNameWithSkip(1)
}
// getCallerFuncName 获取调用者函数名
func getCallerFuncName() string {
return getFuncNameWithSkip(2)
}

136
http.go
View File

@@ -2,70 +2,63 @@ package nano
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/http"
"net/url"
"os"
"reflect"
"strings"
base14 "github.com/fumiama/go-base16384"
)
// NewHTTPEndpointGetRequestWithAuth 新建带鉴权头的 HTTP GET 请求
func NewHTTPEndpointGetRequestWithAuth(ep string, auth string) (req *http.Request, err error) {
req, err = http.NewRequest("GET", StandardAPI+ep, nil)
func newHTTPEndpointRequestWithAuth(method, contenttype, ep string, auth string, body io.Reader) (req *http.Request, err error) {
req, err = http.NewRequest(method, StandardAPI+ep, body)
if err != nil {
return
}
req.Header.Add("Authorization", auth)
if contenttype == "" {
contenttype = "application/json"
}
req.Header.Add("Content-Type", contenttype)
return
}
// NewHTTPEndpointGetRequestWithAuth 新建带鉴权头的 HTTP GET 请求
func NewHTTPEndpointGetRequestWithAuth(ep string, contenttype string, auth string) (*http.Request, error) {
return newHTTPEndpointRequestWithAuth("GET", contenttype, ep, auth, nil)
}
// NewHTTPEndpointPutRequestWithAuth 新建带鉴权头的 HTTP PUT 请求
func NewHTTPEndpointPutRequestWithAuth(ep string, auth string, body io.Reader) (req *http.Request, err error) {
req, err = http.NewRequest("PUT", StandardAPI+ep, body)
if err != nil {
return
}
req.Header.Add("Authorization", auth)
return
func NewHTTPEndpointPutRequestWithAuth(ep string, contenttype string, auth string, body io.Reader) (*http.Request, error) {
return newHTTPEndpointRequestWithAuth("PUT", contenttype, ep, auth, body)
}
// NewHTTPEndpointDeleteRequestWithAuth 新建带鉴权头的 HTTP DELETE 请求
func NewHTTPEndpointDeleteRequestWithAuth(ep string, auth string, body io.Reader) (req *http.Request, err error) {
req, err = http.NewRequest("DELETE", StandardAPI+ep, body)
if err != nil {
return
}
req.Header.Add("Authorization", auth)
return
func NewHTTPEndpointDeleteRequestWithAuth(ep string, contenttype string, auth string, body io.Reader) (*http.Request, error) {
return newHTTPEndpointRequestWithAuth("DELETE", contenttype, ep, auth, body)
}
// 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
func NewHTTPEndpointPostRequestWithAuth(ep string, contenttype string, auth string, body io.Reader) (*http.Request, error) {
return newHTTPEndpointRequestWithAuth("POST", contenttype, ep, auth, body)
}
// NewHTTPEndpointPatchRequestWithAuth 新建带鉴权头的 HTTP PATCH 请求
func NewHTTPEndpointPatchRequestWithAuth(ep string, auth string, body io.Reader) (req *http.Request, err error) {
req, err = http.NewRequest("PATCH", StandardAPI+ep, body)
if err != nil {
return
}
req.Header.Add("Authorization", auth)
return
func NewHTTPEndpointPatchRequestWithAuth(ep string, contenttype string, auth string, body io.Reader) (*http.Request, error) {
return newHTTPEndpointRequestWithAuth("PATCH", contenttype, ep, auth, body)
}
// WriteHTTPQueryIfNotNil 如果非空则将请求添加到 baseurl 后
//
// ex. WriteHTTPQueryIfNotNil("http://a.com/api", "a", 0, "b", 1, "c", 2) is http://a.com/api?b=1&c=2
func WriteHTTPQueryIfNotNil(baseurl string, queries ...any) string {
if len(queries) == 0 {
if len(queries) < 2 {
return baseurl
}
hasstart := false
@@ -101,3 +94,82 @@ func WriteBodyFromJSON(ptr any) *bytes.Buffer {
_ = json.NewEncoder(buf).Encode(ptr)
return buf
}
// WriteBodyByMultipartFormData 使用 multipart/form-data 上传
func WriteBodyByMultipartFormData(params ...any) (*bytes.Buffer, string, error) {
if len(params)%2 != 0 {
panic("invalid params to " + getThisFuncName())
}
fieldname := ""
buf := bytes.NewBuffer(make([]byte, 0, 65536))
w := multipart.NewWriter(buf)
defer w.Close()
for i, x := range params {
if i%2 == 0 { // 参数
fieldname = x.(string)
continue
}
rx := reflect.ValueOf(x)
if rx.IsZero() {
continue
}
r, err := w.CreateFormField(fieldname)
if err != nil {
return nil, "", err
}
if rx.Elem().Kind() == reflect.Struct { // 使用 json 编码
err = json.NewEncoder(r).Encode(x)
if err != nil {
return nil, "", err
}
continue
}
switch o := x.(type) {
case string:
if strings.HasPrefix(o, "file:///") { // 是文件路径
f, err := os.Open(o[8:])
if err != nil {
return nil, "", err
}
defer f.Close()
_, err = io.Copy(r, f)
if err != nil {
return nil, "", err
}
continue
}
if strings.HasPrefix(o, "base64://") { // 是 base64
_, err = io.Copy(r, base64.NewDecoder(base64.StdEncoding, bytes.NewBufferString(o[9:])))
if err != nil {
return nil, "", err
}
continue
}
if strings.HasPrefix(o, "base16384://") { // 是 base16384
_, err = io.Copy(r, base14.NewDecoder(bytes.NewBufferString(o[12:])))
if err != nil {
return nil, "", err
}
continue
}
_, err = io.WriteString(r, o)
if err != nil {
return nil, "", err
}
continue
case []byte:
_, err = r.Write(o)
if err != nil {
return nil, "", err
}
continue
default:
_, err = io.WriteString(r, fmt.Sprint(o))
if err != nil {
return nil, "", err
}
continue
}
}
return buf, w.FormDataContentType(), nil
}

View File

@@ -11,11 +11,11 @@ import (
"github.com/pkg/errors"
)
//go:generate go run codegen/getopenapiof/main.go ShardWSSGateway User Guild Channel Member RoleMembers GuildRoleList ChannelPermissions
//go:generate go run codegen/getopenapiof/main.go ShardWSSGateway User Guild Channel Member RoleMembers GuildRoleList ChannelPermissions Message
// GetOpenAPI 从 ep 获取 json 结构化数据写到 ptr, ptr 除 Slice 外必须在开头继承 CodeMessageBase
func (bot *Bot) GetOpenAPI(ep string, ptr any) error {
req, err := NewHTTPEndpointGetRequestWithAuth(ep, bot.Authorization())
func (bot *Bot) GetOpenAPI(ep, contenttype string, ptr any) error {
req, err := NewHTTPEndpointGetRequestWithAuth(ep, contenttype, bot.Authorization())
if err != nil {
return errors.Wrap(err, getCallerFuncName())
}
@@ -50,8 +50,8 @@ func (bot *Bot) GetOpenAPI(ep string, ptr any) error {
//go:generate go run codegen/putopenapiof/main.go GuildRoleChannelID
// PutOpenAPI 向 ep 发送 PUT 并获取 json 结构化数据返回写到 ptr, ptr 除 Slice 外必须在开头继承 CodeMessageBase
func (bot *Bot) PutOpenAPI(ep string, ptr any, body io.Reader) error {
req, err := NewHTTPEndpointPutRequestWithAuth(ep, bot.Authorization(), body)
func (bot *Bot) PutOpenAPI(ep, contenttype string, ptr any, body io.Reader) error {
req, err := NewHTTPEndpointPutRequestWithAuth(ep, contenttype, bot.Authorization(), body)
if err != nil {
return errors.Wrap(err, getCallerFuncName())
}
@@ -84,8 +84,8 @@ func (bot *Bot) PutOpenAPI(ep string, ptr any, body io.Reader) error {
}
// DeleteOpenAPI 向 ep 发送 DELETE 请求
func (bot *Bot) DeleteOpenAPI(ep string, body io.Reader) error {
req, err := NewHTTPEndpointDeleteRequestWithAuth(ep, bot.Authorization(), body)
func (bot *Bot) DeleteOpenAPI(ep, contenttype string, body io.Reader) error {
req, err := NewHTTPEndpointDeleteRequestWithAuth(ep, contenttype, bot.Authorization(), body)
if err != nil {
return errors.Wrap(err, getCallerFuncName())
}
@@ -103,11 +103,11 @@ func (bot *Bot) DeleteOpenAPI(ep string, body io.Reader) error {
return nil
}
//go:generate go run codegen/postopenapiof/main.go Channel GuildRoleCreate
//go:generate go run codegen/postopenapiof/main.go Channel GuildRoleCreate Message
// PostOpenAPI 从 ep 得到 json 结构化数据返回值写到 ptr, ptr 除 Slice 外必须在开头继承 CodeMessageBase
func (bot *Bot) PostOpenAPI(ep string, ptr any, body io.Reader) error {
req, err := NewHTTPEndpointPostRequestWithAuth(ep, bot.Authorization(), body)
func (bot *Bot) PostOpenAPI(ep, contenttype string, ptr any, body io.Reader) error {
req, err := NewHTTPEndpointPostRequestWithAuth(ep, contenttype, bot.Authorization(), body)
if err != nil {
return errors.Wrap(err, getCallerFuncName())
}
@@ -142,8 +142,8 @@ func (bot *Bot) PostOpenAPI(ep string, ptr any, body io.Reader) error {
//go:generate go run codegen/patchopenapiof/main.go Channel GuildRolePatch
// PatchOpenAPI 从 ep 得到 json 结构化数据返回值写到 ptr, ptr 除 Slice 外必须在开头继承 CodeMessageBase
func (bot *Bot) PatchOpenAPI(ep string, ptr any, body io.Reader) error {
req, err := NewHTTPEndpointPatchRequestWithAuth(ep, bot.Authorization(), body)
func (bot *Bot) PatchOpenAPI(ep, contenttype string, ptr any, body io.Reader) error {
req, err := NewHTTPEndpointPatchRequestWithAuth(ep, contenttype, bot.Authorization(), body)
if err != nil {
return errors.Wrap(err, getCallerFuncName())
}

View File

@@ -64,7 +64,7 @@ type Channel struct {
//
// https://bot.q.qq.com/wiki/develop/api/openapi/channel/get_channels.html
func (bot *Bot) GetChannelsOfGuild(id string) (channels []Channel, err error) {
err = bot.GetOpenAPI("/guilds/"+id+"/channels", &channels)
err = bot.GetOpenAPI("/guilds/"+id+"/channels", "", &channels)
return
}
@@ -95,7 +95,7 @@ type ChannelPost struct {
//
// https://bot.q.qq.com/wiki/develop/api/openapi/channel/post_channels.html
func (bot *Bot) CreateChannelInGuild(id string, config *ChannelPost) (*Channel, error) {
return bot.postOpenAPIofChannel("/guilds/"+id+"/channels", WriteBodyFromJSON(config))
return bot.postOpenAPIofChannel("/guilds/"+id+"/channels", "", WriteBodyFromJSON(config))
}
// ChannelPatch 子频道 patch 操作所用对象
@@ -120,7 +120,7 @@ func (bot *Bot) PatchChannelOf(id string, config *ChannelPatch) (*Channel, error
//
// https://bot.q.qq.com/wiki/develop/api/openapi/channel/delete_channel.html
func (bot *Bot) DeleteChannelOf(id string) error {
return bot.DeleteOpenAPI("/channels/"+id, nil)
return bot.DeleteOpenAPI("/channels/"+id, "", nil)
}
// GetOnlineNumsInChannel 查询音视频/直播子频道 channel_id 的在线成员数
@@ -131,7 +131,7 @@ func (bot *Bot) GetOnlineNumsInChannel(id string) (int, error) {
CodeMessageBase
N int `json:"online_nums"`
}{}
err := bot.GetOpenAPI("/channels/"+id+"/online_nums", &resp)
err := bot.GetOpenAPI("/channels/"+id+"/online_nums", "", &resp)
return resp.N, err
}
@@ -156,7 +156,7 @@ func (bot *Bot) GetChannelPermissionsOfUser(channelid, userid string) (*ChannelP
//
// https://bot.q.qq.com/wiki/develop/api/openapi/channel_permissions/put_channel_permissions.html
func (bot *Bot) SetChannelPermissionsOfUser(channelid, userid string, add, remove string) error {
return bot.PutOpenAPI("/channels/"+channelid+"/members/"+userid+"/permissions", nil, WriteBodyFromJSON(&struct {
return bot.PutOpenAPI("/channels/"+channelid+"/members/"+userid+"/permissions", "", nil, WriteBodyFromJSON(&struct {
A string `json:"add"`
R string `json:"remove"`
}{add, remove}))
@@ -173,7 +173,7 @@ func (bot *Bot) GetChannelPermissionsOfRole(channelid, roleid string) (*ChannelP
//
// https://bot.q.qq.com/wiki/develop/api/openapi/channel_permissions/put_channel_roles_permissions.html
func (bot *Bot) SetChannelPermissionsOfRole(channelid, roleid string, add, remove string) error {
return bot.PutOpenAPI("/channels/"+channelid+"/roles/"+roleid+"/permissions", nil, WriteBodyFromJSON(&struct {
return bot.PutOpenAPI("/channels/"+channelid+"/roles/"+roleid+"/permissions", "", nil, WriteBodyFromJSON(&struct {
A string `json:"add"`
R string `json:"remove"`
}{add, remove}))

View File

@@ -13,12 +13,11 @@ func (bot *Bot) getOpenAPIofShardWSSGateway(ep string) (*ShardWSSGateway, error)
CodeMessageBase
ShardWSSGateway
}{}
err := bot.GetOpenAPI(ep, resp)
err := bot.GetOpenAPI(ep, "", resp)
if err != nil {
err = errors.Wrap(err, getCallerFuncName())
return nil, err
}
return (*ShardWSSGateway)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), nil
return (*ShardWSSGateway)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), err
}
func (bot *Bot) getOpenAPIofUser(ep string) (*User, error) {
@@ -26,12 +25,11 @@ func (bot *Bot) getOpenAPIofUser(ep string) (*User, error) {
CodeMessageBase
User
}{}
err := bot.GetOpenAPI(ep, resp)
err := bot.GetOpenAPI(ep, "", resp)
if err != nil {
err = errors.Wrap(err, getCallerFuncName())
return nil, err
}
return (*User)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), nil
return (*User)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), err
}
func (bot *Bot) getOpenAPIofGuild(ep string) (*Guild, error) {
@@ -39,12 +37,11 @@ func (bot *Bot) getOpenAPIofGuild(ep string) (*Guild, error) {
CodeMessageBase
Guild
}{}
err := bot.GetOpenAPI(ep, resp)
err := bot.GetOpenAPI(ep, "", resp)
if err != nil {
err = errors.Wrap(err, getCallerFuncName())
return nil, err
}
return (*Guild)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), nil
return (*Guild)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), err
}
func (bot *Bot) getOpenAPIofChannel(ep string) (*Channel, error) {
@@ -52,12 +49,11 @@ func (bot *Bot) getOpenAPIofChannel(ep string) (*Channel, error) {
CodeMessageBase
Channel
}{}
err := bot.GetOpenAPI(ep, resp)
err := bot.GetOpenAPI(ep, "", resp)
if err != nil {
err = errors.Wrap(err, getCallerFuncName())
return nil, err
}
return (*Channel)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), nil
return (*Channel)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), err
}
func (bot *Bot) getOpenAPIofMember(ep string) (*Member, error) {
@@ -65,12 +61,11 @@ func (bot *Bot) getOpenAPIofMember(ep string) (*Member, error) {
CodeMessageBase
Member
}{}
err := bot.GetOpenAPI(ep, resp)
err := bot.GetOpenAPI(ep, "", resp)
if err != nil {
err = errors.Wrap(err, getCallerFuncName())
return nil, err
}
return (*Member)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), nil
return (*Member)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), err
}
func (bot *Bot) getOpenAPIofRoleMembers(ep string) (*RoleMembers, error) {
@@ -78,12 +73,11 @@ func (bot *Bot) getOpenAPIofRoleMembers(ep string) (*RoleMembers, error) {
CodeMessageBase
RoleMembers
}{}
err := bot.GetOpenAPI(ep, resp)
err := bot.GetOpenAPI(ep, "", resp)
if err != nil {
err = errors.Wrap(err, getCallerFuncName())
return nil, err
}
return (*RoleMembers)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), nil
return (*RoleMembers)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), err
}
func (bot *Bot) getOpenAPIofGuildRoleList(ep string) (*GuildRoleList, error) {
@@ -91,12 +85,11 @@ func (bot *Bot) getOpenAPIofGuildRoleList(ep string) (*GuildRoleList, error) {
CodeMessageBase
GuildRoleList
}{}
err := bot.GetOpenAPI(ep, resp)
err := bot.GetOpenAPI(ep, "", resp)
if err != nil {
err = errors.Wrap(err, getCallerFuncName())
return nil, err
}
return (*GuildRoleList)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), nil
return (*GuildRoleList)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), err
}
func (bot *Bot) getOpenAPIofChannelPermissions(ep string) (*ChannelPermissions, error) {
@@ -104,10 +97,21 @@ func (bot *Bot) getOpenAPIofChannelPermissions(ep string) (*ChannelPermissions,
CodeMessageBase
ChannelPermissions
}{}
err := bot.GetOpenAPI(ep, resp)
err := bot.GetOpenAPI(ep, "", resp)
if err != nil {
err = errors.Wrap(err, getCallerFuncName())
return nil, err
}
return (*ChannelPermissions)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), nil
return (*ChannelPermissions)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), err
}
func (bot *Bot) getOpenAPIofMessage(ep string) (*Message, error) {
resp := &struct {
CodeMessageBase
Message
}{}
err := bot.GetOpenAPI(ep, "", resp)
if err != nil {
err = errors.Wrap(err, getCallerFuncName())
}
return (*Message)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), err
}

View File

@@ -14,12 +14,11 @@ func (bot *Bot) patchOpenAPIofChannel(ep string, body io.Reader) (*Channel, erro
CodeMessageBase
Channel
}{}
err := bot.PatchOpenAPI(ep, resp, body)
err := bot.PatchOpenAPI(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
return (*Channel)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), err
}
func (bot *Bot) patchOpenAPIofGuildRolePatch(ep string, body io.Reader) (*GuildRolePatch, error) {
@@ -27,10 +26,9 @@ func (bot *Bot) patchOpenAPIofGuildRolePatch(ep string, body io.Reader) (*GuildR
CodeMessageBase
GuildRolePatch
}{}
err := bot.PatchOpenAPI(ep, resp, body)
err := bot.PatchOpenAPI(ep, "", resp, body)
if err != nil {
err = errors.Wrap(err, getCallerFuncName())
return nil, err
}
return (*GuildRolePatch)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), nil
return (*GuildRolePatch)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), err
}

View File

@@ -9,28 +9,38 @@ import (
"github.com/pkg/errors"
)
func (bot *Bot) postOpenAPIofChannel(ep string, body io.Reader) (*Channel, error) {
func (bot *Bot) postOpenAPIofChannel(ep, contenttype string, body io.Reader) (*Channel, error) {
resp := &struct {
CodeMessageBase
Channel
}{}
err := bot.PostOpenAPI(ep, resp, body)
err := bot.PostOpenAPI(ep, contenttype, resp, body)
if err != nil {
err = errors.Wrap(err, getCallerFuncName())
return nil, err
}
return (*Channel)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), nil
return (*Channel)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), err
}
func (bot *Bot) postOpenAPIofGuildRoleCreate(ep string, body io.Reader) (*GuildRoleCreate, error) {
func (bot *Bot) postOpenAPIofGuildRoleCreate(ep, contenttype string, body io.Reader) (*GuildRoleCreate, error) {
resp := &struct {
CodeMessageBase
GuildRoleCreate
}{}
err := bot.PostOpenAPI(ep, resp, body)
err := bot.PostOpenAPI(ep, contenttype, resp, body)
if err != nil {
err = errors.Wrap(err, getCallerFuncName())
return nil, err
}
return (*GuildRoleCreate)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), nil
return (*GuildRoleCreate)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), err
}
func (bot *Bot) postOpenAPIofMessage(ep, contenttype string, body io.Reader) (*Message, error) {
resp := &struct {
CodeMessageBase
Message
}{}
err := bot.PostOpenAPI(ep, contenttype, resp, body)
if err != nil {
err = errors.Wrap(err, getCallerFuncName())
}
return (*Message)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), err
}

View File

@@ -14,10 +14,9 @@ func (bot *Bot) putOpenAPIofGuildRoleChannelID(ep string, body io.Reader) (*Guil
CodeMessageBase
GuildRoleChannelID
}{}
err := bot.PutOpenAPI(ep, resp, body)
err := bot.PutOpenAPI(ep, "", resp, body)
if err != nil {
err = errors.Wrap(err, getCallerFuncName())
return nil, err
}
return (*GuildRoleChannelID)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), nil
return (*GuildRoleChannelID)(unsafe.Add(unsafe.Pointer(resp), unsafe.Sizeof(CodeMessageBase{}))), err
}

4
openapi_markdown.go Normal file
View File

@@ -0,0 +1,4 @@
package nano
type MessageMarkdown struct {
}

View File

@@ -23,7 +23,7 @@ func (bot *Bot) GetGuildMembersIn(id, after string, limit uint32) (members []Mem
err = bot.GetOpenAPI(WriteHTTPQueryIfNotNil("/guilds/"+id+"/members",
"after", after,
"limit", limit,
), &members)
), "", &members)
return
}
@@ -58,7 +58,7 @@ func (bot *Bot) GetGuildMemberOf(guildid, userid string) (*Member, error) {
//
// - delhistmsgdays: 消息撤回时间范围仅支持固定的天数371530。 特殊的时间范围:-1: 撤回全部消息。默认值为0不撤回任何消息。
func (bot *Bot) DeleteGuildMemberOf(guildid, userid string, addblklst bool, delhistmsgdays int) error {
return bot.DeleteOpenAPI("/guilds/"+guildid+"/members/"+userid, WriteBodyFromJSON(&struct {
return bot.DeleteOpenAPI("/guilds/"+guildid+"/members/"+userid, "", WriteBodyFromJSON(&struct {
A bool `json:"add_blacklist"`
D int `json:"delete_history_msg_days"`
}{addblklst, delhistmsgdays}))

168
openapi_message.go Normal file
View File

@@ -0,0 +1,168 @@
package nano
import (
"encoding/json"
"reflect"
"time"
"github.com/pkg/errors"
)
var (
ErrEmptyMessagePost = errors.New("empty message post")
)
// Message 消息对象
//
// https://bot.q.qq.com/wiki/develop/api/openapi/message/model.html#%E6%B6%88%E6%81%AF%E5%AF%B9%E8%B1%A1-message
type Message struct {
ID string `json:"id"`
ChannelID string `json:"channel_id"`
GuildID string `json:"guild_id"`
Content string `json:"content"`
Timestamp time.Time `json:"timestamp"`
EditedTimestamp time.Time `json:"edited_timestamp"`
MentionEveryone bool `json:"mention_everyone"`
Author User `json:"author"`
Attachments []MessageAttachment `json:"attachments"`
Embeds []MessageEmbed `json:"embeds"`
Member Member `json:"member"`
Ark MessageArk `json:"ark"`
SeqInChannel string `json:"seq_in_channel"`
MessageReference MessageReference `json:"message_reference"`
SrcGuildID string `json:"src_guild_id"`
Data *struct {
MessageAudit *MessageAudited `json:"message_audit,omitempty"`
} `json:"data,omitempty"`
}
// MessageEmbed https://bot.q.qq.com/wiki/develop/api/openapi/message/model.html#messageembed
type MessageEmbed struct {
Title string `json:"title"`
Prompt string `json:"prompt"`
Thumbnail MessageEmbedThumbnail `json:"thumbnail"`
Fields []MessageEmbedField `json:"fields"`
}
// MessageEmbedThumbnail https://bot.q.qq.com/wiki/develop/api/openapi/message/model.html#messageembedthumbnail
type MessageEmbedThumbnail struct {
URL string `json:"url"`
}
// MessageEmbedField https://bot.q.qq.com/wiki/develop/api/openapi/message/model.html#messageembedfield
type MessageEmbedField struct {
Name string `json:"name"`
}
// MessageAttachment https://bot.q.qq.com/wiki/develop/api/openapi/message/model.html#messageattachment
type MessageAttachment struct {
URL string `json:"url"`
}
// MessageArk https://bot.q.qq.com/wiki/develop/api/openapi/message/model.html#messageark
type MessageArk struct {
TemplateID int `json:"template_id"`
KV []MessageArkKV `json:"kv"`
}
// MessageArkKV https://bot.q.qq.com/wiki/develop/api/openapi/message/model.html#messagearkkv
type MessageArkKV struct {
Key string `json:"key"`
Value string `json:"value"`
Obj []MessageArkObj `json:"obj"`
}
// MessageArkObj https://bot.q.qq.com/wiki/develop/api/openapi/message/model.html#messagearkobj
type MessageArkObj struct {
ObjKV []MessageArkObjKV `json:"obj_kv"`
}
// MessageArkObjKV https://bot.q.qq.com/wiki/develop/api/openapi/message/model.html#messagearkobjkv
type MessageArkObjKV struct {
Key string `json:"key"`
Value string `json:"value"`
}
// MessageReference https://bot.q.qq.com/wiki/develop/api/openapi/message/model.html#messagereference
type MessageReference struct {
MessageID string `json:"message_id"`
IgnoreGetMessageError bool `json:"ignore_get_message_error"`
}
// MessageAudited 消息审核对象
//
// https://bot.q.qq.com/wiki/develop/api/openapi/message/model.html#%E6%B6%88%E6%81%AF%E5%AE%A1%E6%A0%B8%E5%AF%B9%E8%B1%A1-messageaudited
type MessageAudited struct {
AuditID string `json:"audit_id"`
}
// GetMessageFromChannel 获取子频道 channel_id 下的消息 message_id 的详情
//
// https://bot.q.qq.com/wiki/develop/api/openapi/message/get_message_of_id.html
func (bot *Bot) GetMessageFromChannel(messageid, channelid string) (*Message, error) {
return bot.getOpenAPIofMessage("/channels/" + channelid + "/messages/" + messageid)
}
// MessagePost 发送消息所需参数
//
// https://bot.q.qq.com/wiki/develop/api/openapi/message/post_messages.html#%E9%80%9A%E7%94%A8%E5%8F%82%E6%95%B0
type MessagePost struct {
Content string `json:"content,omitempty"`
Embed *MessageEmbed `json:"embed,omitempty"`
Ark *MessageArk `json:"ark,omitempty"`
MessageReference *MessageReference `json:"message_reference,omitempty"`
Image string `json:"image,omitempty"`
ImageFile string `json:"-"` // ImageFile 为图片路径 file:/// or base64:// or base16384:// , 与 Image 参数二选一, 优先 Image
ReplyMessageID string `json:"msg_id,omitempty"`
ReplyEventID string `json:"event_id,omitempty"`
Markdown *MessageMarkdown `json:"markdown,omitempty"`
}
// PostMessageToChannel 向 channel_id 指定的子频道发送消息
//
// https://bot.q.qq.com/wiki/develop/api/openapi/message/post_messages.html
func (bot *Bot) PostMessageToChannel(id string, content *MessagePost) (*Message, error) {
if content.ImageFile == "" {
return bot.postOpenAPIofMessage("/channels/"+id+"/messages", "", WriteBodyFromJSON(content))
}
x := reflect.ValueOf(content).Elem()
t := x.Type()
msg := []any{}
for i := 0; i < x.NumField(); i++ {
xi := x.Field(i)
if xi.IsZero() {
continue
}
tag := t.Field(i).Tag.Get("json")
if tag == "-" {
tag = "file_image"
}
msg = append(msg, tag)
if xi.Kind() == reflect.Struct {
data, err := json.Marshal(xi.Interface())
if err != nil {
return nil, err
}
msg = append(msg, data)
continue
}
msg = append(msg, xi.String())
}
if len(msg) < 2 {
return nil, ErrEmptyMessagePost
}
body, contenttype, err := WriteBodyByMultipartFormData(msg...)
if err != nil {
return nil, errors.Wrap(err, getThisFuncName())
}
return bot.postOpenAPIofMessage("/channels/"+id+"/messages", contenttype, body)
}
// DeleteMessageInChannel 回子频道 channel_id 下的消息 message_id
//
// https://bot.q.qq.com/wiki/develop/api/openapi/message/delete_message.html
func (bot *Bot) DeleteMessageInChannel(channelid, messageid string, hidetip bool) error {
return bot.DeleteOpenAPI(WriteHTTPQueryIfNotNil("/channels/"+channelid+"/messages/"+messageid,
"hidetip", hidetip,
), "", nil)
}

View File

@@ -58,7 +58,7 @@ type GuildRoleCreate struct {
//
// 参数为非必填,但至少需要传其中之一,默认为空或 0
func (bot *Bot) CreateGuildRoleOf(id string, name string, color uint32, hoist int32) (*GuildRoleCreate, error) {
return bot.postOpenAPIofGuildRoleCreate("/guilds/"+id+"/roles", WriteBodyFromJSON(&struct {
return bot.postOpenAPIofGuildRoleCreate("/guilds/"+id+"/roles", "", WriteBodyFromJSON(&struct {
N string `json:"name,omitempty"`
C uint32 `json:"color,omitempty"`
H int32 `json:"hoist,omitempty"`
@@ -89,7 +89,7 @@ func (bot *Bot) PatchGuildRoleOf(guildid, roleid string, name string, color uint
//
// https://bot.q.qq.com/wiki/develop/api/openapi/guild/delete_guild_role.html
func (bot *Bot) DeleteGuildRoleOf(guildid, roleid string) error {
return bot.DeleteOpenAPI("/guilds/"+guildid+"/roles/"+roleid, nil)
return bot.DeleteOpenAPI("/guilds/"+guildid+"/roles/"+roleid, "", nil)
}
// GuildRoleChannelID 频道身份组成员返回 只填充了子频道 id 字段的对象
@@ -140,5 +140,5 @@ func (bot *Bot) RemoveRoleFromMemberOfGuild(guildid, userid, roleid, channelid s
}{channelid},
})
}
return bot.DeleteOpenAPI("/guilds/"+guildid+"/members/"+userid+"/roles/"+roleid, body)
return bot.DeleteOpenAPI("/guilds/"+guildid+"/members/"+userid+"/roles/"+roleid, "", body)
}

View File

@@ -27,6 +27,6 @@ func (bot *Bot) GetMyGuilds(before, after string, limit int) (guilds []Guild, er
"before", before,
"after", after,
"limit", limit,
), &guilds)
), "", &guilds)
return
}

View File

@@ -8,7 +8,7 @@ func (bot *Bot) GetGeneralWSSGateway() (string, error) {
CodeMessageBase
U string `json:"url"`
}{}
err := bot.GetOpenAPI("/gateway", &resp)
err := bot.GetOpenAPI("/gateway", "", &resp)
return resp.U, err
}