github.com/chanxuehong/wechat@v0.0.0-20230222024006-36f0325263cd/mp/shakearound/relation/search.go (about)

     1  package relation
     2  
     3  import (
     4  	"errors"
     5  
     6  	"github.com/chanxuehong/wechat/internal/util"
     7  	"github.com/chanxuehong/wechat/mp/core"
     8  	"github.com/chanxuehong/wechat/mp/shakearound/device"
     9  )
    10  
    11  type SearchQuery struct {
    12  	Type             int                      `json:"type"`                        // 查询方式。1: 查询设备的关联关系;2:查询页面的关联关系
    13  	DeviceIdentifier *device.DeviceIdentifier `json:"device_identifier,omitempty"` // 指定的设备;当type为1时,此项为必填
    14  	PageId           *int64                   `json:"page_id,omitempty"`           // 指定的页面id;当type为2时,此项为必填
    15  	Begin            *int                     `json:"begin,omitempty"`             // 关联关系列表的起始索引值;当type为2时,此项为必填
    16  	Count            *int                     `json:"count,omitempty"`             // 待查询的关联关系数量,不能超过50个;当type为2时,此项为必填
    17  }
    18  
    19  func NewSearchQuery1(deviceIdentifier *device.DeviceIdentifier) *SearchQuery {
    20  	return &SearchQuery{
    21  		Type:             1,
    22  		DeviceIdentifier: deviceIdentifier,
    23  	}
    24  }
    25  
    26  func NewSearchQuery1X(deviceIdentifier *device.DeviceIdentifier, begin, count int) *SearchQuery {
    27  	return &SearchQuery{
    28  		Type:             1,
    29  		DeviceIdentifier: deviceIdentifier,
    30  		Begin:            util.Int(begin),
    31  		Count:            util.Int(count),
    32  	}
    33  }
    34  
    35  func NewSearchQuery2(pageId int64, begin, count int) *SearchQuery {
    36  	return &SearchQuery{
    37  		Type:   2,
    38  		PageId: util.Int64(pageId),
    39  		Begin:  util.Int(begin),
    40  		Count:  util.Int(count),
    41  	}
    42  }
    43  
    44  type SearchResult struct {
    45  	TotalCount int        `json:"total_count"` // 设备或页面的关联关系总数
    46  	ItemCount  int        `json:"item_count"`  // 查询的关联关系数量
    47  	Relations  []Relation `json:"relations"`   // 查询的关联关系列表
    48  }
    49  
    50  type Relation struct {
    51  	device.DeviceBase
    52  	PageId int64 `json:"page_id"`
    53  }
    54  
    55  // 查询设备与页面的关联关系.
    56  func Search(clt *core.Client, query *SearchQuery) (rslt *SearchResult, err error) {
    57  	var result struct {
    58  		core.Error
    59  		SearchResult `json:"data"`
    60  	}
    61  
    62  	incompleteURL := "https://api.weixin.qq.com/shakearound/relation/search?access_token="
    63  	if err = clt.PostJSON(incompleteURL, query, &result); err != nil {
    64  		return
    65  	}
    66  
    67  	if result.ErrCode != core.ErrCodeOK {
    68  		err = &result.Error
    69  		return
    70  	}
    71  
    72  	result.SearchResult.ItemCount = len(result.SearchResult.Relations)
    73  	rslt = &result.SearchResult
    74  	return
    75  }
    76  
    77  // RelationIterator
    78  //
    79  //	iter, err := NewRelationIterator(*core.Client, *SearchQuery)
    80  //	if err != nil {
    81  //	    // TODO: 增加你的代码
    82  //	}
    83  //
    84  //	for iter.HasNext() {
    85  //	    items, err := iter.NextPage()
    86  //	    if err != nil {
    87  //	        // TODO: 增加你的代码
    88  //	    }
    89  //	    // TODO: 增加你的代码
    90  //	}
    91  type RelationIterator struct {
    92  	clt *core.Client
    93  
    94  	nextQuery *SearchQuery // 下一次查询参数
    95  
    96  	lastSearchResult *SearchResult // 最近一次获取的数据
    97  	nextPageCalled   bool          // NextPage() 是否调用过
    98  }
    99  
   100  func (iter *RelationIterator) TotalCount() int {
   101  	return iter.lastSearchResult.TotalCount
   102  }
   103  
   104  func (iter *RelationIterator) HasNext() bool {
   105  	if !iter.nextPageCalled { // 第一次调用需要特殊对待
   106  		return iter.lastSearchResult.ItemCount > 0 ||
   107  			*iter.nextQuery.Begin < iter.lastSearchResult.TotalCount
   108  	}
   109  
   110  	return *iter.nextQuery.Begin < iter.lastSearchResult.TotalCount
   111  }
   112  
   113  func (iter *RelationIterator) NextPage() (relations []Relation, err error) {
   114  	if !iter.nextPageCalled { // 第一次调用需要特殊对待
   115  		iter.nextPageCalled = true
   116  
   117  		relations = iter.lastSearchResult.Relations
   118  		return
   119  	}
   120  
   121  	rslt, err := Search(iter.clt, iter.nextQuery)
   122  	if err != nil {
   123  		return
   124  	}
   125  
   126  	*iter.nextQuery.Begin += rslt.ItemCount
   127  	iter.lastSearchResult = rslt
   128  
   129  	relations = rslt.Relations
   130  	return
   131  }
   132  
   133  func NewRelationIterator(clt *core.Client, query *SearchQuery) (iter *RelationIterator, err error) {
   134  	if query.Begin == nil {
   135  		err = errors.New("nil SearchQuery.Begin")
   136  		return
   137  	}
   138  	if query.Count == nil {
   139  		err = errors.New("nil SearchQuery.Count")
   140  		return
   141  	}
   142  
   143  	// 逻辑上相当于第一次调用 RelationIterator.NextPage, 因为第一次调用 RelationIterator.HasNext 需要数据支撑, 所以提前获取了数据
   144  
   145  	rslt, err := Search(clt, query)
   146  	if err != nil {
   147  		return
   148  	}
   149  
   150  	*query.Begin += rslt.ItemCount
   151  
   152  	iter = &RelationIterator{
   153  		clt: clt,
   154  
   155  		nextQuery: query,
   156  
   157  		lastSearchResult: rslt,
   158  		nextPageCalled:   false,
   159  	}
   160  	return
   161  }