package srv_mediaresource import ( "encoding/json" "errors" "net/http" "strconv" "videoweb/pub/common" "videoweb/pub/common/httputil" "videoweb/pub/common/log" "videoweb/web/api/proto" ) const ( // playletMediaListErrMsg 短剧媒资列表接口统一错误文案 playletMediaListErrMsg = "短剧媒资列表查询失败" // playletMediaSyncErrMsg 短剧媒资同步接口统一错误文案 playletMediaSyncErrMsg = "短剧媒资同步失败" // playletMediaDeletedCode 媒资中心资源已删除业务码 playletMediaDeletedCode = 7003 ) // playletMediaCenterService 短剧媒资中心客户端 type playletMediaCenterService struct { url string // 媒资中心接口域名 proId string // 媒资中心商户号 secret string // 媒资中心签名密钥,当前接口按源项目逻辑暂不签名 } // playletMediaCenterConfig 创建短剧媒资中心客户端所需配置 type playletMediaCenterConfig struct { Url string // 媒资中心接口域名 ProId string // 媒资中心商户号 Secret string // 媒资中心签名密钥 } // playletMediaCenterMsg 媒资中心统一响应结构 type playletMediaCenterMsg struct { Code int `json:"code"` // 媒资中心业务码,0 表示成功 Msg string `json:"msg"` // 媒资中心业务消息 Data json.RawMessage `json:"data"` // 媒资中心业务数据,校验 code 成功后再解析 } // playletMediaPagination 媒资中心列表分页信息。 type playletMediaPagination struct { IsLastPage bool `json:"is_last_page"` // 是否最后一页 Page uint `json:"page"` // 当前页码 Size uint `json:"size"` // 每页数量 Count uint `json:"count"` // 总数量 } // playletMediaListReq 媒资中心 /services/media/list 查询参数 type playletMediaListReq struct { MediaType int `json:"media_type"` // 媒体类型:1-动漫 2-漫画 4-漫画短剧 5-短剧 6-普通短剧 Id *uint `json:"id"` // 媒资中心资源ID VloggerId *uint `json:"vlogger_id"` // UP主ID IsUp *int `json:"is_up"` // 是否UP主资源:0-否 1-是 Title *string `json:"title"` // 标题筛选 Tag *string `json:"tag"` // 标签筛选 SyncType int `json:"sync_type"` // 同步类型:1-全量 2-增量 Page uint `json:"page"` // 页码 Size uint `json:"size"` // 每页数量 } // playletMediaListResp 媒资中心列表响应 data 节点 type playletMediaListResp struct { Data []*proto.PlayletResourceListItem `json:"data"` // 短剧媒资列表 Pagination playletMediaPagination `json:"pagination"` // 分页信息 } // playletMediaJHListResp 媒资中心嘉华短剧列表响应 data 节点 type playletMediaJHListResp struct { Data []*proto.PlayletResourceJHListItem `json:"data"` // 嘉华短剧媒资列表 Pagination playletMediaPagination `json:"pagination"` // 分页信息 } // playletMediaContent 媒资中心短剧章节内容 type playletMediaContent struct { ID uint `json:"id"` // 媒资内容ID SaleCoin uint `json:"sale_coin"` // 单集售价 VloggerId uint `json:"vlogger_id"` // UP主ID Cover string `json:"cover"` // 封面 MediaId uint `json:"video_id"` // 媒资中心资源ID MediaType int `json:"media_type"` // 媒体类型 EpisodeNumber int `json:"episode_number"` // 第几集 Title string `json:"title"` // 章节名 Text string `json:"text"` // 文本内容 Urls string `json:"urls"` // 资源地址集 Height uint `json:"height"` // 高 Width uint `json:"width"` // 宽 Ratio float64 `json:"ratio"` // 宽高比 MediaSize uint `json:"media_size"` // 资源大小 PlayTime uint `json:"play_time"` // 播放时长 M3u8Url string `json:"m3u8_url"` // m3u8视频地址 AudioUrl string `json:"audio_url"` // 音频地址 FsResourceId string `json:"fs_resource_id"` // 文件服务资源ID FsResourceStatus string `json:"fs_resource_status"` // 文件服务资源状态 HashId string `json:"hash_id"` // 资源hash DataVersion int8 `json:"data_version"` // 数据版本 TerminalCdo string `json:"terminal_cdo"` // 上传者 CreateTime int64 `json:"create_time"` // 创建时间 UpdateTime int64 `json:"update_time"` // 更新时间 } // playletMediaSyncReq 媒资中心 /services/media/sync 查询参数 type playletMediaSyncReq struct { Id uint `json:"id"` // 媒资中心资源ID SyncTime int64 `json:"sync_time"` // 增量同步时间,0 表示拉全量详情 } // playletMediaSyncResp 媒资中心同步响应 data 节点 type playletMediaSyncResp struct { IsDelete bool `json:"-"` // 是否已从媒资中心删除 Media *proto.PlayletResourceListItem `json:"media"` // 短剧主资源 MediaContentList []playletMediaContent `json:"media_content_list"` // 短剧章节资源 } // newPlayletMediaCenterService 创建短剧媒资中心客户端 func newPlayletMediaCenterService(c playletMediaCenterConfig) *playletMediaCenterService { return &playletMediaCenterService{ url: c.Url, proId: c.ProId, secret: c.Secret, } } // mediaListParams 构造媒资中心列表查询参数 func (m *playletMediaCenterService) mediaListParams(p *playletMediaListReq) map[string]string { params := map[string]string{ "media_type": strconv.Itoa(p.MediaType), "sync_type": strconv.Itoa(p.SyncType), "page": strconv.FormatUint(uint64(p.Page), 10), "size": strconv.FormatUint(uint64(p.Size), 10), "pro_id": m.proId, "sign": m.sign(), } if p.Id != nil { params["id"] = strconv.FormatUint(uint64(*p.Id), 10) } if p.VloggerId != nil { params["vlogger_id"] = strconv.FormatUint(uint64(*p.VloggerId), 10) } if p.IsUp != nil { params["is_up"] = strconv.Itoa(*p.IsUp) } if p.Title != nil { params["title"] = *p.Title } if p.Tag != nil { params["tag"] = *p.Tag } return params } // mediaSyncParams 构造媒资中心同步查询参数 func (m *playletMediaCenterService) mediaSyncParams(p *playletMediaSyncReq) map[string]string { return map[string]string{ "id": strconv.FormatUint(uint64(p.Id), 10), "sync_time": strconv.FormatInt(p.SyncTime, 10), "pro_id": m.proId, "sign": m.sign(), } } // mediaList 查询短剧媒资列表 func (m *playletMediaCenterService) mediaList(p *playletMediaListReq) (result playletMediaListResp, err error) { var retMsg playletMediaCenterMsg params := m.mediaListParams(p) path := "/services/media/list" log.Info("查询短剧媒资列表", log.Any("params", params)) code, err := httputil.Client().GetWithJResp(&retMsg, common.BindUrl(m.url, path), nil, params) if err != nil { log.Error("查询短剧媒资列表请求失败", log.Any("code", code), log.E(err)) return result, errors.New(playletMediaListErrMsg) } if code != http.StatusOK { log.Error("查询短剧媒资列表状态码异常", log.Any("code", code)) return result, errors.New(playletMediaListErrMsg) } if retMsg.Code != 0 { log.Error("查询短剧媒资列表业务码异常", log.Any("retMsg", retMsg)) return result, errors.New(playletMediaListErrMsg) } if err = json.Unmarshal(retMsg.Data, &result); err != nil { log.Error("解析短剧媒资列表失败", log.E(err)) return result, errors.New(playletMediaListErrMsg) } return result, nil } // mediaJHList 查询嘉华短剧媒资列表 func (m *playletMediaCenterService) mediaJHList(p *playletMediaListReq) (result playletMediaJHListResp, err error) { var retMsg playletMediaCenterMsg params := m.mediaListParams(p) path := "/services/media/list" log.Info("查询嘉华短剧媒资列表", log.Any("params", params)) code, err := httputil.Client().GetWithJResp(&retMsg, common.BindUrl(m.url, path), nil, params) if err != nil { log.Error("查询嘉华短剧媒资列表请求失败", log.Any("code", code), log.E(err)) return result, errors.New(playletMediaListErrMsg) } if code != http.StatusOK { log.Error("查询嘉华短剧媒资列表状态码异常", log.Any("code", code)) return result, errors.New(playletMediaListErrMsg) } if retMsg.Code != 0 { log.Error("查询嘉华短剧媒资列表业务码异常", log.Any("retMsg", retMsg)) return result, errors.New(playletMediaListErrMsg) } if err = json.Unmarshal(retMsg.Data, &result); err != nil { log.Error("解析嘉华短剧媒资列表失败", log.E(err)) return result, errors.New(playletMediaListErrMsg) } return result, nil } // mediaSync 查询短剧媒资详情和章节内容 func (m *playletMediaCenterService) mediaSync(p *playletMediaSyncReq) (result playletMediaSyncResp, err error) { var retMsg playletMediaCenterMsg params := m.mediaSyncParams(p) path := "/services/media/sync" code, err := httputil.Client().GetWithJResp(&retMsg, common.BindUrl(m.url, path), nil, params) if err != nil { log.Error("同步短剧媒资详情请求失败", log.Any("params", params), log.Any("code", code), log.E(err)) return result, errors.New(playletMediaSyncErrMsg) } if code != http.StatusOK { log.Error("同步短剧媒资详情状态码异常", log.Any("params", params), log.Any("code", code)) return result, errors.New(playletMediaSyncErrMsg) } if retMsg.Code == playletMediaDeletedCode { result.IsDelete = true return result, nil } if retMsg.Code != 0 { log.Error("同步短剧媒资详情业务码异常", log.Any("params", params), log.Any("retMsg", retMsg)) return result, errors.New(playletMediaSyncErrMsg) } if err = json.Unmarshal(retMsg.Data, &result); err != nil { log.Error("解析短剧媒资详情失败", log.Any("params", params), log.E(err)) return result, errors.New(playletMediaSyncErrMsg) } return result, nil } // sign 生成媒资中心签名 func (m *playletMediaCenterService) sign() string { return "" }