github.com/fumiama/NanoBot@v0.0.0-20231122134259-c22d8183efca/openapi_wss.go (about)

     1  package nano
     2  
     3  import (
     4  	"encoding/json"
     5  	"net/http"
     6  	"strconv"
     7  
     8  	"github.com/pkg/errors"
     9  )
    10  
    11  var (
    12  	ErrEmptyToken    = errors.New("empty token")
    13  	ErrInvalidExpire = errors.New("invalid expire")
    14  )
    15  
    16  // GetGeneralWSSGatewayNoContext 获取通用 WSS 接入点
    17  //
    18  // https://bot.q.qq.com/wiki/develop/api/openapi/wss/url_get.html
    19  func (bot *Bot) GetGeneralWSSGatewayNoContext() (string, error) {
    20  	resp := struct {
    21  		CodeMessageBase
    22  		U string `json:"url"`
    23  	}{}
    24  	err := bot.GetOpenAPI("/gateway", "", &resp)
    25  	return resp.U, err
    26  }
    27  
    28  // ShardWSSGateway 带分片 WSS 接入点响应数据
    29  //
    30  // https://bot.q.qq.com/wiki/develop/api/openapi/wss/shard_url_get.html#%E8%BF%94%E5%9B%9E
    31  type ShardWSSGateway struct {
    32  	URL               string `json:"url"`
    33  	Shards            int    `json:"shards"`
    34  	SessionStartLimit struct {
    35  		Total          int `json:"total"`
    36  		Remaining      int `json:"remaining"`
    37  		ResetAfter     int `json:"reset_after"`
    38  		MaxConcurrency int `json:"max_concurrency"`
    39  	} `json:"session_start_limit"`
    40  }
    41  
    42  // GetShardWSSGatewayNoContext 获取带分片 WSS 接入点
    43  //
    44  // https://bot.q.qq.com/wiki/develop/api/openapi/wss/shard_url_get.html
    45  func (bot *Bot) GetShardWSSGatewayNoContext() (*ShardWSSGateway, error) {
    46  	return bot.getOpenAPIofShardWSSGateway("/gateway/bot")
    47  }
    48  
    49  // GetAppAccessTokenNoContext 获取接口凭证并保存到 bot.Token
    50  //
    51  // https://bot.q.qq.com/wiki/develop/api-231017/dev-prepare/interface-framework/api-use.html#%E8%8E%B7%E5%8F%96%E6%8E%A5%E5%8F%A3%E5%87%AD%E8%AF%81
    52  func (bot *Bot) GetAppAccessTokenNoContext() error {
    53  	req, err := newHTTPEndpointRequestWithAuth("POST", "", AccessTokenAPI, "", "", WriteBodyFromJSON(&struct {
    54  		A string `json:"appId"`
    55  		S string `json:"clientSecret"`
    56  	}{bot.AppID, bot.Secret}))
    57  	if err != nil {
    58  		return err
    59  	}
    60  	resp, err := bot.client.Do(req)
    61  	if err != nil {
    62  		return errors.Wrap(err, getThisFuncName())
    63  	}
    64  	defer resp.Body.Close()
    65  	if resp.StatusCode != http.StatusOK {
    66  		return errors.Wrap(errors.New("http status code: "+strconv.Itoa(resp.StatusCode)), getThisFuncName())
    67  	}
    68  	body := struct {
    69  		C int    `json:"code"`
    70  		M string `json:"message"`
    71  		T string `json:"access_token"`
    72  		E string `json:"expires_in"`
    73  	}{}
    74  	err = json.NewDecoder(resp.Body).Decode(&body)
    75  	if err != nil {
    76  		return errors.Wrap(err, getThisFuncName())
    77  	}
    78  	if body.C != 0 {
    79  		return errors.Wrap(errors.New("code: "+strconv.Itoa(body.C)+", msg: "+body.M), getThisFuncName())
    80  	}
    81  	if body.T == "" {
    82  		return errors.Wrap(ErrEmptyToken, getThisFuncName())
    83  	}
    84  	if body.E == "" {
    85  		return errors.Wrap(ErrInvalidExpire, getThisFuncName())
    86  	}
    87  	bot.token = body.T
    88  	bot.expiresec, err = strconv.ParseInt(body.E, 10, 64)
    89  	if err != nil {
    90  		return errors.Wrap(err, getThisFuncName())
    91  	}
    92  	if bot.expiresec <= 0 {
    93  		return errors.Wrap(ErrInvalidExpire, getThisFuncName())
    94  	}
    95  	return nil
    96  }