diff --git a/marketing-api/QIANCHUAN.md b/marketing-api/QIANCHUAN.md index 8727e14f..583b3ceb 100644 --- a/marketing-api/QIANCHUAN.md +++ b/marketing-api/QIANCHUAN.md @@ -121,6 +121,8 @@ - 获取低效素材 [ api.qianchuan.file.VideoEffeciencyGet(clt *core.SDKClient, accessToken string, req *api.qianchuan.file.VideoEffeciencyGetRequest) ([]string, error) ] - 批量删除图片素材 [ api.qianchuan.file.ImageDelete(clt *core.SDKClient, accessToken string, req *api.qianchuan.file.ImageDeleteRequest) ([]string, error) ] - 批量删除视频素材 [ api.qianchuan.file.VideoDelete(clt *core.SDKClient, accessToken string, req *api.qianchuan.file.VideoDeleteRequest) ([]string, error) ] + - 获取千川素材库图文 [ api.qianchuan.carousel.Get(clt *core.SDKClient, req *carousel.GetRequest, accessToken string) (*carousel.GetResult, error) ] + - 获取抖音号下图文 [ api.qianchuan.carousel.AwemeGet(clt *core.SDKClient, req *carousel.AwemeGetRequest, accessToken string) (*carousel.AwemeGetResult, error) ] - 工具 - 查询工具 - 获取行业列表 [ tools.IndustryGet(clt *core.SDKClient, accessToken string, req *tools.IndustryGetRequest) ([]tools.Industry, error) ] diff --git a/marketing-api/api/qianchuan/carousel/aweme_get.go b/marketing-api/api/qianchuan/carousel/aweme_get.go new file mode 100644 index 00000000..0438cf00 --- /dev/null +++ b/marketing-api/api/qianchuan/carousel/aweme_get.go @@ -0,0 +1,16 @@ +package carousel + +import ( + "github.com/bububa/oceanengine/marketing-api/core" + "github.com/bububa/oceanengine/marketing-api/model/qianchuan/carousel" +) + +// AwemeGet 获取抖音号下图文 +// 通过商品id获取抖音号下已有的图文素材,当前仅短视频带货支持,必须传商品id +func AwemeGet(clt *core.SDKClient, req *carousel.AwemeGetRequest, accessToken string) (*carousel.AwemeGetResult, error) { + var resp carousel.AwemeGetResponse + if err := clt.Get("v1.0/qianchuan/carousel/aweme/get/", req, &resp, accessToken); err != nil { + return nil, err + } + return resp.Data, nil +} diff --git a/marketing-api/api/qianchuan/carousel/get.go b/marketing-api/api/qianchuan/carousel/get.go new file mode 100644 index 00000000..0336c023 --- /dev/null +++ b/marketing-api/api/qianchuan/carousel/get.go @@ -0,0 +1,15 @@ +package carousel + +import ( + "github.com/bububa/oceanengine/marketing-api/core" + "github.com/bububa/oceanengine/marketing-api/model/qianchuan/carousel" +) + +// Get 获取千川素材库图文 +func Get(clt *core.SDKClient, req *carousel.GetRequest, accessToken string) (*carousel.GetResult, error) { + var resp carousel.GetResponse + if err := clt.Get("v1.0/qianchuan/carousel/get/", req, &resp, accessToken); err != nil { + return nil, err + } + return resp.Data, nil +} diff --git a/marketing-api/enum/material_mode.go b/marketing-api/enum/material_mode.go index b76c2c05..281e20a6 100644 --- a/marketing-api/enum/material_mode.go +++ b/marketing-api/enum/material_mode.go @@ -22,4 +22,6 @@ const ( MaterialMode_UNION_SPLASH MaterialMode = "UNION_SPLASH" // MaterialMode_AWEME_LIVE_ROOM 直播画面类型 MaterialMode_AWEME_LIVE_ROOM MaterialMode = "AWEME_LIVE_ROOM" + // MaterialMode_CAROUSEL 图文 + MaterialMode_CAROUSEL MaterialMode = "CAROUSEL" ) diff --git a/marketing-api/enum/qianchuan/carousel_source.go b/marketing-api/enum/qianchuan/carousel_source.go new file mode 100644 index 00000000..4f2b162d --- /dev/null +++ b/marketing-api/enum/qianchuan/carousel_source.go @@ -0,0 +1,9 @@ +package qianchuan + +// CarouselSource 图文素材来源 +type CarouselSource string + +const ( + // CarouselSource_JICHAUNG 即创 + CarouselSource_JICHAUNG CarouselSource = "JICHAUNG" +) diff --git a/marketing-api/enum/qianchuan/title_type.go b/marketing-api/enum/qianchuan/title_type.go new file mode 100644 index 00000000..4d59ead2 --- /dev/null +++ b/marketing-api/enum/qianchuan/title_type.go @@ -0,0 +1,13 @@ +package qianchuan + +// TitleType 素材类型 +type TitleType string + +const ( + // TitleType_CUSTOM 自定义标题 + TitleType_CUSTOM TitleType = "CUSTOM" + // TitleType_COMMODITY_CARD 商品卡标题 + TitleType_COMMODITY_CARD TitleType = "COMMODITY_CARD" + // TitleType_AWEME_CAROUSEL 抖音主页图集标题 + TitleType_AWEME_CAROUSEL TitleType = "AWEME_CAROUSEL" +) diff --git a/marketing-api/model/qianchuan/ad/compensate_status_get.go b/marketing-api/model/qianchuan/ad/compensate_status_get.go index 91e89cf9..eae0e27f 100644 --- a/marketing-api/model/qianchuan/ad/compensate_status_get.go +++ b/marketing-api/model/qianchuan/ad/compensate_status_get.go @@ -16,6 +16,7 @@ type CompensateStatusGetRequest struct { AdIDs []uint64 `json:"ad_ids,omitempty"` } +// Encode implement GetRequest interface func (r CompensateStatusGetRequest) Encode() string { values := util.GetUrlValues() values.Set("advertiser_id", strconv.FormatUint(r.AdvertiserID, 10)) diff --git a/marketing-api/model/qianchuan/ad/learning_status_get.go b/marketing-api/model/qianchuan/ad/learning_status_get.go index 69b0c0ad..9f5be8ce 100644 --- a/marketing-api/model/qianchuan/ad/learning_status_get.go +++ b/marketing-api/model/qianchuan/ad/learning_status_get.go @@ -16,6 +16,7 @@ type LearningStatusGetRequest struct { AdIDs []uint64 `json:"ad_ids,omitempty"` } +// Encode implement GetRequest interface func (r LearningStatusGetRequest) Encode() string { values := util.GetUrlValues() values.Set("advertiser_id", strconv.FormatUint(r.AdvertiserID, 10)) diff --git a/marketing-api/model/qianchuan/carousel/audio.go b/marketing-api/model/qianchuan/carousel/audio.go new file mode 100644 index 00000000..f61ee89a --- /dev/null +++ b/marketing-api/model/qianchuan/carousel/audio.go @@ -0,0 +1,9 @@ +package carousel + +// Audio 音频信息 +type Audio struct { + // VideoID 音频id + VideoID string `json:"video_id,omitempty"` + // URL 音频URL + URL string `json:"url,omitempty"` +} diff --git a/marketing-api/model/qianchuan/carousel/aweme_get.go b/marketing-api/model/qianchuan/carousel/aweme_get.go new file mode 100644 index 00000000..8cd557c6 --- /dev/null +++ b/marketing-api/model/qianchuan/carousel/aweme_get.go @@ -0,0 +1,93 @@ +package carousel + +import ( + "strconv" + + "github.com/bububa/oceanengine/marketing-api/model" + "github.com/bububa/oceanengine/marketing-api/util" +) + +// AwemeGetRequest 获取抖音号下图文 API Request +type AwemeGetRequest struct { + // AdvertiserID 广告主id + AdvertiserID uint64 `json:"advertiser_id,omitempty"` + // AwemeID 抖音号uid,需拉取图文的抖音号,可通过「千川账户下已授权抖音号」获取 + AwemeID uint64 `json:"aweme_id,omitempty"` + // Filtering 图文过滤条件 + Filtering *AwemeGetFilter `json:"filtering,omitempty"` + // Cursor 页码游标值,第一次拉取,无需入参 + Cursor int `json:"cursor,omitempty"` + // Count 页面大小,默认值30,限制1-50 + Count int `json:"count,omitempty"` +} + +type AwemeGetFilter struct { + // ProductID 商品id + ProductID uint64 `json:"product_id,omitempty"` + // AwemeItemURL 图文url链接 + AwemeItemURL string `json:"aweme_item_url,omitempty"` + // AwemeCarouselID 挂车商品指定的筛选主页图文id + AwemeCarouseID uint64 `json:"aweme_carousel_id,omitempty"` +} + +// Encode implement GetRequest interface +func (r AwemeGetRequest) Encode() string { + values := util.GetUrlValues() + values.Set("advertiser_id", strconv.FormatUint(r.AdvertiserID, 10)) + values.Set("aweme_id", strconv.FormatUint(r.AwemeID, 10)) + if r.Filtering != nil { + values.Set("filtering", string(util.JSONMarshal(r.Filtering))) + } + if r.Cursor > 0 { + values.Set("cursor", strconv.Itoa(r.Cursor)) + } + if r.Count > 0 { + values.Set("count", strconv.Itoa(r.Count)) + } + ret := values.Encode() + util.PutUrlValues(values) + return ret +} + +// AwemeGetResponse 获取抖音号下图文 API Response +type AwemeGetResponse struct { + model.BaseResponse + Data *AwemeGetResult `json:"data,omitempty"` +} + +type AwemeGetResult struct { + // PageInfo 分页信息 + PageInfo *model.PageInfo `json:"page_info,omitempty"` + // ImageAggregateList 图文列表 + ImageAggregateList []AwemeCarousel `json:"image_aggregate_list,omitempty"` +} + +// AwemeCarousel 抖音号图文 +type AwemeCarousel struct { + // AwemeCarouselID 图文itemid + AwemeCarouselID string `json:"aweme_carousel_id,omitempty"` + // Title 图文标题 + Title string `json:"title,omitempty"` + // Description 图文描述 + Description string `json:"description,omitempty"` + // Images 图文图片列表 + Images []Image `json:"images,omitempty"` + // MusicID 音乐ID + MusicID string `json:"music_id,omitempty"` + // MusicURL 音乐播放链接 + MusicURL string `json:"music_url,omitempty"` + // Metrics 数据指标 + Metrics *Metrics `json:"metrics,omitempty"` +} + +// Metrics 数据指标 +type Metrics struct { + // ViewCnt 观看数 + ViewCnt int64 `json:"view_cnt,omitempty"` + // LikeCnt 点赞数 + LikeCnt int64 `json:"like_cnt,omitempty"` + // ShareCnt 分享数 + ShareCnt int64 `json:"share_cnt,omitempty"` + // CommentCnt 评论数 + CommentCnt int64 `json:"comment_cnt,omitempty"` +} diff --git a/marketing-api/model/qianchuan/carousel/get.go b/marketing-api/model/qianchuan/carousel/get.go new file mode 100644 index 00000000..b0396477 --- /dev/null +++ b/marketing-api/model/qianchuan/carousel/get.go @@ -0,0 +1,100 @@ +package carousel + +import ( + "strconv" + + "github.com/bububa/oceanengine/marketing-api/enum" + "github.com/bububa/oceanengine/marketing-api/enum/qianchuan" + "github.com/bububa/oceanengine/marketing-api/model" + "github.com/bububa/oceanengine/marketing-api/util" +) + +// GetRequest 获取千川素材库图文 API Request +type GetRequest struct { + // AdvertiserID 广告主id + AdvertiserID uint64 `json:"advertiser_id,omitempty"` + // Filtering 图文过滤信息 + Filtering *GetFilter `json:"filtering,omitempty"` + // OrderFields 排序字段,默认不传为create_time,见返回参数中metrics + OrderFields string `json:"order_fields,omitempty"` + // OrderType 排序方式,允许值: + // ASC 升序(默认) + // DESC 降序 + OrderType enum.OrderType `json:"order_type,omitempty"` + // Page 页码,默认值1 + Page int `json:"page,omitempty"` + // PageSize 页面大小,默认值20 + PageSize int `json:"page_size,omitempty"` +} + +type GetFilter struct { + // MaterialIDs 素材id列表,可以根据material_ids(素材报表使用的id,一个素材唯一对应一个素材id)进行过滤 + // 数量限制:<=100 + MaterialIDs []uint64 `json:"material_ids,omitempty"` + // Sources 图文素材来源,允许值 + // JICHAUNG 即创 + Sources []qianchuan.CarouselSource `json:"sources,omitempty"` + // ImageMode 素材类型,允许值 + // CAROUSEL 图文 + ImageMode enum.MaterialMode `json:"image_mode,omitempty"` + // QueryString 支持根据图文名称/ID搜索 + QueryString string `json:"query_string,omitempty"` + // StartTime 根据图片上传时间进行过滤的起始时间,与end_time搭配使用,格式:"yyyy-mm-dd" + StartTime string `json:"start_time,omitempty"` + // EndTime 根据图片上传时间进行过滤的截止时间,与start_time搭配使用,格式:"yyyy-mm-dd" + EndTime string `json:"end_time,omitempty"` +} + +// Encode implement GetRequest interface +func (r GetRequest) Encode() string { + values := util.GetUrlValues() + values.Set("advertiser_id", strconv.FormatUint(r.AdvertiserID, 10)) + if r.Filtering != nil { + values.Set("filtering", string(util.JSONMarshal(r.Filtering))) + } + if r.OrderFields != "" { + values.Set("order_fields", r.OrderFields) + } + if r.OrderType != "" { + values.Set("order_type", string(r.OrderType)) + } + if r.Page > 0 { + values.Set("page", strconv.Itoa(r.Page)) + } + if r.PageSize > 0 { + values.Set("page_size", strconv.Itoa(r.PageSize)) + } + ret := values.Encode() + util.PutUrlValues(values) + return ret +} + +// GetResponse 获取千川素材库图文 API Response +type GetResponse struct { + model.BaseResponse + Data *GetResult `json:"data,omitempty"` +} + +type GetResult struct { + PageInfo *model.PageInfo `json:"page_info,omitempty"` + Carousels []Carousel `json:"carousels,omitempty"` +} + +// Carousel 素材信息 +type Carousel struct { + // MaterialID 素材id + MaterialID uint64 `json:"material_id,omitempty"` + // ImageMode 素材类型: + // CAROUSEL 图文 + ImageMode enum.MaterialMode `json:"image_mode,omitempty"` + // Images 图片信息 + Images []Image `json:"images,omitempty"` + // Audio 音频信息 + Audio *Audio `json:"audio,omitempty"` + // Filename 素材的文件名 + Filename string `json:"filename,omitempty"` + // CreateTime 图文创建时间 + CreateTime string `json:"create_time,omitempty"` + // Description 素材描述 + Description string `json:"description,omitempty"` +} diff --git a/marketing-api/model/qianchuan/carousel/image.go b/marketing-api/model/qianchuan/carousel/image.go new file mode 100644 index 00000000..4bf7c484 --- /dev/null +++ b/marketing-api/model/qianchuan/carousel/image.go @@ -0,0 +1,19 @@ +package carousel + +// Image 图片信息 +type Image struct { + // ImageID 图片id + ImageID string `json:"image_id,omitempty"` + // ImageMaterialID 图片素材id + ImageMaterialID uint64 `json:"image_material_id,omitempty"` + // Height 图片高度 + Height int `json:"height,omitempty"` + // Width 图片宽度 + Width int `json:"width,omitempty"` + // Ratio 图片比例 + Ratio float64 `json:"ratio,omitempty"` + // WebURL 图片url + WebURL string `json:"web_url,omitempty"` + // URL 图片url + URL string `json:"url,omitempty"` +} diff --git a/marketing-api/model/qianchuan/creative/carousel_material.go b/marketing-api/model/qianchuan/creative/carousel_material.go new file mode 100644 index 00000000..21792d23 --- /dev/null +++ b/marketing-api/model/qianchuan/creative/carousel_material.go @@ -0,0 +1,9 @@ +package creative + +// CarouselMaterial 图文信息 +type CarouselMaterial struct { + // AwemeCarouselID 抖音图文id + AwemeCarouselID uint64 `json:"aweme_carousel_id,omitempty"` + // CarouselID 图文ID + CarouselID uint64 `json:"carousel_id,omitempty"` +} diff --git a/marketing-api/model/qianchuan/creative/creative.go b/marketing-api/model/qianchuan/creative/creative.go index 5d629054..046f3cff 100644 --- a/marketing-api/model/qianchuan/creative/creative.go +++ b/marketing-api/model/qianchuan/creative/creative.go @@ -29,6 +29,8 @@ type Creative struct { ImageMaterial *ImageMaterial `json:"image_material,omitempty"` // TitleMaterial 标题素材 TitleMaterial *TitleMaterial `json:"title_material,omitempty"` + // CarouselMaterial 图文信息,对应image_mode=CAROUSEL + CarouselMaterial *CarouselMaterial `json:"carousel_material,omitempty"` // LabAdType 托管计划类型,NOT_LAB_AD:非托管计划,LAB_AD:托管计划 LabAdType enum.AdLabType `json:"ad_lab_type,omitempty"` // VideoMaterialList 视频素材列表 diff --git a/marketing-api/model/qianchuan/creative/programmatic_creative.go b/marketing-api/model/qianchuan/creative/programmatic_creative.go index 5cc85b03..3131174e 100644 --- a/marketing-api/model/qianchuan/creative/programmatic_creative.go +++ b/marketing-api/model/qianchuan/creative/programmatic_creative.go @@ -12,6 +12,10 @@ type ProgrammaticCreativeMedia struct { VideoCoverID string `json:"video_cover_id,omitempty"` // ImageIDs 图片ID列表 ImageIDs []string `json:"image_ids,omitempty"` + // CarouselID 素材库图文id + CarouselID uint64 `json:"carousel_id,omitempty"` + // AwemeCarouselID 抖音主页图文id + AwemeCarouselID uint64 `json:"aweme_carousel_id,omitempty"` // IsAutoGenerate 是否为派生创意标识,1:是,0:不是 IsAutoGenerate int `json:"is_auto_generate,omitempty"` } diff --git a/marketing-api/model/qianchuan/creative/title_material.go b/marketing-api/model/qianchuan/creative/title_material.go index 816fe1d4..7551127a 100644 --- a/marketing-api/model/qianchuan/creative/title_material.go +++ b/marketing-api/model/qianchuan/creative/title_material.go @@ -1,11 +1,22 @@ package creative +import "github.com/bububa/oceanengine/marketing-api/enum/qianchuan" + // TitleMaterial 标题素材 type TitleMaterial struct { // ID 素材唯一标识 ID uint64 `json:"id,omitempty"` // Title 创意标题 Title string `json:"title,omitempty"` + // TitleType 素材类型,可选值 + // CUSTOM自定义标题 + // COMMODITY_CARD商品卡标题 + // 注意:商品卡标题限制条件如下: + // 广告主类型为商家 + // 抖音号选择的是「官方」或「自运营」 + TitleType qianchuan.TitleType `json:"title_type,omitempty"` + // AwemeCarouselID 抖音主页图文id + AwemeCarouselID uint64 `json:"aweme_carousel_id,omitempty"` // DynamicWords 动态词包对象列表 DynamicWords []DynamicWord `json:"dynamic_words,omitempty"` }