diff --git a/http.go b/http.go index 7f10810..fd355b2 100644 --- a/http.go +++ b/http.go @@ -30,8 +30,8 @@ func newHTTPEndpointRequestWithAuth(method, contenttype, ep string, auth string, } // NewHTTPEndpointGetRequestWithAuth 新建带鉴权头的 HTTP GET 请求 -func NewHTTPEndpointGetRequestWithAuth(ep string, contenttype string, auth string) (*http.Request, error) { - return newHTTPEndpointRequestWithAuth("GET", contenttype, ep, auth, nil) +func NewHTTPEndpointGetRequestWithAuth(ep string, contenttype string, auth string, body io.Reader) (*http.Request, error) { + return newHTTPEndpointRequestWithAuth("GET", contenttype, ep, auth, body) } // NewHTTPEndpointPutRequestWithAuth 新建带鉴权头的 HTTP PUT 请求 diff --git a/openapi.go b/openapi.go index 2231355..826ca92 100644 --- a/openapi.go +++ b/openapi.go @@ -19,11 +19,41 @@ func checkrespbaseunsafe(ptr any) error { return nil } -//go:generate go run codegen/getopenapiof/main.go ShardWSSGateway User Guild Channel Member RoleMembers GuildRoleList ChannelPermissions Message MessageSetting PinsMessage +//go:generate go run codegen/getopenapiof/main.go ShardWSSGateway User Guild Channel Member RoleMembers GuildRoleList ChannelPermissions Message MessageSetting PinsMessage Schedule // GetOpenAPI 从 ep 获取 json 结构化数据写到 ptr, ptr 除 Slice 外必须在开头继承 CodeMessageBase func (bot *Bot) GetOpenAPI(ep, contenttype string, ptr any) error { - req, err := NewHTTPEndpointGetRequestWithAuth(ep, contenttype, bot.Authorization()) + req, err := NewHTTPEndpointGetRequestWithAuth(ep, contenttype, bot.Authorization(), nil) + 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() + if resp.StatusCode == http.StatusNoContent { + return nil + } + if resp.StatusCode >= http.StatusBadRequest { + return errors.Wrap(errors.New("code: "+strconv.Itoa(resp.StatusCode)+", msg: "+resp.Status), getCallerFuncName()) + } + if ptr == nil { + return nil + } + err = json.NewDecoder(resp.Body).Decode(ptr) + if err != nil { + return errors.Wrap(err, getCallerFuncName()) + } + if reflect.ValueOf(ptr).Elem().Kind() == reflect.Slice { + return nil + } + return checkrespbaseunsafe(ptr) +} + +// GetOpenAPIWithBody 不规范地从 ep 获取 json 结构化数据写到 ptr, ptr 除 Slice 外必须在开头继承 CodeMessageBase +func (bot *Bot) GetOpenAPIWithBody(ep, contenttype string, ptr any, body io.Reader) error { + req, err := NewHTTPEndpointGetRequestWithAuth(ep, contenttype, bot.Authorization(), body) if err != nil { return errors.Wrap(err, getCallerFuncName()) } diff --git a/openapi_codegen_getopenapiof.go b/openapi_codegen_getopenapiof.go index b6648ce..b5c8227 100644 --- a/openapi_codegen_getopenapiof.go +++ b/openapi_codegen_getopenapiof.go @@ -137,3 +137,15 @@ func (bot *Bot) getOpenAPIofPinsMessage(ep string) (*PinsMessage, error) { } return &resp.PinsMessage, err } + +func (bot *Bot) getOpenAPIofSchedule(ep string) (*Schedule, error) { + resp := &struct { + CodeMessageBase + Schedule + }{} + err := bot.GetOpenAPI(ep, "", resp) + if err != nil { + err = errors.Wrap(err, getCallerFuncName()) + } + return &resp.Schedule, err +} diff --git a/openapi_schedule.go b/openapi_schedule.go new file mode 100644 index 0000000..b4ad767 --- /dev/null +++ b/openapi_schedule.go @@ -0,0 +1,65 @@ +package nano + +// Schedule 日程对象 +// +// https://bot.q.qq.com/wiki/develop/api/openapi/schedule/model.html +type Schedule struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + StartTimestamp string `json:"start_timestamp,omitempty"` + EndTimestamp string `json:"end_timestamp,omitempty"` + Creator *Member `json:"creator,omitempty"` + JumpChannelID string `json:"jump_channel_id,omitempty"` + RemindType string `json:"remind_type,omitempty"` // https://bot.q.qq.com/wiki/develop/api/openapi/schedule/model.html#remindtype +} + +// GetChannelSchedules 获取channel_id指定的子频道中当天的日程列表 +// +// https://bot.q.qq.com/wiki/develop/api/openapi/schedule/get_schedules.html +func (bot *Bot) GetChannelSchedules(id string, since uint64) (schedules []Schedule, err error) { + if since == 0 { + err = bot.GetOpenAPI("/channels/"+id+"/schedules", "", &schedules) + } else { + err = bot.GetOpenAPIWithBody("/channels/"+id+"/schedules", "", &schedules, WriteBodyFromJSON(&struct { + S uint64 `json:"since"` + }{since})) + } + return +} + +// GetScheduleInChannel 获取日程子频道 channel_id 下 schedule_id 指定的的日程的详情 +// +// https://bot.q.qq.com/wiki/develop/api/openapi/schedule/get_schedule.html +func (bot *Bot) GetScheduleInChannel(channelid string, scheduleid string) (*Schedule, error) { + return bot.getOpenAPIofSchedule("/channels/" + channelid + "/schedules/" + scheduleid) +} + +// CreateScheduleInChannel 在 channel_id 指定的日程子频道下创建一个日程 +// +// https://bot.q.qq.com/wiki/develop/api/openapi/schedule/post_schedule.html +// +// schedule 会被写入返回的对象 +func (bot *Bot) CreateScheduleInChannel(id string, schedule *Schedule) error { + return bot.PostOpenAPI("/channels/"+id+"/schedules", "", schedule, WriteBodyFromJSON(&struct { + S *Schedule `json:"schedule"` + }{schedule})) +} + +// PatchScheduleInChannel 修改日程子频道 channel_id 下 schedule_id 指定的日程的详情 +// +// https://bot.q.qq.com/wiki/develop/api/openapi/schedule/patch_schedule.html +// +// schedule 会被写入返回的对象 +func (bot *Bot) PatchScheduleInChannel(channelid string, scheduleid string, schedule *Schedule) error { + return bot.PatchOpenAPI("/channels/"+channelid+"/schedules/"+scheduleid, "", schedule, WriteBodyFromJSON(&struct { + S *Schedule `json:"schedule"` + }{schedule})) +} + +// DeleteScheduleInChannel 删除日程子频道 channel_id 下 schedule_id 指定的日程 +// +// https://bot.q.qq.com/wiki/develop/api/openapi/schedule/delete_schedule.html +func (bot *Bot) DeleteScheduleInChannel(channelid string, scheduleid string) error { + return bot.DeleteOpenAPI("/channels/"+channelid+"/schedules/"+scheduleid, "", nil) +}