You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: syncmsg.go
    path of file: ./repos/wechat/work/kf
    
    the code of the file until where you have to start completion: package kf

import (
	"encoding/json"
	"errors"
	"fmt"

	"github.com/silenceper/wechat/v2/util"
	"github.com/silenceper/wechat/v2/work/kf/syncmsg"
)

const (
	// 获取消息
	syncMsgAddr = "https://qyapi.weixin.qq.com/cgi-bin/kf/sync_msg?access_token=%s"
)

// SyncMsgOptions 获取消息查询参数
type SyncMsgOptions struct {
	Cursor      string `json:"cursor"`                 // 上一次调用时返回的next_cursor，第一次拉取可以不填, 不多于64字节
	Token       string `json:"token"`                  // 回调事件返回的token字段，10分钟内有效；可不填，如果不填接口有严格的频率限制, 不多于128字节
	Limit       uint   `json:"limit"`                  // 期望请求的数据量，默认值和最大值都为1000, 注意：可能会出现返回条数少于limit的情况，需结合返回的has_more字段判断是否继续请求。
	VoiceFormat uint   `json:"voice_format,omitempty"` // 语音消息类型，0-Amr 1-Silk，默认0。可通过该参数控制返回的语音格式，开发者可按需选择自己程序支持的一种格式
	OpenKfID    string `json:"open_kfid,omitempty"`    // 指定拉取某个客服帐号的消息，否则默认返回有权限的客服帐号的消息。当客服帐号较多，建议按open_kfid来拉取以获取更好的性能。
}

// SyncMsgSchema 获取消息查询响应内容
type syncMsgSchema struct {
	ErrCode    int32                    `json:"errcode"`     // 返回码
	ErrMsg     string                   `json:"errmsg"`      /
    
func (r *Client) SyncMsg(options SyncMsgOptions) (info SyncMsgSchema, err error) {
	var (
		accessToken string
		data        []byte
	)
	if accessToken, err = r.ctx.GetAccessToken(); err != nil {
		return
	}
	if data, err = util.PostJSON(fmt.Sprintf(syncMsgAddr, accessToken), options); err != nil {
		return
	}
	originInfo := syncMsgSchema{}
	if err = json.Unmarshal(data, &originInfo); err != nil {
		return
	}
	if originInfo.ErrCode != 0 {
		return info, errors.New(originInfo.ErrMsg)
	}
	msgList := make([]syncmsg.Message, 0)
	if len(originInfo.MsgList) > 0 {
		for _, msg := range originInfo.MsgList {
			newMsg := syncmsg.Message{}
			if val, ok := msg["msgid"].(string); ok {
				newMsg.MsgID = val
			}
			if val, ok := msg["open_kfid"].(string); ok {
				newMsg.OpenKFID = val
			}
			if val, ok := msg["external_userid"].(string); ok {
				newMsg.ExternalUserID = val
			}
			if val, ok := msg["send_time"].(float64); ok {
				newMsg.SendTime = uint64(val)
			}
			if val, ok := msg["origin"].(float64); ok {
				newMsg.Origin = uint32(val)
			}

			if val, ok := msg["msgtype"].(string); ok {
				newMsg.MsgType = val
			}
			if newMsg.MsgType == "event" {
				if event, ok := msg["event"].(map[string]interface{}); ok {
					if eType, ok := event["event_type"].(string); ok {
						newMsg.EventType = eType
					}
				}
			}
			originData, err := json.Marshal(msg)
			if err != nil {
				return info, err
			}
			newMsg.OriginData = originData
			msgList = append(msgList, newMsg)
		}
	}
	return SyncMsgSchema{
		ErrCode:    originInfo.ErrCode,
		ErrMsg:     originInfo.ErrMsg,
		NextCursor: originInfo.NextCursor,
		HasMore:    originInfo.HasMore,
		MsgList:    msgList,
	}, nil
}