批量导出Excel表格以及压缩图片
This commit is contained in:
commit
60c8855993
@ -3327,6 +3327,9 @@ type WorkInfoResp struct {
|
||||
ArtistPhone string `protobuf:"bytes,4,opt,name=artistPhone,proto3" json:"artistPhone"`
|
||||
ArtistPhoneAreaCode string `protobuf:"bytes,5,opt,name=artistPhoneAreaCode,proto3" json:"artistPhoneAreaCode"`
|
||||
WorkCategory uint32 `protobuf:"varint,6,opt,name=workCategory,proto3" json:"workCategory"`
|
||||
PlatformInfoData []*PlatformInfo `protobuf:"bytes,7,rep,name=platformInfoData,proto3" json:"platformInfoData"`
|
||||
Title string `protobuf:"bytes,8,opt,name=title,proto3" json:"title"`
|
||||
PublishStatus PublishStatusENUM `protobuf:"varint,9,opt,name=publishStatus,proto3,enum=Cast.PublishStatusENUM" json:"publishStatus"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@ -3403,6 +3406,27 @@ func (x *WorkInfoResp) GetWorkCategory() uint32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *WorkInfoResp) GetPlatformInfoData() []*PlatformInfo {
|
||||
if x != nil {
|
||||
return x.PlatformInfoData
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *WorkInfoResp) GetTitle() string {
|
||||
if x != nil {
|
||||
return x.Title
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *WorkInfoResp) GetPublishStatus() PublishStatusENUM {
|
||||
if x != nil {
|
||||
return x.PublishStatus
|
||||
}
|
||||
return PublishStatusENUM_PublishMediaStatus_NO
|
||||
}
|
||||
|
||||
// 发布成功的作品列表请求
|
||||
type WorkListPublishedReq struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
@ -3765,7 +3789,7 @@ type PlatformInfo struct {
|
||||
PublishType uint32 `protobuf:"varint,4,opt,name=publishType,proto3" json:"publishType"`
|
||||
PublishResp string `protobuf:"bytes,5,opt,name=publishResp,proto3" json:"publishResp"`
|
||||
PublishMediaId string `protobuf:"bytes,6,opt,name=publishMediaId,proto3" json:"publishMediaId"`
|
||||
PublishStatus PublishStatusENUM `protobuf:"varint,7,opt,name=publishStatus,proto3,enum=Cast.PublishStatusENUM" json:"publishStatus"`
|
||||
PublishMediaStatus PublishStatusENUM `protobuf:"varint,7,opt,name=publishMediaStatus,proto3,enum=Cast.PublishStatusENUM" json:"publishMediaStatus"`
|
||||
Remark string `protobuf:"bytes,8,opt,name=remark,proto3" json:"remark"`
|
||||
PlatformUuid string `protobuf:"bytes,9,opt,name=platformUuid,proto3" json:"platformUuid"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
@ -3844,9 +3868,9 @@ func (x *PlatformInfo) GetPublishMediaId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *PlatformInfo) GetPublishStatus() PublishStatusENUM {
|
||||
func (x *PlatformInfo) GetPublishMediaStatus() PublishStatusENUM {
|
||||
if x != nil {
|
||||
return x.PublishStatus
|
||||
return x.PublishMediaStatus
|
||||
}
|
||||
return PublishStatusENUM_PublishMediaStatus_NO
|
||||
}
|
||||
@ -12947,6 +12971,7 @@ type UpsertTaskListReq struct {
|
||||
Status uint32 `protobuf:"varint,4,opt,name=status,proto3" json:"status"` // 状态:1-待处理 2-处理中 3-处理完成
|
||||
OperatorID string `protobuf:"bytes,5,opt,name=operatorID,proto3" json:"operatorID"` // 操作人ID
|
||||
OperatorName string `protobuf:"bytes,6,opt,name=operatorName,proto3" json:"operatorName"` // 操作人名称
|
||||
ExtraData string `protobuf:"bytes,7,opt,name=extraData,proto3" json:"extraData"` // 扩展信息
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@ -13023,6 +13048,13 @@ func (x *UpsertTaskListReq) GetOperatorName() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *UpsertTaskListReq) GetExtraData() string {
|
||||
if x != nil {
|
||||
return x.ExtraData
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// 新增或更新任务响应
|
||||
type UpsertTaskListResp struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
@ -13132,6 +13164,7 @@ type TaskListInfo struct {
|
||||
OperatorName string `protobuf:"bytes,6,opt,name=operatorName,proto3" json:"operatorName"` // 操作人名称
|
||||
CreatedAt string `protobuf:"bytes,7,opt,name=createdAt,proto3" json:"createdAt"` // 创建时间
|
||||
UpdatedAt string `protobuf:"bytes,8,opt,name=updatedAt,proto3" json:"updatedAt"` // 更新时间
|
||||
ExtraData string `protobuf:"bytes,9,opt,name=extraData,proto3" json:"extraData"` // 扩展信息
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@ -13222,6 +13255,13 @@ func (x *TaskListInfo) GetUpdatedAt() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *TaskListInfo) GetExtraData() string {
|
||||
if x != nil {
|
||||
return x.ExtraData
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// 获取任务详情响应
|
||||
type GetTaskListResp struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
@ -17263,7 +17303,7 @@ const file_pb_fiee_cast_proto_rawDesc = "" +
|
||||
"DelWorkReq\x12\x1a\n" +
|
||||
"\bworkUuid\x18\x01 \x01(\tR\bworkUuid\")\n" +
|
||||
"\vWorkInfoReq\x12\x1a\n" +
|
||||
"\bworkUuid\x18\x01 \x01(\tR\bworkUuid\"\xe6\x01\n" +
|
||||
"\bworkUuid\x18\x01 \x01(\tR\bworkUuid\"\xfb\x02\n" +
|
||||
"\fWorkInfoResp\x12\x1e\n" +
|
||||
"\n" +
|
||||
"workStatus\x18\x01 \x01(\rR\n" +
|
||||
@ -17276,7 +17316,10 @@ const file_pb_fiee_cast_proto_rawDesc = "" +
|
||||
"artistName\x12 \n" +
|
||||
"\vartistPhone\x18\x04 \x01(\tR\vartistPhone\x120\n" +
|
||||
"\x13artistPhoneAreaCode\x18\x05 \x01(\tR\x13artistPhoneAreaCode\x12\"\n" +
|
||||
"\fworkCategory\x18\x06 \x01(\rR\fworkCategory\"f\n" +
|
||||
"\fworkCategory\x18\x06 \x01(\rR\fworkCategory\x12>\n" +
|
||||
"\x10platformInfoData\x18\a \x03(\v2\x12.Cast.PlatformInfoR\x10platformInfoData\x12\x14\n" +
|
||||
"\x05title\x18\b \x01(\tR\x05title\x12=\n" +
|
||||
"\rpublishStatus\x18\t \x01(\x0e2\x17.Cast.PublishStatusENUMR\rpublishStatus\"f\n" +
|
||||
"\x14WorkListPublishedReq\x12\x1e\n" +
|
||||
"\n" +
|
||||
"artistUuid\x18\x01 \x01(\tR\n" +
|
||||
@ -17327,7 +17370,7 @@ const file_pb_fiee_cast_proto_rawDesc = "" +
|
||||
"imageWorks\x18\x01 \x03(\v2\x18.Cast.UpdateWorkImageReqR\n" +
|
||||
"imageWorks\x12\"\n" +
|
||||
"\fsuccessCount\x18\x02 \x01(\x05R\fsuccessCount\x12\x1c\n" +
|
||||
"\tfailCount\x18\x03 \x01(\x05R\tfailCount\"\xdd\x02\n" +
|
||||
"\tfailCount\x18\x03 \x01(\x05R\tfailCount\"\xe7\x02\n" +
|
||||
"\fPlatformInfo\x12\x1a\n" +
|
||||
"\bworkUuid\x18\x01 \x01(\tR\bworkUuid\x12*\n" +
|
||||
"\x10mediaAccountUuid\x18\x02 \x01(\tR\x10mediaAccountUuid\x12\x1e\n" +
|
||||
@ -17336,8 +17379,8 @@ const file_pb_fiee_cast_proto_rawDesc = "" +
|
||||
"platformID\x12 \n" +
|
||||
"\vpublishType\x18\x04 \x01(\rR\vpublishType\x12 \n" +
|
||||
"\vpublishResp\x18\x05 \x01(\tR\vpublishResp\x12&\n" +
|
||||
"\x0epublishMediaId\x18\x06 \x01(\tR\x0epublishMediaId\x12=\n" +
|
||||
"\rpublishStatus\x18\a \x01(\x0e2\x17.Cast.PublishStatusENUMR\rpublishStatus\x12\x16\n" +
|
||||
"\x0epublishMediaId\x18\x06 \x01(\tR\x0epublishMediaId\x12G\n" +
|
||||
"\x12publishMediaStatus\x18\a \x01(\x0e2\x17.Cast.PublishStatusENUMR\x12publishMediaStatus\x12\x16\n" +
|
||||
"\x06remark\x18\b \x01(\tR\x06remark\x12\"\n" +
|
||||
"\fplatformUuid\x18\t \x01(\tR\fplatformUuid\"[\n" +
|
||||
"\x19UpdateWorkPlatformInfoReq\x12>\n" +
|
||||
@ -18421,7 +18464,7 @@ const file_pb_fiee_cast_proto_rawDesc = "" +
|
||||
"\tupdatedAt\x18\x14 \x01(\x05R\tupdatedAt\"`\n" +
|
||||
"\x18ListWorkMetricsDailyResp\x12.\n" +
|
||||
"\x04data\x18\x01 \x03(\v2\x1a.Cast.WorkMetricsDailyInfoR\x04data\x12\x14\n" +
|
||||
"\x05count\x18\x02 \x01(\x03R\x05count\"\xad\x01\n" +
|
||||
"\x05count\x18\x02 \x01(\x03R\x05count\"\xcb\x01\n" +
|
||||
"\x11UpsertTaskListReq\x12\x12\n" +
|
||||
"\x04uuid\x18\x01 \x01(\tR\x04uuid\x12\x16\n" +
|
||||
"\x06action\x18\x02 \x01(\tR\x06action\x12\x10\n" +
|
||||
@ -18430,12 +18473,13 @@ const file_pb_fiee_cast_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"operatorID\x18\x05 \x01(\tR\n" +
|
||||
"operatorID\x12\"\n" +
|
||||
"\foperatorName\x18\x06 \x01(\tR\foperatorName\":\n" +
|
||||
"\foperatorName\x18\x06 \x01(\tR\foperatorName\x12\x1c\n" +
|
||||
"\textraData\x18\a \x01(\tR\textraData\":\n" +
|
||||
"\x12UpsertTaskListResp\x12\x12\n" +
|
||||
"\x04uuid\x18\x01 \x01(\tR\x04uuid\x12\x10\n" +
|
||||
"\x03msg\x18\x02 \x01(\tR\x03msg\"$\n" +
|
||||
"\x0eGetTaskListReq\x12\x12\n" +
|
||||
"\x04uuid\x18\x01 \x01(\tR\x04uuid\"\xe4\x01\n" +
|
||||
"\x04uuid\x18\x01 \x01(\tR\x04uuid\"\x82\x02\n" +
|
||||
"\fTaskListInfo\x12\x12\n" +
|
||||
"\x04uuid\x18\x01 \x01(\tR\x04uuid\x12\x16\n" +
|
||||
"\x06action\x18\x02 \x01(\tR\x06action\x12\x10\n" +
|
||||
@ -18446,7 +18490,8 @@ const file_pb_fiee_cast_proto_rawDesc = "" +
|
||||
"operatorID\x12\"\n" +
|
||||
"\foperatorName\x18\x06 \x01(\tR\foperatorName\x12\x1c\n" +
|
||||
"\tcreatedAt\x18\a \x01(\tR\tcreatedAt\x12\x1c\n" +
|
||||
"\tupdatedAt\x18\b \x01(\tR\tupdatedAt\"K\n" +
|
||||
"\tupdatedAt\x18\b \x01(\tR\tupdatedAt\x12\x1c\n" +
|
||||
"\textraData\x18\t \x01(\tR\textraData\"K\n" +
|
||||
"\x0fGetTaskListResp\x12&\n" +
|
||||
"\x04data\x18\x01 \x01(\v2\x12.Cast.TaskListInfoR\x04data\x12\x10\n" +
|
||||
"\x03msg\x18\x02 \x01(\tR\x03msg\"\x91\x01\n" +
|
||||
@ -19108,268 +19153,270 @@ var file_pb_fiee_cast_proto_depIdxs = []int32{
|
||||
200, // 34: Cast.MediaAccountsResp.data:type_name -> Cast.MediaAccountsResp.Info
|
||||
201, // 35: Cast.MediaWorksResp.data:type_name -> Cast.MediaWorksResp.Info
|
||||
202, // 36: Cast.PublishResp.data:type_name -> Cast.PublishResp.Info
|
||||
203, // 37: Cast.WorkListPublishedResp.data:type_name -> Cast.WorkListPublishedResp.Info
|
||||
16, // 38: Cast.ImportWorkBatchReq.imageWorks:type_name -> Cast.UpdateWorkImageReq
|
||||
16, // 39: Cast.ImportWorkBatchResp.imageWorks:type_name -> Cast.UpdateWorkImageReq
|
||||
4, // 40: Cast.PlatformInfo.publishStatus:type_name -> Cast.PublishStatusENUM
|
||||
48, // 41: Cast.UpdateWorkPlatformInfoReq.PlatformInfoData:type_name -> Cast.PlatformInfo
|
||||
0, // 42: Cast.UpdateWorkPublishLogReq.platformID:type_name -> Cast.PlatformIDENUM
|
||||
204, // 43: Cast.RefreshWorkListResp.Data:type_name -> Cast.RefreshWorkListResp.Info
|
||||
0, // 44: Cast.OAuthCodeToTokenReq.platformID:type_name -> Cast.PlatformIDENUM
|
||||
206, // 45: Cast.UpdateOAuthReq.Data:type_name -> Cast.UpdateOAuthReq.Info
|
||||
0, // 46: Cast.RefreshTokenReq.platformID:type_name -> Cast.PlatformIDENUM
|
||||
73, // 47: Cast.ListVideoScriptsResp.data:type_name -> Cast.VideoScriptInfo
|
||||
73, // 48: Cast.UpdateVideoScriptBatchReq.data:type_name -> Cast.VideoScriptInfo
|
||||
73, // 49: Cast.UpdateVideoScriptBatchResp.data:type_name -> Cast.VideoScriptInfo
|
||||
2, // 50: Cast.UpdateScriptStatusReq.workAction:type_name -> Cast.WorkActionENUM
|
||||
6, // 51: Cast.UpdatePromptReq.category:type_name -> Cast.CategoryENUM
|
||||
6, // 52: Cast.GetPromptResp.category:type_name -> Cast.CategoryENUM
|
||||
6, // 53: Cast.ListPromptsReq.category:type_name -> Cast.CategoryENUM
|
||||
6, // 54: Cast.PromptInfo.category:type_name -> Cast.CategoryENUM
|
||||
87, // 55: Cast.ListPromptsResp.data:type_name -> Cast.PromptInfo
|
||||
87, // 56: Cast.UpdatePromptBatchReq.data:type_name -> Cast.PromptInfo
|
||||
87, // 57: Cast.UpdatePromptBatchResp.data:type_name -> Cast.PromptInfo
|
||||
91, // 58: Cast.UpdateArtistReq.artistInfo:type_name -> Cast.ArtistInfo
|
||||
91, // 59: Cast.GetArtistResp.artistInfo:type_name -> Cast.ArtistInfo
|
||||
2, // 60: Cast.UpdateWorkAnalysisStatusReq.workAction:type_name -> Cast.WorkActionENUM
|
||||
101, // 61: Cast.GetWorkAnalysisResp.fansSeries:type_name -> Cast.WorkAnalysisFansSeries
|
||||
102, // 62: Cast.GetWorkAnalysisResp.viewsSeries:type_name -> Cast.WorkAnalysisViewsSeries
|
||||
103, // 63: Cast.GetWorkAnalysisResp.likesSeries:type_name -> Cast.WorkAnalysisLikesSeries
|
||||
104, // 64: Cast.GetWorkAnalysisResp.commentsSeries:type_name -> Cast.WorkAnalysisCommentsSeries
|
||||
105, // 65: Cast.GetWorkAnalysisResp.sharesSeries:type_name -> Cast.WorkAnalysisSharesSeries
|
||||
106, // 66: Cast.GetWorkAnalysisResp.topCitiesSeries:type_name -> Cast.WorkAnalysisTopCities
|
||||
107, // 67: Cast.GetWorkAnalysisResp.mostActiveDaySeries:type_name -> Cast.WorkAnalysisMostActiveDay
|
||||
108, // 68: Cast.GetWorkAnalysisResp.bestPostTimeSeries:type_name -> Cast.WorkAnalysisBestPostTime
|
||||
100, // 69: Cast.GetWorkAnalysisDetailResp.WorkAnalysisLogData:type_name -> Cast.WorkAnalysisLogInfo
|
||||
101, // 70: Cast.GetWorkAnalysisDetailResp.fansSeries:type_name -> Cast.WorkAnalysisFansSeries
|
||||
102, // 71: Cast.GetWorkAnalysisDetailResp.viewsSeries:type_name -> Cast.WorkAnalysisViewsSeries
|
||||
103, // 72: Cast.GetWorkAnalysisDetailResp.likesSeries:type_name -> Cast.WorkAnalysisLikesSeries
|
||||
104, // 73: Cast.GetWorkAnalysisDetailResp.commentsSeries:type_name -> Cast.WorkAnalysisCommentsSeries
|
||||
105, // 74: Cast.GetWorkAnalysisDetailResp.sharesSeries:type_name -> Cast.WorkAnalysisSharesSeries
|
||||
106, // 75: Cast.GetWorkAnalysisDetailResp.topCitiesSeries:type_name -> Cast.WorkAnalysisTopCities
|
||||
107, // 76: Cast.GetWorkAnalysisDetailResp.mostActiveDaySeries:type_name -> Cast.WorkAnalysisMostActiveDay
|
||||
108, // 77: Cast.GetWorkAnalysisDetailResp.bestPostTimeSeries:type_name -> Cast.WorkAnalysisBestPostTime
|
||||
109, // 78: Cast.GetWorkAnalysisDetailResp.extra:type_name -> Cast.WorkAnalysisExtra
|
||||
115, // 79: Cast.ListWorkAnalysisResp.data:type_name -> Cast.WorkAnalysisInfo
|
||||
119, // 80: Cast.ArtistDataListResp.data:type_name -> Cast.ArtistDataRespItem
|
||||
122, // 81: Cast.MediaDataListResp.data:type_name -> Cast.MediaDataListItem
|
||||
101, // 82: Cast.ArtistMetricsSeriesResp.fansSeries:type_name -> Cast.WorkAnalysisFansSeries
|
||||
102, // 83: Cast.ArtistMetricsSeriesResp.viewsSeries:type_name -> Cast.WorkAnalysisViewsSeries
|
||||
103, // 84: Cast.ArtistMetricsSeriesResp.likesSeries:type_name -> Cast.WorkAnalysisLikesSeries
|
||||
104, // 85: Cast.ArtistMetricsSeriesResp.commentsSeries:type_name -> Cast.WorkAnalysisCommentsSeries
|
||||
105, // 86: Cast.ArtistMetricsSeriesResp.sharesSeries:type_name -> Cast.WorkAnalysisSharesSeries
|
||||
108, // 87: Cast.ArtistMetricsSeriesResp.bestPostTime:type_name -> Cast.WorkAnalysisBestPostTime
|
||||
107, // 88: Cast.ArtistMetricsSeriesResp.mostActiveDay:type_name -> Cast.WorkAnalysisMostActiveDay
|
||||
129, // 89: Cast.ArtistMetricsDailyWindowResp.fans:type_name -> Cast.SimplePoint
|
||||
129, // 90: Cast.ArtistMetricsDailyWindowResp.views:type_name -> Cast.SimplePoint
|
||||
129, // 91: Cast.ArtistMetricsDailyWindowResp.likes:type_name -> Cast.SimplePoint
|
||||
129, // 92: Cast.ArtistMetricsDailyWindowResp.comments:type_name -> Cast.SimplePoint
|
||||
129, // 93: Cast.ArtistMetricsDailyWindowResp.shares:type_name -> Cast.SimplePoint
|
||||
130, // 94: Cast.ArtistMetricsDailyWindowResp.bestPostTime:type_name -> Cast.BestPostTimePoint
|
||||
131, // 95: Cast.ArtistMetricsDailyWindowResp.mostActiveDay:type_name -> Cast.MostActiveDayPoint
|
||||
134, // 96: Cast.TobeConfirmedListResp.data:type_name -> Cast.TobeConfirmedItem
|
||||
137, // 97: Cast.UpsertMediaMetricsDailyBatchReq.data:type_name -> Cast.MediaMetricsDailyItem
|
||||
140, // 98: Cast.UpsertWorkMetricsDailyBatchReq.data:type_name -> Cast.WorkMetricsDailyItem
|
||||
144, // 99: Cast.GetArtistAyrShareInfoResp.data:type_name -> Cast.ArtistAyrShareInfo
|
||||
144, // 100: Cast.GetArtistAyrShareInfoByPlatformIDsResp.data:type_name -> Cast.ArtistAyrShareInfo
|
||||
149, // 101: Cast.ListWorkPlatformInfoResp.data:type_name -> Cast.WorkPlatformInfo
|
||||
152, // 102: Cast.ListMediaMetricsDailyResp.data:type_name -> Cast.MediaMetricsDailyInfo
|
||||
155, // 103: Cast.ListWorkMetricsDailyResp.data:type_name -> Cast.WorkMetricsDailyInfo
|
||||
160, // 104: Cast.GetTaskListResp.data:type_name -> Cast.TaskListInfo
|
||||
160, // 105: Cast.ListTaskListResp.data:type_name -> Cast.TaskListInfo
|
||||
170, // 106: Cast.ListCastTagsResp.data:type_name -> Cast.CastTagInfo
|
||||
170, // 107: Cast.UpdateCastTagBatchReq.data:type_name -> Cast.CastTagInfo
|
||||
170, // 108: Cast.UpdateCastTagBatchResp.data:type_name -> Cast.CastTagInfo
|
||||
170, // 109: Cast.BatchUpdateCastTagsReq.data:type_name -> Cast.CastTagInfo
|
||||
2, // 110: Cast.UpdateCompetitiveReportStatusReq.workAction:type_name -> Cast.WorkActionENUM
|
||||
182, // 111: Cast.GetCompetitiveReportDetailResp.reportLogData:type_name -> Cast.CompetitiveReportLogInfo
|
||||
183, // 112: Cast.GetCompetitiveReportDetailResp.extra:type_name -> Cast.CompetitiveReportExtra
|
||||
189, // 113: Cast.ListCompetitiveReportResp.data:type_name -> Cast.CompetitiveReportInfo
|
||||
177, // 114: Cast.ImportCompetitiveReportBatchReq.reports:type_name -> Cast.CreateCompetitiveReportReq
|
||||
177, // 115: Cast.ImportCompetitiveReportBatchResp.reports:type_name -> Cast.CreateCompetitiveReportReq
|
||||
195, // 116: Cast.CountCompetitiveReportByWorkUuidsResp.data:type_name -> Cast.WorkUuidCount
|
||||
198, // 117: Cast.WorkListResp.Info.PublishMediaIDs:type_name -> Cast.WorkListResp.Info.PublishMediaIDsEntry
|
||||
9, // 118: Cast.WorkDetailResp.MediaAccDataEntry.value:type_name -> Cast.MediaUserInfo
|
||||
205, // 119: Cast.RefreshWorkListResp.Info.PlatformInfoData:type_name -> Cast.RefreshWorkListResp.Info.PlatformInfo
|
||||
0, // 120: Cast.RefreshWorkListResp.Info.PlatformInfo.platformID:type_name -> Cast.PlatformIDENUM
|
||||
0, // 121: Cast.UpdateOAuthReq.Info.platformID:type_name -> Cast.PlatformIDENUM
|
||||
8, // 122: Cast.Cast.MediaUserList:input_type -> Cast.MediaUserListReq
|
||||
11, // 123: Cast.Cast.UpdateMediaAccount:input_type -> Cast.UpdateMediaAccountReq
|
||||
13, // 124: Cast.Cast.UnbindManager:input_type -> Cast.UnbindManagerReq
|
||||
15, // 125: Cast.Cast.BindManager:input_type -> Cast.BindManagerReq
|
||||
16, // 126: Cast.Cast.UpdateWorkImage:input_type -> Cast.UpdateWorkImageReq
|
||||
19, // 127: Cast.Cast.UpdateWorkVideo:input_type -> Cast.UpdateWorkVideoReq
|
||||
21, // 128: Cast.Cast.MediaInfo:input_type -> Cast.MediaInfoReq
|
||||
23, // 129: Cast.Cast.MediaInfoByPlatform:input_type -> Cast.MediaInfoByPlatformReq
|
||||
25, // 130: Cast.Cast.WorkList:input_type -> Cast.WorkListReq
|
||||
42, // 131: Cast.Cast.WorkListPublished:input_type -> Cast.WorkListPublishedReq
|
||||
27, // 132: Cast.Cast.WorkDetail:input_type -> Cast.WorkDetailReq
|
||||
30, // 133: Cast.Cast.UpdateStatus:input_type -> Cast.UpdateStatusReq
|
||||
31, // 134: Cast.Cast.MediaAccounts:input_type -> Cast.MediaAccountsReq
|
||||
33, // 135: Cast.Cast.MediaWorks:input_type -> Cast.MediaWorksReq
|
||||
35, // 136: Cast.Cast.Publish:input_type -> Cast.PublishReq
|
||||
37, // 137: Cast.Cast.RePublish:input_type -> Cast.RePublishReq
|
||||
39, // 138: Cast.Cast.DelWork:input_type -> Cast.DelWorkReq
|
||||
40, // 139: Cast.Cast.WorkInfo:input_type -> Cast.WorkInfoReq
|
||||
44, // 140: Cast.Cast.ArtistInfo:input_type -> Cast.ArtistInfoReq
|
||||
46, // 141: Cast.Cast.ImportWorkBatch:input_type -> Cast.ImportWorkBatchReq
|
||||
49, // 142: Cast.Cast.UpdateWorkPlatformInfo:input_type -> Cast.UpdateWorkPlatformInfoReq
|
||||
51, // 143: Cast.Cast.UpdateWorkPublishLog:input_type -> Cast.UpdateWorkPublishLogReq
|
||||
52, // 144: Cast.Cast.RefreshWorkList:input_type -> Cast.RefreshWorkListReq
|
||||
54, // 145: Cast.Cast.OAuthAccount:input_type -> Cast.OAuthAccountReq
|
||||
56, // 146: Cast.Cast.OAuthAccountV2:input_type -> Cast.OAuthAccountV2Req
|
||||
60, // 147: Cast.Cast.OAuthCodeToToken:input_type -> Cast.OAuthCodeToTokenReq
|
||||
62, // 148: Cast.Cast.UpdateOAuth:input_type -> Cast.UpdateOAuthReq
|
||||
63, // 149: Cast.Cast.RefreshToken:input_type -> Cast.RefreshTokenReq
|
||||
65, // 150: Cast.Cast.PublishMediaInfo:input_type -> Cast.PublishMediaInfoReq
|
||||
67, // 151: Cast.Cast.Tools:input_type -> Cast.ToolsReq
|
||||
68, // 152: Cast.Cast.UpdateVideoScript:input_type -> Cast.UpdateVideoScriptReq
|
||||
70, // 153: Cast.Cast.GetVideoScript:input_type -> Cast.GetVideoScriptReq
|
||||
72, // 154: Cast.Cast.ListVideoScripts:input_type -> Cast.ListVideoScriptsReq
|
||||
75, // 155: Cast.Cast.DeleteVideoScript:input_type -> Cast.DeleteVideoScriptReq
|
||||
76, // 156: Cast.Cast.UpdateVideoScriptBatch:input_type -> Cast.UpdateVideoScriptBatchReq
|
||||
78, // 157: Cast.Cast.UpdateScriptStatus:input_type -> Cast.UpdateScriptStatusReq
|
||||
80, // 158: Cast.Cast.GetLayout:input_type -> Cast.GetLayoutReq
|
||||
79, // 159: Cast.Cast.SetLayout:input_type -> Cast.SetLayoutReq
|
||||
82, // 160: Cast.Cast.UpdatePrompt:input_type -> Cast.UpdatePromptReq
|
||||
83, // 161: Cast.Cast.DeletePrompt:input_type -> Cast.DeletePromptReq
|
||||
84, // 162: Cast.Cast.GetPrompt:input_type -> Cast.GetPromptReq
|
||||
86, // 163: Cast.Cast.ListPrompts:input_type -> Cast.ListPromptsReq
|
||||
89, // 164: Cast.Cast.UpdatePromptBatch:input_type -> Cast.UpdatePromptBatchReq
|
||||
92, // 165: Cast.Cast.UpdateArtist:input_type -> Cast.UpdateArtistReq
|
||||
94, // 166: Cast.Cast.GetArtist:input_type -> Cast.GetArtistReq
|
||||
96, // 167: Cast.Cast.CreateWorkAnalysis:input_type -> Cast.CreateWorkAnalysisReq
|
||||
98, // 168: Cast.Cast.UpdateWorkAnalysis:input_type -> Cast.UpdateWorkAnalysisReq
|
||||
99, // 169: Cast.Cast.UpdateWorkAnalysisStatus:input_type -> Cast.UpdateWorkAnalysisStatusReq
|
||||
110, // 170: Cast.Cast.GetWorkAnalysis:input_type -> Cast.GetWorkAnalysisDetailReq
|
||||
111, // 171: Cast.Cast.GetLatestWorkAnalysis:input_type -> Cast.GetLatestWorkAnalysisReq
|
||||
114, // 172: Cast.Cast.ListWorkAnalysis:input_type -> Cast.ListWorkAnalysisReq
|
||||
117, // 173: Cast.Cast.DeleteWorkAnalysis:input_type -> Cast.DeleteWorkAnalysisReq
|
||||
136, // 174: Cast.Cast.UpdateWorkAnalysisApprovalID:input_type -> Cast.UpdateWorkAnalysisApprovalIDReq
|
||||
118, // 175: Cast.Cast.ArtistDataList:input_type -> Cast.ArtistDataListReq
|
||||
121, // 176: Cast.Cast.MediaDataList:input_type -> Cast.MediaDataListReq
|
||||
124, // 177: Cast.Cast.DataOverview:input_type -> Cast.DataOverviewReq
|
||||
126, // 178: Cast.Cast.ArtistMetricsSeries:input_type -> Cast.ArtistMetricsSeriesReq
|
||||
128, // 179: Cast.Cast.ArtistMetricsDailyWindow:input_type -> Cast.ArtistMetricsDailyWindowReq
|
||||
133, // 180: Cast.Cast.TobeConfirmedList:input_type -> Cast.TobeConfirmedListReq
|
||||
138, // 181: Cast.Cast.UpsertMediaMetricsDailyBatch:input_type -> Cast.UpsertMediaMetricsDailyBatchReq
|
||||
141, // 182: Cast.Cast.UpsertWorkMetricsDailyBatch:input_type -> Cast.UpsertWorkMetricsDailyBatchReq
|
||||
151, // 183: Cast.Cast.ListMediaMetricsDaily:input_type -> Cast.ListMediaMetricsDailyReq
|
||||
154, // 184: Cast.Cast.ListWorkMetricsDaily:input_type -> Cast.ListWorkMetricsDailyReq
|
||||
165, // 185: Cast.Cast.CalculateMediaMetricsByWorks:input_type -> Cast.CalculateMediaMetricsByWorksReq
|
||||
143, // 186: Cast.Cast.GetArtistAyrShareInfo:input_type -> Cast.GetArtistAyrShareInfoReq
|
||||
146, // 187: Cast.Cast.GetArtistAyrShareInfoByPlatformIDs:input_type -> Cast.GetArtistAyrShareInfoByPlatformIDsReq
|
||||
148, // 188: Cast.Cast.ListWorkPlatformInfo:input_type -> Cast.ListWorkPlatformInfoReq
|
||||
157, // 189: Cast.Cast.UpsertTaskList:input_type -> Cast.UpsertTaskListReq
|
||||
159, // 190: Cast.Cast.GetTaskList:input_type -> Cast.GetTaskListReq
|
||||
162, // 191: Cast.Cast.ListTaskList:input_type -> Cast.ListTaskListReq
|
||||
164, // 192: Cast.Cast.DeleteTaskList:input_type -> Cast.DeleteTaskListReq
|
||||
167, // 193: Cast.Cast.UpdateCastTag:input_type -> Cast.UpdateCastTagReq
|
||||
169, // 194: Cast.Cast.ListCastTags:input_type -> Cast.ListCastTagsReq
|
||||
172, // 195: Cast.Cast.UpdateCastTagBatch:input_type -> Cast.UpdateCastTagBatchReq
|
||||
174, // 196: Cast.Cast.BatchUpdateCastTags:input_type -> Cast.BatchUpdateCastTagsReq
|
||||
175, // 197: Cast.Cast.UpdateCastTagStatus:input_type -> Cast.UpdateCastTagStatusReq
|
||||
207, // 198: Cast.Cast.RecalculateCastTagQuoteCount:input_type -> google.protobuf.Empty
|
||||
177, // 199: Cast.Cast.CreateCompetitiveReport:input_type -> Cast.CreateCompetitiveReportReq
|
||||
192, // 200: Cast.Cast.ImportCompetitiveReportBatch:input_type -> Cast.ImportCompetitiveReportBatchReq
|
||||
180, // 201: Cast.Cast.UpdateCompetitiveReportStatus:input_type -> Cast.UpdateCompetitiveReportStatusReq
|
||||
184, // 202: Cast.Cast.GetCompetitiveReport:input_type -> Cast.GetCompetitiveReportDetailReq
|
||||
185, // 203: Cast.Cast.GetCompetitiveReportForApp:input_type -> Cast.GetCompetitiveReportForAppReq
|
||||
188, // 204: Cast.Cast.ListCompetitiveReport:input_type -> Cast.ListCompetitiveReportReq
|
||||
191, // 205: Cast.Cast.DeleteCompetitiveReport:input_type -> Cast.DeleteCompetitiveReportReq
|
||||
181, // 206: Cast.Cast.UpdateCompetitiveReportApprovalID:input_type -> Cast.UpdateCompetitiveReportApprovalIDReq
|
||||
194, // 207: Cast.Cast.CountCompetitiveReportByWorkUuids:input_type -> Cast.CountCompetitiveReportByWorkUuidsReq
|
||||
10, // 208: Cast.Cast.MediaUserList:output_type -> Cast.MediaUserListResp
|
||||
12, // 209: Cast.Cast.UpdateMediaAccount:output_type -> Cast.UpdateMediaAccountResp
|
||||
14, // 210: Cast.Cast.UnbindManager:output_type -> Cast.UnbindManagerResp
|
||||
207, // 211: Cast.Cast.BindManager:output_type -> google.protobuf.Empty
|
||||
17, // 212: Cast.Cast.UpdateWorkImage:output_type -> Cast.UpdateWorkImageResp
|
||||
20, // 213: Cast.Cast.UpdateWorkVideo:output_type -> Cast.UpdateWorkVideoResp
|
||||
22, // 214: Cast.Cast.MediaInfo:output_type -> Cast.MediaInfoResp
|
||||
24, // 215: Cast.Cast.MediaInfoByPlatform:output_type -> Cast.MediaInfoByPlatformResp
|
||||
26, // 216: Cast.Cast.WorkList:output_type -> Cast.WorkListResp
|
||||
43, // 217: Cast.Cast.WorkListPublished:output_type -> Cast.WorkListPublishedResp
|
||||
29, // 218: Cast.Cast.WorkDetail:output_type -> Cast.WorkDetailResp
|
||||
207, // 219: Cast.Cast.UpdateStatus:output_type -> google.protobuf.Empty
|
||||
32, // 220: Cast.Cast.MediaAccounts:output_type -> Cast.MediaAccountsResp
|
||||
34, // 221: Cast.Cast.MediaWorks:output_type -> Cast.MediaWorksResp
|
||||
36, // 222: Cast.Cast.Publish:output_type -> Cast.PublishResp
|
||||
38, // 223: Cast.Cast.RePublish:output_type -> Cast.RePublishResp
|
||||
207, // 224: Cast.Cast.DelWork:output_type -> google.protobuf.Empty
|
||||
41, // 225: Cast.Cast.WorkInfo:output_type -> Cast.WorkInfoResp
|
||||
45, // 226: Cast.Cast.ArtistInfo:output_type -> Cast.ArtistInfoResp
|
||||
47, // 227: Cast.Cast.ImportWorkBatch:output_type -> Cast.ImportWorkBatchResp
|
||||
50, // 228: Cast.Cast.UpdateWorkPlatformInfo:output_type -> Cast.UpdateWorkPlatformInfoResp
|
||||
207, // 229: Cast.Cast.UpdateWorkPublishLog:output_type -> google.protobuf.Empty
|
||||
53, // 230: Cast.Cast.RefreshWorkList:output_type -> Cast.RefreshWorkListResp
|
||||
55, // 231: Cast.Cast.OAuthAccount:output_type -> Cast.OAuthAccountResp
|
||||
57, // 232: Cast.Cast.OAuthAccountV2:output_type -> Cast.OAuthAccountV2Resp
|
||||
61, // 233: Cast.Cast.OAuthCodeToToken:output_type -> Cast.OAuthCodeToTokenResp
|
||||
207, // 234: Cast.Cast.UpdateOAuth:output_type -> google.protobuf.Empty
|
||||
64, // 235: Cast.Cast.RefreshToken:output_type -> Cast.RefreshTokenResp
|
||||
66, // 236: Cast.Cast.PublishMediaInfo:output_type -> Cast.PublishMediaInfoResp
|
||||
207, // 237: Cast.Cast.Tools:output_type -> google.protobuf.Empty
|
||||
69, // 238: Cast.Cast.UpdateVideoScript:output_type -> Cast.UpdateVideoScriptResp
|
||||
71, // 239: Cast.Cast.GetVideoScript:output_type -> Cast.GetVideoScriptResp
|
||||
74, // 240: Cast.Cast.ListVideoScripts:output_type -> Cast.ListVideoScriptsResp
|
||||
207, // 241: Cast.Cast.DeleteVideoScript:output_type -> google.protobuf.Empty
|
||||
77, // 242: Cast.Cast.UpdateVideoScriptBatch:output_type -> Cast.UpdateVideoScriptBatchResp
|
||||
207, // 243: Cast.Cast.UpdateScriptStatus:output_type -> google.protobuf.Empty
|
||||
81, // 244: Cast.Cast.GetLayout:output_type -> Cast.GetLayoutResp
|
||||
207, // 245: Cast.Cast.SetLayout:output_type -> google.protobuf.Empty
|
||||
207, // 246: Cast.Cast.UpdatePrompt:output_type -> google.protobuf.Empty
|
||||
207, // 247: Cast.Cast.DeletePrompt:output_type -> google.protobuf.Empty
|
||||
85, // 248: Cast.Cast.GetPrompt:output_type -> Cast.GetPromptResp
|
||||
88, // 249: Cast.Cast.ListPrompts:output_type -> Cast.ListPromptsResp
|
||||
90, // 250: Cast.Cast.UpdatePromptBatch:output_type -> Cast.UpdatePromptBatchResp
|
||||
93, // 251: Cast.Cast.UpdateArtist:output_type -> Cast.UpdateArtistResp
|
||||
95, // 252: Cast.Cast.GetArtist:output_type -> Cast.GetArtistResp
|
||||
97, // 253: Cast.Cast.CreateWorkAnalysis:output_type -> Cast.CreateWorkAnalysisResp
|
||||
207, // 254: Cast.Cast.UpdateWorkAnalysis:output_type -> google.protobuf.Empty
|
||||
207, // 255: Cast.Cast.UpdateWorkAnalysisStatus:output_type -> google.protobuf.Empty
|
||||
113, // 256: Cast.Cast.GetWorkAnalysis:output_type -> Cast.GetWorkAnalysisDetailResp
|
||||
112, // 257: Cast.Cast.GetLatestWorkAnalysis:output_type -> Cast.GetWorkAnalysisResp
|
||||
116, // 258: Cast.Cast.ListWorkAnalysis:output_type -> Cast.ListWorkAnalysisResp
|
||||
207, // 259: Cast.Cast.DeleteWorkAnalysis:output_type -> google.protobuf.Empty
|
||||
207, // 260: Cast.Cast.UpdateWorkAnalysisApprovalID:output_type -> google.protobuf.Empty
|
||||
120, // 261: Cast.Cast.ArtistDataList:output_type -> Cast.ArtistDataListResp
|
||||
123, // 262: Cast.Cast.MediaDataList:output_type -> Cast.MediaDataListResp
|
||||
125, // 263: Cast.Cast.DataOverview:output_type -> Cast.DataOverviewResp
|
||||
127, // 264: Cast.Cast.ArtistMetricsSeries:output_type -> Cast.ArtistMetricsSeriesResp
|
||||
132, // 265: Cast.Cast.ArtistMetricsDailyWindow:output_type -> Cast.ArtistMetricsDailyWindowResp
|
||||
135, // 266: Cast.Cast.TobeConfirmedList:output_type -> Cast.TobeConfirmedListResp
|
||||
139, // 267: Cast.Cast.UpsertMediaMetricsDailyBatch:output_type -> Cast.UpsertMediaMetricsDailyBatchResp
|
||||
142, // 268: Cast.Cast.UpsertWorkMetricsDailyBatch:output_type -> Cast.UpsertWorkMetricsDailyBatchResp
|
||||
153, // 269: Cast.Cast.ListMediaMetricsDaily:output_type -> Cast.ListMediaMetricsDailyResp
|
||||
156, // 270: Cast.Cast.ListWorkMetricsDaily:output_type -> Cast.ListWorkMetricsDailyResp
|
||||
166, // 271: Cast.Cast.CalculateMediaMetricsByWorks:output_type -> Cast.CalculateMediaMetricsByWorksResp
|
||||
145, // 272: Cast.Cast.GetArtistAyrShareInfo:output_type -> Cast.GetArtistAyrShareInfoResp
|
||||
147, // 273: Cast.Cast.GetArtistAyrShareInfoByPlatformIDs:output_type -> Cast.GetArtistAyrShareInfoByPlatformIDsResp
|
||||
150, // 274: Cast.Cast.ListWorkPlatformInfo:output_type -> Cast.ListWorkPlatformInfoResp
|
||||
158, // 275: Cast.Cast.UpsertTaskList:output_type -> Cast.UpsertTaskListResp
|
||||
161, // 276: Cast.Cast.GetTaskList:output_type -> Cast.GetTaskListResp
|
||||
163, // 277: Cast.Cast.ListTaskList:output_type -> Cast.ListTaskListResp
|
||||
207, // 278: Cast.Cast.DeleteTaskList:output_type -> google.protobuf.Empty
|
||||
168, // 279: Cast.Cast.UpdateCastTag:output_type -> Cast.UpdateCastTagResp
|
||||
171, // 280: Cast.Cast.ListCastTags:output_type -> Cast.ListCastTagsResp
|
||||
173, // 281: Cast.Cast.UpdateCastTagBatch:output_type -> Cast.UpdateCastTagBatchResp
|
||||
207, // 282: Cast.Cast.BatchUpdateCastTags:output_type -> google.protobuf.Empty
|
||||
207, // 283: Cast.Cast.UpdateCastTagStatus:output_type -> google.protobuf.Empty
|
||||
176, // 284: Cast.Cast.RecalculateCastTagQuoteCount:output_type -> Cast.RecalculateCastTagQuoteCountResp
|
||||
178, // 285: Cast.Cast.CreateCompetitiveReport:output_type -> Cast.CreateCompetitiveReportResp
|
||||
193, // 286: Cast.Cast.ImportCompetitiveReportBatch:output_type -> Cast.ImportCompetitiveReportBatchResp
|
||||
207, // 287: Cast.Cast.UpdateCompetitiveReportStatus:output_type -> google.protobuf.Empty
|
||||
187, // 288: Cast.Cast.GetCompetitiveReport:output_type -> Cast.GetCompetitiveReportDetailResp
|
||||
186, // 289: Cast.Cast.GetCompetitiveReportForApp:output_type -> Cast.GetCompetitiveReportForAppResp
|
||||
190, // 290: Cast.Cast.ListCompetitiveReport:output_type -> Cast.ListCompetitiveReportResp
|
||||
207, // 291: Cast.Cast.DeleteCompetitiveReport:output_type -> google.protobuf.Empty
|
||||
207, // 292: Cast.Cast.UpdateCompetitiveReportApprovalID:output_type -> google.protobuf.Empty
|
||||
196, // 293: Cast.Cast.CountCompetitiveReportByWorkUuids:output_type -> Cast.CountCompetitiveReportByWorkUuidsResp
|
||||
208, // [208:294] is the sub-list for method output_type
|
||||
122, // [122:208] is the sub-list for method input_type
|
||||
122, // [122:122] is the sub-list for extension type_name
|
||||
122, // [122:122] is the sub-list for extension extendee
|
||||
0, // [0:122] is the sub-list for field type_name
|
||||
48, // 37: Cast.WorkInfoResp.platformInfoData:type_name -> Cast.PlatformInfo
|
||||
4, // 38: Cast.WorkInfoResp.publishStatus:type_name -> Cast.PublishStatusENUM
|
||||
203, // 39: Cast.WorkListPublishedResp.data:type_name -> Cast.WorkListPublishedResp.Info
|
||||
16, // 40: Cast.ImportWorkBatchReq.imageWorks:type_name -> Cast.UpdateWorkImageReq
|
||||
16, // 41: Cast.ImportWorkBatchResp.imageWorks:type_name -> Cast.UpdateWorkImageReq
|
||||
4, // 42: Cast.PlatformInfo.publishMediaStatus:type_name -> Cast.PublishStatusENUM
|
||||
48, // 43: Cast.UpdateWorkPlatformInfoReq.PlatformInfoData:type_name -> Cast.PlatformInfo
|
||||
0, // 44: Cast.UpdateWorkPublishLogReq.platformID:type_name -> Cast.PlatformIDENUM
|
||||
204, // 45: Cast.RefreshWorkListResp.Data:type_name -> Cast.RefreshWorkListResp.Info
|
||||
0, // 46: Cast.OAuthCodeToTokenReq.platformID:type_name -> Cast.PlatformIDENUM
|
||||
206, // 47: Cast.UpdateOAuthReq.Data:type_name -> Cast.UpdateOAuthReq.Info
|
||||
0, // 48: Cast.RefreshTokenReq.platformID:type_name -> Cast.PlatformIDENUM
|
||||
73, // 49: Cast.ListVideoScriptsResp.data:type_name -> Cast.VideoScriptInfo
|
||||
73, // 50: Cast.UpdateVideoScriptBatchReq.data:type_name -> Cast.VideoScriptInfo
|
||||
73, // 51: Cast.UpdateVideoScriptBatchResp.data:type_name -> Cast.VideoScriptInfo
|
||||
2, // 52: Cast.UpdateScriptStatusReq.workAction:type_name -> Cast.WorkActionENUM
|
||||
6, // 53: Cast.UpdatePromptReq.category:type_name -> Cast.CategoryENUM
|
||||
6, // 54: Cast.GetPromptResp.category:type_name -> Cast.CategoryENUM
|
||||
6, // 55: Cast.ListPromptsReq.category:type_name -> Cast.CategoryENUM
|
||||
6, // 56: Cast.PromptInfo.category:type_name -> Cast.CategoryENUM
|
||||
87, // 57: Cast.ListPromptsResp.data:type_name -> Cast.PromptInfo
|
||||
87, // 58: Cast.UpdatePromptBatchReq.data:type_name -> Cast.PromptInfo
|
||||
87, // 59: Cast.UpdatePromptBatchResp.data:type_name -> Cast.PromptInfo
|
||||
91, // 60: Cast.UpdateArtistReq.artistInfo:type_name -> Cast.ArtistInfo
|
||||
91, // 61: Cast.GetArtistResp.artistInfo:type_name -> Cast.ArtistInfo
|
||||
2, // 62: Cast.UpdateWorkAnalysisStatusReq.workAction:type_name -> Cast.WorkActionENUM
|
||||
101, // 63: Cast.GetWorkAnalysisResp.fansSeries:type_name -> Cast.WorkAnalysisFansSeries
|
||||
102, // 64: Cast.GetWorkAnalysisResp.viewsSeries:type_name -> Cast.WorkAnalysisViewsSeries
|
||||
103, // 65: Cast.GetWorkAnalysisResp.likesSeries:type_name -> Cast.WorkAnalysisLikesSeries
|
||||
104, // 66: Cast.GetWorkAnalysisResp.commentsSeries:type_name -> Cast.WorkAnalysisCommentsSeries
|
||||
105, // 67: Cast.GetWorkAnalysisResp.sharesSeries:type_name -> Cast.WorkAnalysisSharesSeries
|
||||
106, // 68: Cast.GetWorkAnalysisResp.topCitiesSeries:type_name -> Cast.WorkAnalysisTopCities
|
||||
107, // 69: Cast.GetWorkAnalysisResp.mostActiveDaySeries:type_name -> Cast.WorkAnalysisMostActiveDay
|
||||
108, // 70: Cast.GetWorkAnalysisResp.bestPostTimeSeries:type_name -> Cast.WorkAnalysisBestPostTime
|
||||
100, // 71: Cast.GetWorkAnalysisDetailResp.WorkAnalysisLogData:type_name -> Cast.WorkAnalysisLogInfo
|
||||
101, // 72: Cast.GetWorkAnalysisDetailResp.fansSeries:type_name -> Cast.WorkAnalysisFansSeries
|
||||
102, // 73: Cast.GetWorkAnalysisDetailResp.viewsSeries:type_name -> Cast.WorkAnalysisViewsSeries
|
||||
103, // 74: Cast.GetWorkAnalysisDetailResp.likesSeries:type_name -> Cast.WorkAnalysisLikesSeries
|
||||
104, // 75: Cast.GetWorkAnalysisDetailResp.commentsSeries:type_name -> Cast.WorkAnalysisCommentsSeries
|
||||
105, // 76: Cast.GetWorkAnalysisDetailResp.sharesSeries:type_name -> Cast.WorkAnalysisSharesSeries
|
||||
106, // 77: Cast.GetWorkAnalysisDetailResp.topCitiesSeries:type_name -> Cast.WorkAnalysisTopCities
|
||||
107, // 78: Cast.GetWorkAnalysisDetailResp.mostActiveDaySeries:type_name -> Cast.WorkAnalysisMostActiveDay
|
||||
108, // 79: Cast.GetWorkAnalysisDetailResp.bestPostTimeSeries:type_name -> Cast.WorkAnalysisBestPostTime
|
||||
109, // 80: Cast.GetWorkAnalysisDetailResp.extra:type_name -> Cast.WorkAnalysisExtra
|
||||
115, // 81: Cast.ListWorkAnalysisResp.data:type_name -> Cast.WorkAnalysisInfo
|
||||
119, // 82: Cast.ArtistDataListResp.data:type_name -> Cast.ArtistDataRespItem
|
||||
122, // 83: Cast.MediaDataListResp.data:type_name -> Cast.MediaDataListItem
|
||||
101, // 84: Cast.ArtistMetricsSeriesResp.fansSeries:type_name -> Cast.WorkAnalysisFansSeries
|
||||
102, // 85: Cast.ArtistMetricsSeriesResp.viewsSeries:type_name -> Cast.WorkAnalysisViewsSeries
|
||||
103, // 86: Cast.ArtistMetricsSeriesResp.likesSeries:type_name -> Cast.WorkAnalysisLikesSeries
|
||||
104, // 87: Cast.ArtistMetricsSeriesResp.commentsSeries:type_name -> Cast.WorkAnalysisCommentsSeries
|
||||
105, // 88: Cast.ArtistMetricsSeriesResp.sharesSeries:type_name -> Cast.WorkAnalysisSharesSeries
|
||||
108, // 89: Cast.ArtistMetricsSeriesResp.bestPostTime:type_name -> Cast.WorkAnalysisBestPostTime
|
||||
107, // 90: Cast.ArtistMetricsSeriesResp.mostActiveDay:type_name -> Cast.WorkAnalysisMostActiveDay
|
||||
129, // 91: Cast.ArtistMetricsDailyWindowResp.fans:type_name -> Cast.SimplePoint
|
||||
129, // 92: Cast.ArtistMetricsDailyWindowResp.views:type_name -> Cast.SimplePoint
|
||||
129, // 93: Cast.ArtistMetricsDailyWindowResp.likes:type_name -> Cast.SimplePoint
|
||||
129, // 94: Cast.ArtistMetricsDailyWindowResp.comments:type_name -> Cast.SimplePoint
|
||||
129, // 95: Cast.ArtistMetricsDailyWindowResp.shares:type_name -> Cast.SimplePoint
|
||||
130, // 96: Cast.ArtistMetricsDailyWindowResp.bestPostTime:type_name -> Cast.BestPostTimePoint
|
||||
131, // 97: Cast.ArtistMetricsDailyWindowResp.mostActiveDay:type_name -> Cast.MostActiveDayPoint
|
||||
134, // 98: Cast.TobeConfirmedListResp.data:type_name -> Cast.TobeConfirmedItem
|
||||
137, // 99: Cast.UpsertMediaMetricsDailyBatchReq.data:type_name -> Cast.MediaMetricsDailyItem
|
||||
140, // 100: Cast.UpsertWorkMetricsDailyBatchReq.data:type_name -> Cast.WorkMetricsDailyItem
|
||||
144, // 101: Cast.GetArtistAyrShareInfoResp.data:type_name -> Cast.ArtistAyrShareInfo
|
||||
144, // 102: Cast.GetArtistAyrShareInfoByPlatformIDsResp.data:type_name -> Cast.ArtistAyrShareInfo
|
||||
149, // 103: Cast.ListWorkPlatformInfoResp.data:type_name -> Cast.WorkPlatformInfo
|
||||
152, // 104: Cast.ListMediaMetricsDailyResp.data:type_name -> Cast.MediaMetricsDailyInfo
|
||||
155, // 105: Cast.ListWorkMetricsDailyResp.data:type_name -> Cast.WorkMetricsDailyInfo
|
||||
160, // 106: Cast.GetTaskListResp.data:type_name -> Cast.TaskListInfo
|
||||
160, // 107: Cast.ListTaskListResp.data:type_name -> Cast.TaskListInfo
|
||||
170, // 108: Cast.ListCastTagsResp.data:type_name -> Cast.CastTagInfo
|
||||
170, // 109: Cast.UpdateCastTagBatchReq.data:type_name -> Cast.CastTagInfo
|
||||
170, // 110: Cast.UpdateCastTagBatchResp.data:type_name -> Cast.CastTagInfo
|
||||
170, // 111: Cast.BatchUpdateCastTagsReq.data:type_name -> Cast.CastTagInfo
|
||||
2, // 112: Cast.UpdateCompetitiveReportStatusReq.workAction:type_name -> Cast.WorkActionENUM
|
||||
182, // 113: Cast.GetCompetitiveReportDetailResp.reportLogData:type_name -> Cast.CompetitiveReportLogInfo
|
||||
183, // 114: Cast.GetCompetitiveReportDetailResp.extra:type_name -> Cast.CompetitiveReportExtra
|
||||
189, // 115: Cast.ListCompetitiveReportResp.data:type_name -> Cast.CompetitiveReportInfo
|
||||
177, // 116: Cast.ImportCompetitiveReportBatchReq.reports:type_name -> Cast.CreateCompetitiveReportReq
|
||||
177, // 117: Cast.ImportCompetitiveReportBatchResp.reports:type_name -> Cast.CreateCompetitiveReportReq
|
||||
195, // 118: Cast.CountCompetitiveReportByWorkUuidsResp.data:type_name -> Cast.WorkUuidCount
|
||||
198, // 119: Cast.WorkListResp.Info.PublishMediaIDs:type_name -> Cast.WorkListResp.Info.PublishMediaIDsEntry
|
||||
9, // 120: Cast.WorkDetailResp.MediaAccDataEntry.value:type_name -> Cast.MediaUserInfo
|
||||
205, // 121: Cast.RefreshWorkListResp.Info.PlatformInfoData:type_name -> Cast.RefreshWorkListResp.Info.PlatformInfo
|
||||
0, // 122: Cast.RefreshWorkListResp.Info.PlatformInfo.platformID:type_name -> Cast.PlatformIDENUM
|
||||
0, // 123: Cast.UpdateOAuthReq.Info.platformID:type_name -> Cast.PlatformIDENUM
|
||||
8, // 124: Cast.Cast.MediaUserList:input_type -> Cast.MediaUserListReq
|
||||
11, // 125: Cast.Cast.UpdateMediaAccount:input_type -> Cast.UpdateMediaAccountReq
|
||||
13, // 126: Cast.Cast.UnbindManager:input_type -> Cast.UnbindManagerReq
|
||||
15, // 127: Cast.Cast.BindManager:input_type -> Cast.BindManagerReq
|
||||
16, // 128: Cast.Cast.UpdateWorkImage:input_type -> Cast.UpdateWorkImageReq
|
||||
19, // 129: Cast.Cast.UpdateWorkVideo:input_type -> Cast.UpdateWorkVideoReq
|
||||
21, // 130: Cast.Cast.MediaInfo:input_type -> Cast.MediaInfoReq
|
||||
23, // 131: Cast.Cast.MediaInfoByPlatform:input_type -> Cast.MediaInfoByPlatformReq
|
||||
25, // 132: Cast.Cast.WorkList:input_type -> Cast.WorkListReq
|
||||
42, // 133: Cast.Cast.WorkListPublished:input_type -> Cast.WorkListPublishedReq
|
||||
27, // 134: Cast.Cast.WorkDetail:input_type -> Cast.WorkDetailReq
|
||||
30, // 135: Cast.Cast.UpdateStatus:input_type -> Cast.UpdateStatusReq
|
||||
31, // 136: Cast.Cast.MediaAccounts:input_type -> Cast.MediaAccountsReq
|
||||
33, // 137: Cast.Cast.MediaWorks:input_type -> Cast.MediaWorksReq
|
||||
35, // 138: Cast.Cast.Publish:input_type -> Cast.PublishReq
|
||||
37, // 139: Cast.Cast.RePublish:input_type -> Cast.RePublishReq
|
||||
39, // 140: Cast.Cast.DelWork:input_type -> Cast.DelWorkReq
|
||||
40, // 141: Cast.Cast.WorkInfo:input_type -> Cast.WorkInfoReq
|
||||
44, // 142: Cast.Cast.ArtistInfo:input_type -> Cast.ArtistInfoReq
|
||||
46, // 143: Cast.Cast.ImportWorkBatch:input_type -> Cast.ImportWorkBatchReq
|
||||
49, // 144: Cast.Cast.UpdateWorkPlatformInfo:input_type -> Cast.UpdateWorkPlatformInfoReq
|
||||
51, // 145: Cast.Cast.UpdateWorkPublishLog:input_type -> Cast.UpdateWorkPublishLogReq
|
||||
52, // 146: Cast.Cast.RefreshWorkList:input_type -> Cast.RefreshWorkListReq
|
||||
54, // 147: Cast.Cast.OAuthAccount:input_type -> Cast.OAuthAccountReq
|
||||
56, // 148: Cast.Cast.OAuthAccountV2:input_type -> Cast.OAuthAccountV2Req
|
||||
60, // 149: Cast.Cast.OAuthCodeToToken:input_type -> Cast.OAuthCodeToTokenReq
|
||||
62, // 150: Cast.Cast.UpdateOAuth:input_type -> Cast.UpdateOAuthReq
|
||||
63, // 151: Cast.Cast.RefreshToken:input_type -> Cast.RefreshTokenReq
|
||||
65, // 152: Cast.Cast.PublishMediaInfo:input_type -> Cast.PublishMediaInfoReq
|
||||
67, // 153: Cast.Cast.Tools:input_type -> Cast.ToolsReq
|
||||
68, // 154: Cast.Cast.UpdateVideoScript:input_type -> Cast.UpdateVideoScriptReq
|
||||
70, // 155: Cast.Cast.GetVideoScript:input_type -> Cast.GetVideoScriptReq
|
||||
72, // 156: Cast.Cast.ListVideoScripts:input_type -> Cast.ListVideoScriptsReq
|
||||
75, // 157: Cast.Cast.DeleteVideoScript:input_type -> Cast.DeleteVideoScriptReq
|
||||
76, // 158: Cast.Cast.UpdateVideoScriptBatch:input_type -> Cast.UpdateVideoScriptBatchReq
|
||||
78, // 159: Cast.Cast.UpdateScriptStatus:input_type -> Cast.UpdateScriptStatusReq
|
||||
80, // 160: Cast.Cast.GetLayout:input_type -> Cast.GetLayoutReq
|
||||
79, // 161: Cast.Cast.SetLayout:input_type -> Cast.SetLayoutReq
|
||||
82, // 162: Cast.Cast.UpdatePrompt:input_type -> Cast.UpdatePromptReq
|
||||
83, // 163: Cast.Cast.DeletePrompt:input_type -> Cast.DeletePromptReq
|
||||
84, // 164: Cast.Cast.GetPrompt:input_type -> Cast.GetPromptReq
|
||||
86, // 165: Cast.Cast.ListPrompts:input_type -> Cast.ListPromptsReq
|
||||
89, // 166: Cast.Cast.UpdatePromptBatch:input_type -> Cast.UpdatePromptBatchReq
|
||||
92, // 167: Cast.Cast.UpdateArtist:input_type -> Cast.UpdateArtistReq
|
||||
94, // 168: Cast.Cast.GetArtist:input_type -> Cast.GetArtistReq
|
||||
96, // 169: Cast.Cast.CreateWorkAnalysis:input_type -> Cast.CreateWorkAnalysisReq
|
||||
98, // 170: Cast.Cast.UpdateWorkAnalysis:input_type -> Cast.UpdateWorkAnalysisReq
|
||||
99, // 171: Cast.Cast.UpdateWorkAnalysisStatus:input_type -> Cast.UpdateWorkAnalysisStatusReq
|
||||
110, // 172: Cast.Cast.GetWorkAnalysis:input_type -> Cast.GetWorkAnalysisDetailReq
|
||||
111, // 173: Cast.Cast.GetLatestWorkAnalysis:input_type -> Cast.GetLatestWorkAnalysisReq
|
||||
114, // 174: Cast.Cast.ListWorkAnalysis:input_type -> Cast.ListWorkAnalysisReq
|
||||
117, // 175: Cast.Cast.DeleteWorkAnalysis:input_type -> Cast.DeleteWorkAnalysisReq
|
||||
136, // 176: Cast.Cast.UpdateWorkAnalysisApprovalID:input_type -> Cast.UpdateWorkAnalysisApprovalIDReq
|
||||
118, // 177: Cast.Cast.ArtistDataList:input_type -> Cast.ArtistDataListReq
|
||||
121, // 178: Cast.Cast.MediaDataList:input_type -> Cast.MediaDataListReq
|
||||
124, // 179: Cast.Cast.DataOverview:input_type -> Cast.DataOverviewReq
|
||||
126, // 180: Cast.Cast.ArtistMetricsSeries:input_type -> Cast.ArtistMetricsSeriesReq
|
||||
128, // 181: Cast.Cast.ArtistMetricsDailyWindow:input_type -> Cast.ArtistMetricsDailyWindowReq
|
||||
133, // 182: Cast.Cast.TobeConfirmedList:input_type -> Cast.TobeConfirmedListReq
|
||||
138, // 183: Cast.Cast.UpsertMediaMetricsDailyBatch:input_type -> Cast.UpsertMediaMetricsDailyBatchReq
|
||||
141, // 184: Cast.Cast.UpsertWorkMetricsDailyBatch:input_type -> Cast.UpsertWorkMetricsDailyBatchReq
|
||||
151, // 185: Cast.Cast.ListMediaMetricsDaily:input_type -> Cast.ListMediaMetricsDailyReq
|
||||
154, // 186: Cast.Cast.ListWorkMetricsDaily:input_type -> Cast.ListWorkMetricsDailyReq
|
||||
165, // 187: Cast.Cast.CalculateMediaMetricsByWorks:input_type -> Cast.CalculateMediaMetricsByWorksReq
|
||||
143, // 188: Cast.Cast.GetArtistAyrShareInfo:input_type -> Cast.GetArtistAyrShareInfoReq
|
||||
146, // 189: Cast.Cast.GetArtistAyrShareInfoByPlatformIDs:input_type -> Cast.GetArtistAyrShareInfoByPlatformIDsReq
|
||||
148, // 190: Cast.Cast.ListWorkPlatformInfo:input_type -> Cast.ListWorkPlatformInfoReq
|
||||
157, // 191: Cast.Cast.UpsertTaskList:input_type -> Cast.UpsertTaskListReq
|
||||
159, // 192: Cast.Cast.GetTaskList:input_type -> Cast.GetTaskListReq
|
||||
162, // 193: Cast.Cast.ListTaskList:input_type -> Cast.ListTaskListReq
|
||||
164, // 194: Cast.Cast.DeleteTaskList:input_type -> Cast.DeleteTaskListReq
|
||||
167, // 195: Cast.Cast.UpdateCastTag:input_type -> Cast.UpdateCastTagReq
|
||||
169, // 196: Cast.Cast.ListCastTags:input_type -> Cast.ListCastTagsReq
|
||||
172, // 197: Cast.Cast.UpdateCastTagBatch:input_type -> Cast.UpdateCastTagBatchReq
|
||||
174, // 198: Cast.Cast.BatchUpdateCastTags:input_type -> Cast.BatchUpdateCastTagsReq
|
||||
175, // 199: Cast.Cast.UpdateCastTagStatus:input_type -> Cast.UpdateCastTagStatusReq
|
||||
207, // 200: Cast.Cast.RecalculateCastTagQuoteCount:input_type -> google.protobuf.Empty
|
||||
177, // 201: Cast.Cast.CreateCompetitiveReport:input_type -> Cast.CreateCompetitiveReportReq
|
||||
192, // 202: Cast.Cast.ImportCompetitiveReportBatch:input_type -> Cast.ImportCompetitiveReportBatchReq
|
||||
180, // 203: Cast.Cast.UpdateCompetitiveReportStatus:input_type -> Cast.UpdateCompetitiveReportStatusReq
|
||||
184, // 204: Cast.Cast.GetCompetitiveReport:input_type -> Cast.GetCompetitiveReportDetailReq
|
||||
185, // 205: Cast.Cast.GetCompetitiveReportForApp:input_type -> Cast.GetCompetitiveReportForAppReq
|
||||
188, // 206: Cast.Cast.ListCompetitiveReport:input_type -> Cast.ListCompetitiveReportReq
|
||||
191, // 207: Cast.Cast.DeleteCompetitiveReport:input_type -> Cast.DeleteCompetitiveReportReq
|
||||
181, // 208: Cast.Cast.UpdateCompetitiveReportApprovalID:input_type -> Cast.UpdateCompetitiveReportApprovalIDReq
|
||||
194, // 209: Cast.Cast.CountCompetitiveReportByWorkUuids:input_type -> Cast.CountCompetitiveReportByWorkUuidsReq
|
||||
10, // 210: Cast.Cast.MediaUserList:output_type -> Cast.MediaUserListResp
|
||||
12, // 211: Cast.Cast.UpdateMediaAccount:output_type -> Cast.UpdateMediaAccountResp
|
||||
14, // 212: Cast.Cast.UnbindManager:output_type -> Cast.UnbindManagerResp
|
||||
207, // 213: Cast.Cast.BindManager:output_type -> google.protobuf.Empty
|
||||
17, // 214: Cast.Cast.UpdateWorkImage:output_type -> Cast.UpdateWorkImageResp
|
||||
20, // 215: Cast.Cast.UpdateWorkVideo:output_type -> Cast.UpdateWorkVideoResp
|
||||
22, // 216: Cast.Cast.MediaInfo:output_type -> Cast.MediaInfoResp
|
||||
24, // 217: Cast.Cast.MediaInfoByPlatform:output_type -> Cast.MediaInfoByPlatformResp
|
||||
26, // 218: Cast.Cast.WorkList:output_type -> Cast.WorkListResp
|
||||
43, // 219: Cast.Cast.WorkListPublished:output_type -> Cast.WorkListPublishedResp
|
||||
29, // 220: Cast.Cast.WorkDetail:output_type -> Cast.WorkDetailResp
|
||||
207, // 221: Cast.Cast.UpdateStatus:output_type -> google.protobuf.Empty
|
||||
32, // 222: Cast.Cast.MediaAccounts:output_type -> Cast.MediaAccountsResp
|
||||
34, // 223: Cast.Cast.MediaWorks:output_type -> Cast.MediaWorksResp
|
||||
36, // 224: Cast.Cast.Publish:output_type -> Cast.PublishResp
|
||||
38, // 225: Cast.Cast.RePublish:output_type -> Cast.RePublishResp
|
||||
207, // 226: Cast.Cast.DelWork:output_type -> google.protobuf.Empty
|
||||
41, // 227: Cast.Cast.WorkInfo:output_type -> Cast.WorkInfoResp
|
||||
45, // 228: Cast.Cast.ArtistInfo:output_type -> Cast.ArtistInfoResp
|
||||
47, // 229: Cast.Cast.ImportWorkBatch:output_type -> Cast.ImportWorkBatchResp
|
||||
50, // 230: Cast.Cast.UpdateWorkPlatformInfo:output_type -> Cast.UpdateWorkPlatformInfoResp
|
||||
207, // 231: Cast.Cast.UpdateWorkPublishLog:output_type -> google.protobuf.Empty
|
||||
53, // 232: Cast.Cast.RefreshWorkList:output_type -> Cast.RefreshWorkListResp
|
||||
55, // 233: Cast.Cast.OAuthAccount:output_type -> Cast.OAuthAccountResp
|
||||
57, // 234: Cast.Cast.OAuthAccountV2:output_type -> Cast.OAuthAccountV2Resp
|
||||
61, // 235: Cast.Cast.OAuthCodeToToken:output_type -> Cast.OAuthCodeToTokenResp
|
||||
207, // 236: Cast.Cast.UpdateOAuth:output_type -> google.protobuf.Empty
|
||||
64, // 237: Cast.Cast.RefreshToken:output_type -> Cast.RefreshTokenResp
|
||||
66, // 238: Cast.Cast.PublishMediaInfo:output_type -> Cast.PublishMediaInfoResp
|
||||
207, // 239: Cast.Cast.Tools:output_type -> google.protobuf.Empty
|
||||
69, // 240: Cast.Cast.UpdateVideoScript:output_type -> Cast.UpdateVideoScriptResp
|
||||
71, // 241: Cast.Cast.GetVideoScript:output_type -> Cast.GetVideoScriptResp
|
||||
74, // 242: Cast.Cast.ListVideoScripts:output_type -> Cast.ListVideoScriptsResp
|
||||
207, // 243: Cast.Cast.DeleteVideoScript:output_type -> google.protobuf.Empty
|
||||
77, // 244: Cast.Cast.UpdateVideoScriptBatch:output_type -> Cast.UpdateVideoScriptBatchResp
|
||||
207, // 245: Cast.Cast.UpdateScriptStatus:output_type -> google.protobuf.Empty
|
||||
81, // 246: Cast.Cast.GetLayout:output_type -> Cast.GetLayoutResp
|
||||
207, // 247: Cast.Cast.SetLayout:output_type -> google.protobuf.Empty
|
||||
207, // 248: Cast.Cast.UpdatePrompt:output_type -> google.protobuf.Empty
|
||||
207, // 249: Cast.Cast.DeletePrompt:output_type -> google.protobuf.Empty
|
||||
85, // 250: Cast.Cast.GetPrompt:output_type -> Cast.GetPromptResp
|
||||
88, // 251: Cast.Cast.ListPrompts:output_type -> Cast.ListPromptsResp
|
||||
90, // 252: Cast.Cast.UpdatePromptBatch:output_type -> Cast.UpdatePromptBatchResp
|
||||
93, // 253: Cast.Cast.UpdateArtist:output_type -> Cast.UpdateArtistResp
|
||||
95, // 254: Cast.Cast.GetArtist:output_type -> Cast.GetArtistResp
|
||||
97, // 255: Cast.Cast.CreateWorkAnalysis:output_type -> Cast.CreateWorkAnalysisResp
|
||||
207, // 256: Cast.Cast.UpdateWorkAnalysis:output_type -> google.protobuf.Empty
|
||||
207, // 257: Cast.Cast.UpdateWorkAnalysisStatus:output_type -> google.protobuf.Empty
|
||||
113, // 258: Cast.Cast.GetWorkAnalysis:output_type -> Cast.GetWorkAnalysisDetailResp
|
||||
112, // 259: Cast.Cast.GetLatestWorkAnalysis:output_type -> Cast.GetWorkAnalysisResp
|
||||
116, // 260: Cast.Cast.ListWorkAnalysis:output_type -> Cast.ListWorkAnalysisResp
|
||||
207, // 261: Cast.Cast.DeleteWorkAnalysis:output_type -> google.protobuf.Empty
|
||||
207, // 262: Cast.Cast.UpdateWorkAnalysisApprovalID:output_type -> google.protobuf.Empty
|
||||
120, // 263: Cast.Cast.ArtistDataList:output_type -> Cast.ArtistDataListResp
|
||||
123, // 264: Cast.Cast.MediaDataList:output_type -> Cast.MediaDataListResp
|
||||
125, // 265: Cast.Cast.DataOverview:output_type -> Cast.DataOverviewResp
|
||||
127, // 266: Cast.Cast.ArtistMetricsSeries:output_type -> Cast.ArtistMetricsSeriesResp
|
||||
132, // 267: Cast.Cast.ArtistMetricsDailyWindow:output_type -> Cast.ArtistMetricsDailyWindowResp
|
||||
135, // 268: Cast.Cast.TobeConfirmedList:output_type -> Cast.TobeConfirmedListResp
|
||||
139, // 269: Cast.Cast.UpsertMediaMetricsDailyBatch:output_type -> Cast.UpsertMediaMetricsDailyBatchResp
|
||||
142, // 270: Cast.Cast.UpsertWorkMetricsDailyBatch:output_type -> Cast.UpsertWorkMetricsDailyBatchResp
|
||||
153, // 271: Cast.Cast.ListMediaMetricsDaily:output_type -> Cast.ListMediaMetricsDailyResp
|
||||
156, // 272: Cast.Cast.ListWorkMetricsDaily:output_type -> Cast.ListWorkMetricsDailyResp
|
||||
166, // 273: Cast.Cast.CalculateMediaMetricsByWorks:output_type -> Cast.CalculateMediaMetricsByWorksResp
|
||||
145, // 274: Cast.Cast.GetArtistAyrShareInfo:output_type -> Cast.GetArtistAyrShareInfoResp
|
||||
147, // 275: Cast.Cast.GetArtistAyrShareInfoByPlatformIDs:output_type -> Cast.GetArtistAyrShareInfoByPlatformIDsResp
|
||||
150, // 276: Cast.Cast.ListWorkPlatformInfo:output_type -> Cast.ListWorkPlatformInfoResp
|
||||
158, // 277: Cast.Cast.UpsertTaskList:output_type -> Cast.UpsertTaskListResp
|
||||
161, // 278: Cast.Cast.GetTaskList:output_type -> Cast.GetTaskListResp
|
||||
163, // 279: Cast.Cast.ListTaskList:output_type -> Cast.ListTaskListResp
|
||||
207, // 280: Cast.Cast.DeleteTaskList:output_type -> google.protobuf.Empty
|
||||
168, // 281: Cast.Cast.UpdateCastTag:output_type -> Cast.UpdateCastTagResp
|
||||
171, // 282: Cast.Cast.ListCastTags:output_type -> Cast.ListCastTagsResp
|
||||
173, // 283: Cast.Cast.UpdateCastTagBatch:output_type -> Cast.UpdateCastTagBatchResp
|
||||
207, // 284: Cast.Cast.BatchUpdateCastTags:output_type -> google.protobuf.Empty
|
||||
207, // 285: Cast.Cast.UpdateCastTagStatus:output_type -> google.protobuf.Empty
|
||||
176, // 286: Cast.Cast.RecalculateCastTagQuoteCount:output_type -> Cast.RecalculateCastTagQuoteCountResp
|
||||
178, // 287: Cast.Cast.CreateCompetitiveReport:output_type -> Cast.CreateCompetitiveReportResp
|
||||
193, // 288: Cast.Cast.ImportCompetitiveReportBatch:output_type -> Cast.ImportCompetitiveReportBatchResp
|
||||
207, // 289: Cast.Cast.UpdateCompetitiveReportStatus:output_type -> google.protobuf.Empty
|
||||
187, // 290: Cast.Cast.GetCompetitiveReport:output_type -> Cast.GetCompetitiveReportDetailResp
|
||||
186, // 291: Cast.Cast.GetCompetitiveReportForApp:output_type -> Cast.GetCompetitiveReportForAppResp
|
||||
190, // 292: Cast.Cast.ListCompetitiveReport:output_type -> Cast.ListCompetitiveReportResp
|
||||
207, // 293: Cast.Cast.DeleteCompetitiveReport:output_type -> google.protobuf.Empty
|
||||
207, // 294: Cast.Cast.UpdateCompetitiveReportApprovalID:output_type -> google.protobuf.Empty
|
||||
196, // 295: Cast.Cast.CountCompetitiveReportByWorkUuids:output_type -> Cast.CountCompetitiveReportByWorkUuidsResp
|
||||
210, // [210:296] is the sub-list for method output_type
|
||||
124, // [124:210] is the sub-list for method input_type
|
||||
124, // [124:124] is the sub-list for extension type_name
|
||||
124, // [124:124] is the sub-list for extension extendee
|
||||
0, // [0:124] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_pb_fiee_cast_proto_init() }
|
||||
|
||||
@ -4586,6 +4586,44 @@ func (m *WorkInfoResp) validate(all bool) error {
|
||||
|
||||
// no validation rules for WorkCategory
|
||||
|
||||
for idx, item := range m.GetPlatformInfoData() {
|
||||
_, _ = idx, item
|
||||
|
||||
if all {
|
||||
switch v := interface{}(item).(type) {
|
||||
case interface{ ValidateAll() error }:
|
||||
if err := v.ValidateAll(); err != nil {
|
||||
errors = append(errors, WorkInfoRespValidationError{
|
||||
field: fmt.Sprintf("PlatformInfoData[%v]", idx),
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
case interface{ Validate() error }:
|
||||
if err := v.Validate(); err != nil {
|
||||
errors = append(errors, WorkInfoRespValidationError{
|
||||
field: fmt.Sprintf("PlatformInfoData[%v]", idx),
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if v, ok := interface{}(item).(interface{ Validate() error }); ok {
|
||||
if err := v.Validate(); err != nil {
|
||||
return WorkInfoRespValidationError{
|
||||
field: fmt.Sprintf("PlatformInfoData[%v]", idx),
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// no validation rules for Title
|
||||
|
||||
// no validation rules for PublishStatus
|
||||
|
||||
if len(errors) > 0 {
|
||||
return WorkInfoRespMultiError(errors)
|
||||
}
|
||||
@ -5435,7 +5473,7 @@ func (m *PlatformInfo) validate(all bool) error {
|
||||
|
||||
// no validation rules for PublishMediaId
|
||||
|
||||
// no validation rules for PublishStatus
|
||||
// no validation rules for PublishMediaStatus
|
||||
|
||||
// no validation rules for Remark
|
||||
|
||||
@ -19391,6 +19429,8 @@ func (m *UpsertTaskListReq) validate(all bool) error {
|
||||
|
||||
// no validation rules for OperatorName
|
||||
|
||||
// no validation rules for ExtraData
|
||||
|
||||
if len(errors) > 0 {
|
||||
return UpsertTaskListReqMultiError(errors)
|
||||
}
|
||||
@ -19717,6 +19757,8 @@ func (m *TaskListInfo) validate(all bool) error {
|
||||
|
||||
// no validation rules for UpdatedAt
|
||||
|
||||
// no validation rules for ExtraData
|
||||
|
||||
if len(errors) > 0 {
|
||||
return TaskListInfoMultiError(errors)
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ func InitTasks() error {
|
||||
cm := GetCronManager()
|
||||
err := cm.AddTask("refreshWorkApprovalStatus", "0 */1 * * * *", RefreshWorkApprovalStatusTask)
|
||||
err = cm.AddTask("artistAutoConfirm", "0 */1 * * * *", ArtistAutoConfirmTask)
|
||||
err = cm.AddTask("refreshPublishStatus", "0 */1 * * * *", RefreshPublishStatusTask)
|
||||
err = cm.AddTask("refreshPublishStatus", "0 */1 * * * *", PublishTask)
|
||||
err = cm.AddTask("scheduledPublish", "0 */1 * * * *", ScheduledPublishTask)
|
||||
|
||||
err = cm.AddTask("artistAutoConfirmAnalysis", "0 */1 * * * *", ArtistAutoConfirmAnalysisTask)
|
||||
@ -272,7 +272,11 @@ func RefreshPublishStatusTask() {
|
||||
//zap.L().Info("刷新发布状态成功")
|
||||
}
|
||||
|
||||
// ScheduledPublishTask 定时发布任务,从Redis Sorted Set中获取所有workUuid并根据score判断处理
|
||||
// PublishTask 定时发布任务,从Redis Sorted Set中获取所有workUuid并根据score判断处理
|
||||
func PublishTask() {
|
||||
go RefreshPublishStatusTask() // 刷新发布状态
|
||||
go TaskStatus() // 异步任务状态
|
||||
}
|
||||
func ScheduledPublishTask() {
|
||||
// 加上锁
|
||||
lockKey := "scheduled_publish:lock"
|
||||
@ -303,7 +307,7 @@ func ScheduledPublishTask() {
|
||||
|
||||
publishCount := 0
|
||||
expiredCount := 0
|
||||
const batchSize = 10 // 每批发布10个
|
||||
const batchSize = 8 // 每批发布8个,与PublishWork的workerCount保持一致
|
||||
|
||||
zap.L().Info("发现定时发布任务", zap.Int("total_count", len(workList)))
|
||||
|
||||
@ -382,6 +386,61 @@ func ScheduledPublishTask() {
|
||||
zap.Int("total_count", len(workList)))
|
||||
}
|
||||
|
||||
func TaskStatus() {
|
||||
var actions []string = []string{"publishBatch1", "publishBatch2"}
|
||||
for _, action := range actions {
|
||||
resp, err := service.CastProvider.ListTaskList(context.Background(), &cast.ListTaskListReq{
|
||||
Action: action,
|
||||
Status: 1,
|
||||
Page: 1,
|
||||
PageSize: 100,
|
||||
})
|
||||
if err != nil {
|
||||
zap.L().Error("获取任务列表失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
for _, v := range resp.Data {
|
||||
var extraData modelCast.PublishTaskDto
|
||||
if v.ExtraData == "" {
|
||||
continue
|
||||
}
|
||||
_ = json.Unmarshal([]byte(v.ExtraData), &extraData)
|
||||
var allDone = true
|
||||
for _, workUuid := range extraData.WorkUuids {
|
||||
infoResp, _err := service.CastProvider.WorkInfo(context.Background(), &cast.WorkInfoReq{WorkUuid: workUuid})
|
||||
if _err != nil {
|
||||
zap.L().Error("获取作品信息失败", zap.Error(_err))
|
||||
allDone = false
|
||||
break
|
||||
}
|
||||
if infoResp.PublishStatus != cast.PublishStatusENUM_PublishMediaStatus_DONE {
|
||||
allDone = false
|
||||
break
|
||||
}
|
||||
}
|
||||
var excelUrl string
|
||||
if allDone {
|
||||
excelUrl, err = serverCast.PublishTaskExcel(extraData.WorkUuids, true, v.Action)
|
||||
if err != nil {
|
||||
zap.L().Error("生成发布任务Excel失败", zap.Error(err))
|
||||
continue
|
||||
}
|
||||
_, err = service.CastProvider.UpsertTaskList(context.Background(), &cast.UpsertTaskListReq{
|
||||
Uuid: v.Uuid,
|
||||
Action: v.Action,
|
||||
Url: excelUrl,
|
||||
Status: 3,
|
||||
})
|
||||
if err != nil {
|
||||
zap.L().Error("更新任务状态失败", zap.Error(err))
|
||||
continue
|
||||
}
|
||||
zap.L().Info("任务已完成,更新状态为完成", zap.String("task_uuid", v.Uuid), zap.String("excel_url", excelUrl))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WorkPublishQueueConsumer 监听work:publish:queue队列的消费者
|
||||
func WorkPublishQueueConsumer() {
|
||||
zap.L().Info("开始监听work:publish:queue队列(批量处理模式)")
|
||||
@ -506,5 +565,5 @@ func AyrshareMetricsCollectorTask() {
|
||||
}
|
||||
|
||||
func RefreshArtistOrderTask() {
|
||||
service.CastProvider.Tools(context.Background(), &cast.ToolsReq{Action: "refreshArtistOrder"})
|
||||
_, _ = service.CastProvider.Tools(context.Background(), &cast.ToolsReq{Action: "artistOrderInfo"})
|
||||
}
|
||||
|
||||
13
pkg/model/cast/task.go
Normal file
13
pkg/model/cast/task.go
Normal file
@ -0,0 +1,13 @@
|
||||
package cast
|
||||
|
||||
type PublishTaskDto struct {
|
||||
WorkUuids []string
|
||||
MediaAccountUuids []string
|
||||
PlatformIds []string
|
||||
}
|
||||
|
||||
var TaskActionName = map[string]string{
|
||||
"importWorkBatch": "批量导入图文",
|
||||
"publishBatch1": "批量发布",
|
||||
"publishBatch2": "多账号同步",
|
||||
}
|
||||
@ -63,6 +63,7 @@ func MediaRouter(r *gin.RouterGroup) {
|
||||
{
|
||||
task.POST("list", serviceCast.TaskList)
|
||||
task.POST("delete", serviceCast.DeleteTasK)
|
||||
task.POST("download", serviceCast.DownloadTaskFile)
|
||||
}
|
||||
|
||||
layout := auth.Group("layout")
|
||||
|
||||
@ -169,7 +169,7 @@ func UpdateMediaAccount(ctx *gin.Context) {
|
||||
}
|
||||
if userResp != nil && len(userResp.Data) > 0 {
|
||||
for _, v := range userResp.Data {
|
||||
if v.PlatformID == uint32(req.PlatformID) {
|
||||
if v.PlatformID == uint32(req.PlatformID) && v.Expired == 1 {
|
||||
service.Error(ctx, errors.New("账号已存在"))
|
||||
return
|
||||
}
|
||||
@ -258,6 +258,10 @@ func OAuthAccount(ctx *gin.Context) {
|
||||
service.Error(ctx, errors.New("未找到该账号"))
|
||||
return
|
||||
}
|
||||
if mediaResp.Data[0].Expired != 1 {
|
||||
service.Error(ctx, errors.New("账号已过期"))
|
||||
return
|
||||
}
|
||||
if err = SyncAsAuth(mediaResp.Data[0].ArtistUuid); err != nil {
|
||||
service.Error(ctx, err)
|
||||
return
|
||||
|
||||
@ -2,12 +2,23 @@ package cast
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"fonchain-fiee/cmd/config"
|
||||
"fonchain-fiee/pkg/service/upload"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"fonchain-fiee/api/cast"
|
||||
modelCast "fonchain-fiee/pkg/model/cast"
|
||||
"fonchain-fiee/pkg/model/login"
|
||||
"fonchain-fiee/pkg/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/xuri/excelize/v2"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func TaskList(ctx *gin.Context) {
|
||||
@ -42,5 +53,148 @@ func DeleteTasK(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
service.Success(ctx, resp)
|
||||
}
|
||||
|
||||
func DownloadTaskFile(ctx *gin.Context) {
|
||||
var req *cast.GetTaskListReq
|
||||
var err error
|
||||
if err = ctx.ShouldBind(&req); err != nil {
|
||||
service.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
resp, err := service.CastProvider.GetTaskList(context.Background(), req)
|
||||
if err != nil {
|
||||
service.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
if resp == nil || resp.Data == nil {
|
||||
service.Error(ctx, errors.New("没有此任务"))
|
||||
return
|
||||
}
|
||||
|
||||
var taskInfo modelCast.PublishTaskDto
|
||||
if resp.Data.ExtraData != "" {
|
||||
_ = json.Unmarshal([]byte(resp.Data.ExtraData), &taskInfo)
|
||||
}
|
||||
exportUrl, err := PublishTaskExcel(taskInfo.WorkUuids, false, resp.Data.Action)
|
||||
if err != nil {
|
||||
service.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
service.Success(ctx, gin.H{
|
||||
"url": exportUrl,
|
||||
})
|
||||
}
|
||||
|
||||
func PublishTaskExcel(workUuids []string, uploadOss bool, action string) (string, error) {
|
||||
// 创建Excel文件
|
||||
f := excelize.NewFile()
|
||||
sheetName := "Sheet1"
|
||||
f.SetSheetName("Sheet1", sheetName)
|
||||
// 设置表头
|
||||
headers := []interface{}{
|
||||
"艺人编号", "艺人姓名", "内容类型", "内容标题",
|
||||
"执行结果", "TIKTOK", "YOUTUBE", "INS", "DM", "BULESKY",
|
||||
}
|
||||
sw, err := f.NewStreamWriter(sheetName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err = sw.SetRow("A1", headers); err != nil {
|
||||
return "", err
|
||||
}
|
||||
// 遍历所有作品,收集数据
|
||||
rowIndex := 2
|
||||
for _, workUuid := range workUuids {
|
||||
var workResp *cast.WorkDetailResp
|
||||
workResp, err = service.CastProvider.WorkDetail(context.Background(), &cast.WorkDetailReq{WorkUuid: workUuid})
|
||||
if err != nil {
|
||||
continue // 如果某个作品获取失败,跳过继续处理其他作品
|
||||
}
|
||||
// 内容类型
|
||||
contentType := ""
|
||||
if workResp.WorkCategory == 1 {
|
||||
contentType = "图文"
|
||||
} else if workResp.WorkCategory == 2 {
|
||||
contentType = "视频"
|
||||
}
|
||||
// 执行结果
|
||||
executionResult := modelCast.WorkStatusMM[int(workResp.WorkStatus)]
|
||||
tiktokStatus := ""
|
||||
youtubeStatus := ""
|
||||
insStatus := ""
|
||||
dmStatus := ""
|
||||
blueskyStatus := ""
|
||||
|
||||
// 获取平台信息和艺人姓名
|
||||
artistName := ""
|
||||
var infoResp *cast.WorkInfoResp
|
||||
infoResp, err = service.CastProvider.WorkInfo(context.Background(), &cast.WorkInfoReq{WorkUuid: workUuid})
|
||||
if err == nil && infoResp != nil {
|
||||
artistName = infoResp.ArtistName
|
||||
if infoResp.PlatformInfoData != nil {
|
||||
for _, platform := range infoResp.PlatformInfoData {
|
||||
statusText := modelCast.PlatformPublishStatusMM[platform.PublishMediaStatus]
|
||||
switch cast.PlatformIDENUM(platform.PlatformID) {
|
||||
case cast.PlatformIDENUM_TIKTOK:
|
||||
tiktokStatus = statusText
|
||||
case cast.PlatformIDENUM_YOUTUBE:
|
||||
youtubeStatus = statusText
|
||||
case cast.PlatformIDENUM_INS:
|
||||
insStatus = statusText
|
||||
case cast.PlatformIDENUM_DM:
|
||||
dmStatus = statusText
|
||||
case cast.PlatformIDENUM_BULESKY:
|
||||
blueskyStatus = statusText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
row := []interface{}{
|
||||
workResp.ArtistSubNum,
|
||||
artistName,
|
||||
contentType,
|
||||
workResp.Title,
|
||||
executionResult,
|
||||
tiktokStatus,
|
||||
youtubeStatus,
|
||||
insStatus,
|
||||
dmStatus,
|
||||
blueskyStatus,
|
||||
}
|
||||
cell, _ := excelize.CoordinatesToCellName(1, rowIndex)
|
||||
if err = sw.SetRow(cell, row); err != nil {
|
||||
continue
|
||||
}
|
||||
rowIndex++
|
||||
}
|
||||
if err = sw.Flush(); err != nil {
|
||||
zap.L().Error("PublishTaskExcel Flush err", zap.Error(err))
|
||||
return "", errors.New("生成Excel文件失败")
|
||||
}
|
||||
tempDir := "./runtime/task"
|
||||
if _, err = os.Stat(tempDir); os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(tempDir, 0755); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
TaskActionName, ok := modelCast.TaskActionName[action]
|
||||
if !ok {
|
||||
TaskActionName = "未知任务"
|
||||
}
|
||||
filename := fmt.Sprintf("%s_%s.xlsx", TaskActionName, time.Now().Format("20060102150405"))
|
||||
filePath := tempDir + "/" + filename
|
||||
var exportUrl string = fmt.Sprintf("%s/api/fiee/static/%s", config.AppConfig.System.FieeHost, strings.Replace(filePath, "./runtime/", "", 1))
|
||||
if err = f.SaveAs(filePath); err != nil {
|
||||
zap.L().Error("PublishTaskExcel SaveAs err", zap.Error(err))
|
||||
return "", errors.New("保存Excel文件失败")
|
||||
}
|
||||
if uploadOss {
|
||||
// 上传到阿里云
|
||||
exportUrl, err = upload.PutBos(filePath, "excel", true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
return exportUrl, nil
|
||||
}
|
||||
|
||||
@ -16,6 +16,10 @@ import (
|
||||
|
||||
func Test(ctx *gin.Context) {
|
||||
action := ctx.PostForm("action")
|
||||
if action == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if action == "getPost" {
|
||||
id := ctx.PostForm("id")
|
||||
profileKey := ctx.PostForm("profileKey")
|
||||
@ -70,19 +74,6 @@ func Test(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if action == "" {
|
||||
resp, err := service.CastProvider.WorkList(context.Background(), &cast.WorkListReq{
|
||||
Page: 1,
|
||||
PageSize: 1000,
|
||||
SubmitTimeMonths: []string{"2026-01", "2025-12"},
|
||||
})
|
||||
if err != nil {
|
||||
service.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
service.Success(ctx, resp)
|
||||
return
|
||||
}
|
||||
if action == "getProfile" {
|
||||
//profileKey := ctx.PostForm("profileKey")
|
||||
resp, err := service.AyrshareProvider.GetProfiles(context.Background(), &aryshare.GetProfilesRequest{
|
||||
@ -166,6 +157,16 @@ func Test(ctx *gin.Context) {
|
||||
service.Success(ctx, "ok")
|
||||
}
|
||||
|
||||
if action == "RefreshWorkList" {
|
||||
resp, err := service.CastProvider.RefreshWorkList(context.Background(), &cast.RefreshWorkListReq{PublishStatus: 1})
|
||||
if err != nil {
|
||||
service.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
service.Success(ctx, resp)
|
||||
return
|
||||
}
|
||||
|
||||
service.Success(ctx, "unknow")
|
||||
return
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ import (
|
||||
"fonchain-fiee/pkg/service/check"
|
||||
"fonchain-fiee/pkg/service/upload"
|
||||
"fonchain-fiee/pkg/utils"
|
||||
utilsImg "fonchain-fiee/pkg/utils/img"
|
||||
"fonchain-fiee/pkg/utils/stime"
|
||||
"image"
|
||||
"image/jpeg"
|
||||
@ -109,11 +110,10 @@ func UpdateWorkImageCore(ctx *gin.Context, req *cast.UpdateWorkImageReq) (*cast.
|
||||
ID: artistId,
|
||||
Domain: "app",
|
||||
})
|
||||
zap.L().Info("UpdateWorkImage infoResp", zap.Any("infoResp", infoResp))
|
||||
zap.L().Info("UpdateWorkImage infoResp1", zap.Any("infoResp", infoResp))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.ArtistName = infoResp.Name
|
||||
req.ArtistPhone = infoResp.TelNum
|
||||
req.ArtistPhoneAreaCode = infoResp.TelAreaCode
|
||||
@ -127,6 +127,7 @@ func UpdateWorkImageCore(ctx *gin.Context, req *cast.UpdateWorkImageReq) (*cast.
|
||||
resp, err := service.CastProvider.UpdateWorkImage(newCtx, req)
|
||||
zap.L().Info("UpdateWorkImage resp", zap.Any("resp", resp))
|
||||
if err != nil {
|
||||
zap.L().Error("UpdateWorkImage err", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
@ -434,10 +435,26 @@ func Publish(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
newCtx := NewCtxWithUserInfo(ctx)
|
||||
loginInfo := login.GetUserInfoFromC(ctx)
|
||||
var extraBytes []byte
|
||||
extraBytes, _ = json.Marshal(req)
|
||||
_, err = service.CastProvider.UpsertTaskList(newCtx, &cast.UpsertTaskListReq{
|
||||
Action: "publishBatch1",
|
||||
Url: "",
|
||||
Status: 1,
|
||||
OperatorID: fmt.Sprint(loginInfo.ID),
|
||||
OperatorName: loginInfo.Name,
|
||||
ExtraData: string(extraBytes),
|
||||
})
|
||||
if err != nil {
|
||||
service.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
if err = PublishWork(newCtx, req); err != nil {
|
||||
service.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
service.Success(ctx, req)
|
||||
return
|
||||
}
|
||||
@ -445,7 +462,6 @@ func Publish(ctx *gin.Context) {
|
||||
// PublishWork 统一发布
|
||||
func PublishWork(ctx context.Context, req *cast.PublishReq) error {
|
||||
var (
|
||||
wg sync.WaitGroup
|
||||
errsMu sync.Mutex
|
||||
errs []error
|
||||
)
|
||||
@ -453,20 +469,45 @@ func PublishWork(ctx context.Context, req *cast.PublishReq) error {
|
||||
if len(req.WorkUuids) == 0 {
|
||||
return errors.New("请选择作品")
|
||||
}
|
||||
jobs := make(chan string, len(req.WorkUuids))
|
||||
// 添加日志
|
||||
zap.L().Info("开始发布作品", zap.Int("总数", len(req.WorkUuids)))
|
||||
startTime := time.Now().Unix()
|
||||
workerCount := 10
|
||||
if len(req.WorkUuids) < workerCount {
|
||||
workerCount = len(req.WorkUuids) // 避免创建多余的协程
|
||||
|
||||
// 每批次协程数量设为8
|
||||
workerCount := 8
|
||||
batchSize := workerCount // 每批处理8个任务
|
||||
|
||||
// 分批处理
|
||||
for batchStart := 0; batchStart < len(req.WorkUuids); batchStart += batchSize {
|
||||
batchEnd := batchStart + batchSize
|
||||
if batchEnd > len(req.WorkUuids) {
|
||||
batchEnd = len(req.WorkUuids)
|
||||
}
|
||||
for i := 0; i < workerCount; i++ {
|
||||
|
||||
currentBatch := req.WorkUuids[batchStart:batchEnd]
|
||||
batchNum := batchStart/batchSize + 1
|
||||
totalBatches := (len(req.WorkUuids) + batchSize - 1) / batchSize
|
||||
|
||||
zap.L().Info("开始处理批次",
|
||||
zap.Int("批次", batchNum),
|
||||
zap.Int("总批次", totalBatches),
|
||||
zap.Int("本批数量", len(currentBatch)))
|
||||
|
||||
// 处理当前批次
|
||||
var wg sync.WaitGroup
|
||||
jobs := make(chan string, len(currentBatch))
|
||||
|
||||
currentWorkerCount := workerCount
|
||||
if len(currentBatch) < workerCount {
|
||||
currentWorkerCount = len(currentBatch) // 避免创建多余的协程
|
||||
}
|
||||
|
||||
for i := 0; i < currentWorkerCount; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for workUuid := range jobs {
|
||||
if err := PostAS(workUuid); err != nil {
|
||||
if err := PostAS(ctx, workUuid); err != nil {
|
||||
errsMu.Lock()
|
||||
errs = append(errs, err)
|
||||
errsMu.Unlock()
|
||||
@ -474,11 +515,23 @@ func PublishWork(ctx context.Context, req *cast.PublishReq) error {
|
||||
}
|
||||
}()
|
||||
}
|
||||
for _, workUuid := range req.WorkUuids {
|
||||
|
||||
for _, workUuid := range currentBatch {
|
||||
jobs <- workUuid
|
||||
}
|
||||
close(jobs)
|
||||
wg.Wait()
|
||||
|
||||
zap.L().Info("批次处理完成", zap.Int("批次", batchNum))
|
||||
|
||||
// 如果不是最后一批,等待10-15秒再进行下一批
|
||||
if batchEnd < len(req.WorkUuids) {
|
||||
waitTime := 10 + time.Duration(time.Now().UnixNano()%6) // 随机10-15秒
|
||||
zap.L().Info("等待后再处理下一批", zap.Int64("等待秒数", int64(waitTime)))
|
||||
time.Sleep(waitTime * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
// 统计结果
|
||||
successCount := len(req.WorkUuids) - len(errs)
|
||||
zap.L().Info("发布完成",
|
||||
@ -493,9 +546,9 @@ func PublishWork(ctx context.Context, req *cast.PublishReq) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func PostAS(workUuid string) error {
|
||||
func PostAS(ctx context.Context, workUuid string) error {
|
||||
var err error
|
||||
_, err = service.CastProvider.Publish(context.Background(), &cast.PublishReq{WorkUuids: []string{workUuid}})
|
||||
_, err = service.CastProvider.Publish(ctx, &cast.PublishReq{WorkUuids: []string{workUuid}})
|
||||
if err != nil {
|
||||
zap.L().Error("Publish err", zap.String("workUuid", workUuid), zap.Error(err))
|
||||
return err
|
||||
@ -528,7 +581,12 @@ func PostAS(workUuid string) error {
|
||||
if workDetail.WorkCategory == 1 {
|
||||
isVideo = false
|
||||
// 先用服务器上的文件,不上传到第三方
|
||||
//mediaUrls = workDetail.Images
|
||||
mediaUrls, err = ProcessImg(workDetail.Images)
|
||||
if err != nil {
|
||||
mediaUrls = workDetail.Images
|
||||
err = nil
|
||||
}
|
||||
/* for _, imageUrl := range workDetail.Images {
|
||||
urlResp, err = UploadMediaByURL(context.Background(), imageUrl, "", "")
|
||||
if err != nil {
|
||||
@ -544,6 +602,10 @@ func PostAS(workUuid string) error {
|
||||
isVideo = true
|
||||
mediaUrls = []string{workDetail.VideoUrl}
|
||||
coverUrl = workDetail.CoverUrl
|
||||
coverUrls, _ := ProcessImg([]string{workDetail.CoverUrl})
|
||||
if len(coverUrls) > 0 {
|
||||
coverUrl = coverUrls[0]
|
||||
}
|
||||
// 先用服务器上的文件,不上传到第三方
|
||||
/*urlResp, err = UploadMediaByURL(context.Background(), workDetail.VideoUrl, "", "")
|
||||
if err != nil {
|
||||
@ -686,7 +748,7 @@ func PostAS(workUuid string) error {
|
||||
PublishType: 2,
|
||||
PublishResp: _err.Error(),
|
||||
PublishMediaId: "",
|
||||
PublishStatus: cast.PublishStatusENUM_PublishMediaStatus_EXCEPTION,
|
||||
PublishMediaStatus: cast.PublishStatusENUM_PublishMediaStatus_EXCEPTION,
|
||||
Remark: "",
|
||||
})
|
||||
zap.L().Info("UpdateWorkPlatformInfo", zap.Any("infoReq", infoReq))
|
||||
@ -747,7 +809,7 @@ func PostAS(workUuid string) error {
|
||||
PublishType: 2,
|
||||
PublishResp: string(postBytes),
|
||||
PublishMediaId: postResp.Posts[0].Id,
|
||||
PublishStatus: publishStatus,
|
||||
PublishMediaStatus: publishStatus,
|
||||
Remark: string(postData),
|
||||
})
|
||||
}
|
||||
@ -806,11 +868,27 @@ func RePublish(ctx *gin.Context) {
|
||||
service.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
fmt.Println(resp)
|
||||
loginInfo := login.GetUserInfoFromC(ctx)
|
||||
var extraBytes []byte
|
||||
extraBytes, _ = json.Marshal(req)
|
||||
_, err = service.CastProvider.UpsertTaskList(newCtx, &cast.UpsertTaskListReq{
|
||||
Action: "publishBatch2",
|
||||
Url: "",
|
||||
Status: 1,
|
||||
OperatorID: fmt.Sprint(loginInfo.ID),
|
||||
OperatorName: loginInfo.Name,
|
||||
ExtraData: string(extraBytes),
|
||||
})
|
||||
if err != nil {
|
||||
zap.L().Error("RePublish UpsertTaskList failed", zap.Error(err))
|
||||
service.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
if err = PublishWork(newCtx, &cast.PublishReq{WorkUuids: resp.WorkUuids}); err != nil {
|
||||
service.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
service.Success(ctx, req)
|
||||
return
|
||||
}
|
||||
@ -1564,9 +1642,11 @@ func ImportWorkBatch(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
}
|
||||
service.CastProvider.UpsertTaskList(context.Background(), &cast.UpsertTaskListReq{
|
||||
urlResult, _ = upload.PutBos(excelPath, "excel", true)
|
||||
_, _ = service.CastProvider.UpsertTaskList(context.Background(), &cast.UpsertTaskListReq{
|
||||
Uuid: taskResp.Uuid,
|
||||
Status: 3,
|
||||
Url: urlResult,
|
||||
})
|
||||
service.Success(ctx, map[string]interface{}{
|
||||
"successCount": resp.SuccessCount,
|
||||
@ -1600,6 +1680,14 @@ func RefreshPublish() error {
|
||||
}
|
||||
for _, platformInfo := range workInfo.PlatformInfoData {
|
||||
if platformInfo.PublishMediaID == "" {
|
||||
var infoReq = &cast.UpdateWorkPlatformInfoReq{
|
||||
PlatformInfoData: make([]*cast.PlatformInfo, 0),
|
||||
}
|
||||
infoReq.PlatformInfoData = append(infoReq.PlatformInfoData, &cast.PlatformInfo{
|
||||
WorkUuid: workInfo.WorkUuid,
|
||||
PublishMediaStatus: cast.PublishStatusENUM_PublishMediaStatus_NO,
|
||||
})
|
||||
_, _ = service.CastProvider.UpdateWorkPlatformInfo(context.Background(), infoReq)
|
||||
continue
|
||||
}
|
||||
var infoReq = &cast.UpdateWorkPlatformInfoReq{
|
||||
@ -1618,7 +1706,7 @@ func RefreshPublish() error {
|
||||
PublishType: 2,
|
||||
PublishResp: err.Error(),
|
||||
PublishMediaId: platformInfo.PublishMediaID,
|
||||
PublishStatus: cast.PublishStatusENUM_PublishMediaStatus_EXCEPTION,
|
||||
PublishMediaStatus: cast.PublishStatusENUM_PublishMediaStatus_EXCEPTION,
|
||||
Remark: "",
|
||||
PlatformUuid: platformInfo.PlatformUuid,
|
||||
})
|
||||
@ -1635,7 +1723,7 @@ func RefreshPublish() error {
|
||||
PublishType: 2,
|
||||
PublishResp: string(dmData),
|
||||
PublishMediaId: platformInfo.PublishMediaID,
|
||||
PublishStatus: cast.PublishStatusENUM_PublishMediaStatus_DONE,
|
||||
PublishMediaStatus: cast.PublishStatusENUM_PublishMediaStatus_DONE,
|
||||
Remark: "",
|
||||
PlatformUuid: platformInfo.PlatformUuid,
|
||||
})
|
||||
@ -1688,7 +1776,7 @@ func RefreshPublish() error {
|
||||
PublishType: 2,
|
||||
PublishResp: _err.Error(),
|
||||
PublishMediaId: platformInfo.PublishMediaID,
|
||||
PublishStatus: cast.PublishStatusENUM_PublishMediaStatus_EXCEPTION,
|
||||
PublishMediaStatus: cast.PublishStatusENUM_PublishMediaStatus_EXCEPTION,
|
||||
Remark: "",
|
||||
PlatformUuid: platformInfo.PlatformUuid,
|
||||
})
|
||||
@ -1708,7 +1796,7 @@ func RefreshPublish() error {
|
||||
PublishType: 2,
|
||||
PublishResp: string(postBytes),
|
||||
PublishMediaId: platformInfo.PublishMediaID,
|
||||
PublishStatus: cast.PublishStatusENUM_PublishMediaStatus_FAIL,
|
||||
PublishMediaStatus: cast.PublishStatusENUM_PublishMediaStatus_FAIL,
|
||||
Remark: "",
|
||||
PlatformUuid: platformInfo.PlatformUuid,
|
||||
})
|
||||
@ -1738,7 +1826,7 @@ func RefreshPublish() error {
|
||||
PublishType: 2,
|
||||
PublishResp: string(postBytes),
|
||||
PublishMediaId: platformInfo.PublishMediaID,
|
||||
PublishStatus: publishStatus,
|
||||
PublishMediaStatus: publishStatus,
|
||||
Remark: "",
|
||||
PlatformUuid: platformInfo.PlatformUuid,
|
||||
})
|
||||
@ -1799,3 +1887,38 @@ func checkAndReuploadImage(imageUrl string, mediaType string) (string, error) {
|
||||
}
|
||||
return compressUrl, nil
|
||||
}
|
||||
|
||||
func ProcessImg(imgs []string) ([]string, error) {
|
||||
var newImgs []string
|
||||
for _, img := range imgs {
|
||||
newPath, err := utilsImg.ProcessFromURL(
|
||||
img,
|
||||
utilsImg.Options{
|
||||
TargetWidth: 1024,
|
||||
TargetHeight: 1024,
|
||||
MaxSizeMB: 1, // 提高到 2MB,对于 1024x1024 更合理
|
||||
Mode: utilsImg.ResizeModePad, // 等比缩放+留白
|
||||
OutputDir: "./runtime/tmp/images/processed",
|
||||
MinQuality: 20, // 最低质量阈值
|
||||
MaxRetries: 15, // 最大尝试次数
|
||||
AllowResolutionReduction: true, // 允许降低分辨率
|
||||
ForceJPEG: true, // 强制转换为 JPEG 格式
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
zap.L().Error("processImg err", zap.Error(err), zap.Any("img", img))
|
||||
newImgs = append(newImgs, img)
|
||||
err = nil
|
||||
continue
|
||||
}
|
||||
exportUrl, err := upload.PutBos(newPath, "fieework", true)
|
||||
if err != nil {
|
||||
zap.L().Error("upload.PutBos err", zap.Error(err), zap.Any("img", img))
|
||||
newImgs = append(newImgs, img)
|
||||
err = nil
|
||||
continue
|
||||
}
|
||||
newImgs = append(newImgs, exportUrl)
|
||||
}
|
||||
return newImgs, nil
|
||||
}
|
||||
|
||||
555
pkg/utils/img/imageproc.go
Normal file
555
pkg/utils/img/imageproc.go
Normal file
@ -0,0 +1,555 @@
|
||||
package img
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/gif"
|
||||
"image/jpeg"
|
||||
"image/png"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/disintegration/imaging"
|
||||
)
|
||||
|
||||
// ResizeMode controls how the source image is mapped to the target WxH.
|
||||
//
|
||||
// - ResizeModeFit: contain (keep aspect), no cropping; resulting image may be smaller than WxH
|
||||
// - ResizeModeFill: cover + crop (center crop) to exactly WxH
|
||||
// - ResizeModePad: keep aspect + pad (letterbox) to exactly WxH (no crop, no stretch)
|
||||
//
|
||||
// If you only pass a single dimension (e.g. W>0, H=0), Fit will keep aspect.
|
||||
// Fill/Pad requires both W and H.
|
||||
//
|
||||
// Note: GIF input will be processed as a single frame (first frame).
|
||||
// If you need animated GIF support, we can extend this later.
|
||||
type ResizeMode string
|
||||
|
||||
const (
|
||||
ResizeModeFit ResizeMode = "fit"
|
||||
ResizeModeFill ResizeMode = "fill"
|
||||
// ResizeModePad keeps aspect ratio (no crop, no stretch) and pads to exactly WxH.
|
||||
// Typical use: 16:9 -> 1024x1024 with white/black bars.
|
||||
ResizeModePad ResizeMode = "pad"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
TargetWidth int
|
||||
TargetHeight int
|
||||
MaxSizeMB float64
|
||||
|
||||
Mode ResizeMode
|
||||
|
||||
// PadColor is used only when Mode == ResizeModePad.
|
||||
// Default: white.
|
||||
PadColor color.Color
|
||||
|
||||
// OutputDir is where the processed image will be written.
|
||||
// Default: ./runtime/tmp/images/processed
|
||||
OutputDir string
|
||||
|
||||
// Timeout controls total download time.
|
||||
// Default: 30s.
|
||||
Timeout time.Duration
|
||||
|
||||
// MaxDownloadMB caps download size to protect memory/disk.
|
||||
// Default: max( maxSizeMB*6, 30MB ).
|
||||
MaxDownloadMB float64
|
||||
|
||||
// MinQuality is the minimum JPEG quality to try (1-100).
|
||||
// Default: 10. If compression still can't meet MaxSizeMB, returns error.
|
||||
MinQuality int
|
||||
|
||||
// MaxRetries controls how many quality adjustments to attempt.
|
||||
// Default: 15.
|
||||
MaxRetries int
|
||||
|
||||
// AllowResolutionReduction allows reducing resolution further if compression fails.
|
||||
// Default: false.
|
||||
AllowResolutionReduction bool
|
||||
|
||||
// ForceJPEG forces output to JPEG format even if input is PNG/GIF/etc.
|
||||
// If image has alpha channel, it will be flattened to white background.
|
||||
// Default: false.
|
||||
ForceJPEG bool
|
||||
}
|
||||
|
||||
// ProcessFromURL downloads an image from imgURL, resizes it, compresses it to <= MaxSizeMB,
|
||||
// and returns the local output path.
|
||||
//
|
||||
// Contract:
|
||||
// - imgURL: http/https
|
||||
// - TargetWidth/TargetHeight: pixels, >=0
|
||||
// - MaxSizeMB: >0
|
||||
// - returns: absolute or relative file path (depending on OutputDir), and error
|
||||
func ProcessFromURL(imgURL string, opt Options) (string, error) {
|
||||
if strings.TrimSpace(imgURL) == "" {
|
||||
return "", errors.New("imgURL is empty")
|
||||
}
|
||||
u, err := url.Parse(imgURL)
|
||||
if err != nil || (u.Scheme != "http" && u.Scheme != "https") {
|
||||
return "", errors.New("imgURL must be http/https")
|
||||
}
|
||||
if opt.MaxSizeMB <= 0 {
|
||||
return "", errors.New("MaxSizeMB must be > 0")
|
||||
}
|
||||
if opt.TargetWidth < 0 || opt.TargetHeight < 0 {
|
||||
return "", errors.New("TargetWidth/TargetHeight must be >= 0")
|
||||
}
|
||||
if opt.TargetWidth == 0 && opt.TargetHeight == 0 {
|
||||
return "", errors.New("TargetWidth and TargetHeight cannot both be 0")
|
||||
}
|
||||
if opt.Mode == "" {
|
||||
opt.Mode = ResizeModeFit
|
||||
}
|
||||
if opt.Mode != ResizeModeFit && opt.Mode != ResizeModeFill && opt.Mode != ResizeModePad {
|
||||
return "", errors.New("invalid resize Mode")
|
||||
}
|
||||
if (opt.Mode == ResizeModeFill || opt.Mode == ResizeModePad) && (opt.TargetWidth == 0 || opt.TargetHeight == 0) {
|
||||
return "", errors.New("fill/pad mode requires both TargetWidth and TargetHeight")
|
||||
}
|
||||
if opt.Timeout <= 0 {
|
||||
opt.Timeout = 30 * time.Second
|
||||
}
|
||||
if opt.OutputDir == "" {
|
||||
opt.OutputDir = filepath.FromSlash("./runtime/tmp/images/processed")
|
||||
}
|
||||
if opt.MaxDownloadMB <= 0 {
|
||||
opt.MaxDownloadMB = opt.MaxSizeMB * 6
|
||||
if opt.MaxDownloadMB < 30 {
|
||||
opt.MaxDownloadMB = 30
|
||||
}
|
||||
if opt.MaxDownloadMB > 200 {
|
||||
opt.MaxDownloadMB = 200
|
||||
}
|
||||
}
|
||||
if opt.MinQuality <= 0 {
|
||||
opt.MinQuality = 10
|
||||
}
|
||||
if opt.MinQuality > 100 {
|
||||
opt.MinQuality = 100
|
||||
}
|
||||
if opt.MaxRetries <= 0 {
|
||||
opt.MaxRetries = 15
|
||||
}
|
||||
|
||||
// Ensure output dir exists.
|
||||
if err := os.MkdirAll(opt.OutputDir, os.ModePerm); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), opt.Timeout)
|
||||
defer cancel()
|
||||
|
||||
data, contentType, err := downloadWithLimit(ctx, imgURL, int64(opt.MaxDownloadMB*1024*1024))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
img, fmtName, err := decodeImage(data, contentType)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Check if image already meets requirements
|
||||
if alreadyMeetsRequirements(img, data, opt) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
img = applyResize(img, opt)
|
||||
|
||||
// Determine output format
|
||||
outExt := ".jpg"
|
||||
outFormat := "jpeg"
|
||||
|
||||
if opt.ForceJPEG {
|
||||
// Force JPEG output, flatten alpha if needed
|
||||
outFormat = "jpeg"
|
||||
outExt = ".jpg"
|
||||
if imageHasAlpha(img) {
|
||||
img = flattenToWhite(img)
|
||||
}
|
||||
} else {
|
||||
// Auto-detect: if image has alpha, output PNG; otherwise JPEG
|
||||
hasAlpha := imageHasAlpha(img)
|
||||
if hasAlpha {
|
||||
outExt = ".png"
|
||||
outFormat = "png"
|
||||
}
|
||||
}
|
||||
|
||||
// Create a stable file name based on url + options + content signature.
|
||||
h := sha256.New()
|
||||
h.Write([]byte(imgURL))
|
||||
h.Write([]byte(fmt.Sprintf("|%d|%d|%f|%s|%s", opt.TargetWidth, opt.TargetHeight, opt.MaxSizeMB, opt.Mode, outFormat)))
|
||||
h.Write(data[:minInt(len(data), 1024)])
|
||||
name := hex.EncodeToString(h.Sum(nil))[:32] + outExt
|
||||
outPath := filepath.Join(opt.OutputDir, name)
|
||||
|
||||
maxBytes := int64(opt.MaxSizeMB * 1024 * 1024)
|
||||
encoded, err := encodeUnderSize(img, outFormat, maxBytes, opt.MinQuality, opt.MaxRetries)
|
||||
if err != nil {
|
||||
// Fallback: if PNG can't fit, try JPEG (dropping alpha with white background).
|
||||
if outFormat == "png" {
|
||||
flattened := flattenToWhite(img)
|
||||
encoded, err = encodeUnderSize(flattened, "jpeg", maxBytes, opt.MinQuality, opt.MaxRetries)
|
||||
if err == nil {
|
||||
outPath = strings.TrimSuffix(outPath, filepath.Ext(outPath)) + ".jpg"
|
||||
} else {
|
||||
// If AllowResolutionReduction is true, try reducing resolution
|
||||
if opt.AllowResolutionReduction {
|
||||
return tryWithReducedResolution(img, opt, outPath, maxBytes)
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
} else {
|
||||
// If AllowResolutionReduction is true, try reducing resolution
|
||||
if opt.AllowResolutionReduction {
|
||||
return tryWithReducedResolution(img, opt, outPath, maxBytes)
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
tmpPath := outPath + ".tmp"
|
||||
if err := os.WriteFile(tmpPath, encoded, 0o644); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := os.Rename(tmpPath, outPath); err != nil {
|
||||
_ = os.Remove(tmpPath)
|
||||
return "", err
|
||||
}
|
||||
|
||||
_ = fmtName // reserved for future behavior
|
||||
return outPath, nil
|
||||
}
|
||||
|
||||
func downloadWithLimit(ctx context.Context, imgURL string, maxBytes int64) ([]byte, string, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, imgURL, nil)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
// Reasonable defaults; could be overridden later.
|
||||
req.Header.Set("User-Agent", "fonchain-tools/1.0")
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
return nil, "", fmt.Errorf("download failed: %s", resp.Status)
|
||||
}
|
||||
if resp.ContentLength > 0 && resp.ContentLength > maxBytes {
|
||||
return nil, "", fmt.Errorf("remote file too large: %d > %d", resp.ContentLength, maxBytes)
|
||||
}
|
||||
|
||||
lr := &io.LimitedReader{R: resp.Body, N: maxBytes + 1}
|
||||
b, err := io.ReadAll(lr)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
if int64(len(b)) > maxBytes {
|
||||
return nil, "", fmt.Errorf("download exceeded limit: %d > %d", len(b), maxBytes)
|
||||
}
|
||||
return b, resp.Header.Get("Content-Type"), nil
|
||||
}
|
||||
|
||||
func decodeImage(data []byte, contentType string) (image.Image, string, error) {
|
||||
// Register gif (jpeg/png already registered) for Decode.
|
||||
_ = gif.GIF{}
|
||||
reader := bytes.NewReader(data)
|
||||
img, fmtName, err := image.Decode(reader)
|
||||
if err == nil {
|
||||
return img, fmtName, nil
|
||||
}
|
||||
|
||||
// Some servers set odd content-type; try simple sniff.
|
||||
_ = contentType
|
||||
return nil, "", fmt.Errorf("decode image failed: %w", err)
|
||||
}
|
||||
|
||||
func applyResize(img image.Image, opt Options) image.Image {
|
||||
w := opt.TargetWidth
|
||||
h := opt.TargetHeight
|
||||
|
||||
srcW := img.Bounds().Dx()
|
||||
srcH := img.Bounds().Dy()
|
||||
if srcW <= 0 || srcH <= 0 {
|
||||
return img
|
||||
}
|
||||
|
||||
switch opt.Mode {
|
||||
case ResizeModeFill:
|
||||
return imaging.Fill(img, w, h, imaging.Center, imaging.Lanczos)
|
||||
case ResizeModeFit:
|
||||
// If only one dimension is provided, keep aspect.
|
||||
if w == 0 {
|
||||
w = int(float64(srcW) * (float64(h) / float64(srcH)))
|
||||
if w < 1 {
|
||||
w = 1
|
||||
}
|
||||
}
|
||||
if h == 0 {
|
||||
h = int(float64(srcH) * (float64(w) / float64(srcW)))
|
||||
if h < 1 {
|
||||
h = 1
|
||||
}
|
||||
}
|
||||
// imaging.Fit ensures the result fits within w,h without cropping.
|
||||
return imaging.Fit(img, w, h, imaging.Lanczos)
|
||||
case ResizeModePad:
|
||||
bg := opt.PadColor
|
||||
if bg == nil {
|
||||
bg = color.White
|
||||
}
|
||||
// First, fit within WxH (no crop).
|
||||
fitted := imaging.Fit(img, w, h, imaging.Lanczos)
|
||||
// Then, paste centered onto WxH canvas.
|
||||
canvas := imaging.New(w, h, bg)
|
||||
x := (w - fitted.Bounds().Dx()) / 2
|
||||
y := (h - fitted.Bounds().Dy()) / 2
|
||||
return imaging.Paste(canvas, fitted, image.Pt(x, y))
|
||||
default:
|
||||
return img
|
||||
}
|
||||
}
|
||||
|
||||
func encodeUnderSize(img image.Image, format string, maxBytes int64, minQuality, maxRetries int) ([]byte, error) {
|
||||
if maxBytes <= 0 {
|
||||
return nil, errors.New("maxBytes must be > 0")
|
||||
}
|
||||
|
||||
switch format {
|
||||
case "jpeg":
|
||||
// Binary search quality.
|
||||
lo, hi := minQuality, 92
|
||||
var best []byte
|
||||
iterations := 0
|
||||
maxIterations := maxInt(8, maxRetries/2)
|
||||
|
||||
for i := 0; i < maxIterations && lo <= hi; i++ {
|
||||
iterations++
|
||||
q := (lo + hi) / 2
|
||||
b, err := encodeJPEG(img, q)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if int64(len(b)) <= maxBytes {
|
||||
best = b
|
||||
lo = q + 1
|
||||
} else {
|
||||
hi = q - 1
|
||||
}
|
||||
}
|
||||
|
||||
if best != nil {
|
||||
return best, nil
|
||||
}
|
||||
|
||||
// Try more aggressive qualities from minQuality down to 1
|
||||
qualities := []int{}
|
||||
for q := minQuality; q >= 1; q -= 5 {
|
||||
qualities = append(qualities, q)
|
||||
}
|
||||
// Ensure we try the lowest qualities
|
||||
if minQuality > 3 {
|
||||
qualities = append(qualities, 3, 1)
|
||||
}
|
||||
|
||||
var lastSize int64
|
||||
for _, q := range qualities {
|
||||
if iterations >= maxRetries {
|
||||
break
|
||||
}
|
||||
iterations++
|
||||
b, err := encodeJPEG(img, q)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lastSize = int64(len(b))
|
||||
if lastSize <= maxBytes {
|
||||
return b, nil
|
||||
}
|
||||
}
|
||||
|
||||
sizeMB := float64(lastSize) / (1024 * 1024)
|
||||
targetMB := float64(maxBytes) / (1024 * 1024)
|
||||
return nil, fmt.Errorf("cannot compress to %.2fMB (best: %.2fMB at quality %d after %d attempts). Consider increasing MaxSizeMB or enabling AllowResolutionReduction",
|
||||
targetMB, sizeMB, minQuality, iterations)
|
||||
|
||||
case "png":
|
||||
// PNG size depends heavily on content; try best compression.
|
||||
b, err := encodePNG(img, png.BestCompression)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if int64(len(b)) <= maxBytes {
|
||||
return b, nil
|
||||
}
|
||||
sizeMB := float64(len(b)) / (1024 * 1024)
|
||||
targetMB := float64(maxBytes) / (1024 * 1024)
|
||||
return nil, fmt.Errorf("PNG cannot compress to %.2fMB (got %.2fMB). Consider using JPEG format or enabling AllowResolutionReduction",
|
||||
targetMB, sizeMB)
|
||||
|
||||
default:
|
||||
return nil, errors.New("unsupported output format")
|
||||
}
|
||||
}
|
||||
|
||||
func encodeJPEG(img image.Image, quality int) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
// Use 4:2:0 subsampling (default) for smaller size.
|
||||
err := jpeg.Encode(&buf, img, &jpeg.Options{Quality: quality})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func encodePNG(img image.Image, level png.CompressionLevel) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
enc := png.Encoder{CompressionLevel: level}
|
||||
if err := enc.Encode(&buf, img); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func imageHasAlpha(img image.Image) bool {
|
||||
switch img.(type) {
|
||||
case *image.NRGBA, *image.NRGBA64, *image.RGBA, *image.RGBA64, *image.Alpha, *image.Alpha16, *image.Paletted:
|
||||
// Need to inspect pixels if we want exactness; but this is good enough and stable.
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func flattenToWhite(img image.Image) image.Image {
|
||||
b := img.Bounds()
|
||||
dst := image.NewRGBA(b)
|
||||
|
||||
// Fill with white.
|
||||
for y := b.Min.Y; y < b.Max.Y; y++ {
|
||||
for x := b.Min.X; x < b.Max.X; x++ {
|
||||
dst.Set(x, y, image.White)
|
||||
}
|
||||
}
|
||||
|
||||
// Draw original image over white background.
|
||||
return imaging.Overlay(dst, img, image.Pt(0, 0), 1.0)
|
||||
}
|
||||
|
||||
func minInt(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func maxInt(a, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// alreadyMeetsRequirements checks if the image already satisfies the size and dimension requirements
|
||||
func alreadyMeetsRequirements(img image.Image, data []byte, opt Options) bool {
|
||||
// Check file size
|
||||
maxBytes := int64(opt.MaxSizeMB * 1024 * 1024)
|
||||
if int64(len(data)) > maxBytes {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check dimensions based on mode
|
||||
srcW := img.Bounds().Dx()
|
||||
srcH := img.Bounds().Dy()
|
||||
targetW := opt.TargetWidth
|
||||
targetH := opt.TargetHeight
|
||||
|
||||
switch opt.Mode {
|
||||
case ResizeModeFit:
|
||||
// For fit mode, check if image is already within or equal to target dimensions
|
||||
if targetW > 0 && srcW > targetW {
|
||||
return false
|
||||
}
|
||||
if targetH > 0 && srcH > targetH {
|
||||
return false
|
||||
}
|
||||
// If only one dimension is specified, check aspect ratio compatibility
|
||||
if targetW > 0 && targetH == 0 && srcW <= targetW {
|
||||
return true
|
||||
}
|
||||
if targetH > 0 && targetW == 0 && srcH <= targetH {
|
||||
return true
|
||||
}
|
||||
if targetW > 0 && targetH > 0 && srcW <= targetW && srcH <= targetH {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
case ResizeModeFill, ResizeModePad:
|
||||
// For fill/pad mode, image must be exactly the target dimensions
|
||||
if srcW != targetW || srcH != targetH {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// tryWithReducedResolution attempts to compress by progressively reducing resolution
|
||||
func tryWithReducedResolution(img image.Image, opt Options, outPath string, maxBytes int64) (string, error) {
|
||||
bounds := img.Bounds()
|
||||
w := bounds.Dx()
|
||||
h := bounds.Dy()
|
||||
|
||||
// Try reducing resolution in steps: 90%, 80%, 70%, 60%, 50%
|
||||
reductions := []float64{0.9, 0.8, 0.7, 0.6, 0.5}
|
||||
|
||||
for _, factor := range reductions {
|
||||
newW := int(float64(w) * factor)
|
||||
newH := int(float64(h) * factor)
|
||||
|
||||
if newW < 100 || newH < 100 {
|
||||
break // Don't reduce too much
|
||||
}
|
||||
|
||||
resized := imaging.Resize(img, newW, newH, imaging.Lanczos)
|
||||
|
||||
// Try to encode with reduced resolution
|
||||
encoded, err := encodeUnderSize(resized, "jpeg", maxBytes, opt.MinQuality, opt.MaxRetries/2)
|
||||
if err == nil {
|
||||
// Success! Save it
|
||||
tmpPath := outPath + ".tmp"
|
||||
if err := os.WriteFile(tmpPath, encoded, 0o644); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := os.Rename(tmpPath, outPath); err != nil {
|
||||
_ = os.Remove(tmpPath)
|
||||
return "", err
|
||||
}
|
||||
return outPath, nil
|
||||
}
|
||||
}
|
||||
|
||||
targetMB := float64(maxBytes) / (1024 * 1024)
|
||||
return "", fmt.Errorf("cannot compress to %.2fMB even after reducing resolution to 50%%. Original size too large", targetMB)
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user