@@ -0,0 +1,195 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
client = http.Client{
|
||||
Timeout: 30 * time.Second,
|
||||
Transport: &http.Transport{
|
||||
MaxIdleConnsPerHost: 5,
|
||||
MaxConnsPerHost: 100,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
type ByteSize int64
|
||||
|
||||
const (
|
||||
_ = iota // ignore first value by assigning to blank identifier
|
||||
KB ByteSize = 1 << (10 * iota)
|
||||
MB
|
||||
)
|
||||
|
||||
var (
|
||||
outOfBodySizeErr = errors.New("out of body size limit")
|
||||
)
|
||||
|
||||
type ResponseBody struct {
|
||||
StatusCode int
|
||||
Data []byte
|
||||
}
|
||||
|
||||
type RequestFormData map[string]string
|
||||
|
||||
// Post
|
||||
// Note: 只会读取小于1M的数据
|
||||
func Post(url string, header map[string]string, body io.Reader) (fr *ResponseBody, err error) {
|
||||
fr, err = do(http.MethodPost, url, header, body, int64(1024*MB))
|
||||
return
|
||||
}
|
||||
|
||||
// PostFormData 提交标准的form表单
|
||||
func PostFormData(url string, fromdata RequestFormData) (fr *ResponseBody, err error) {
|
||||
var b bytes.Buffer
|
||||
writer := multipart.NewWriter(&b)
|
||||
|
||||
for k, v := range fromdata {
|
||||
if err = writer.WriteField(k, v); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if err = writer.Close(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
header := map[string]string{"Content-Type": writer.FormDataContentType()}
|
||||
fr, err = do(http.MethodPost, url, header, &b, 2*int64(KB))
|
||||
return
|
||||
}
|
||||
|
||||
// Get
|
||||
// Note: 只会读取小于1M的数据
|
||||
func Get(url string, header map[string]string) (fr *ResponseBody, err error) {
|
||||
fr, err = do(http.MethodGet, url, header, nil, int64(KB))
|
||||
return
|
||||
}
|
||||
|
||||
func GetWithBody(url string, header map[string]string, body io.Reader) (fr *ResponseBody, err error) {
|
||||
fr, err = do(http.MethodGet, url, header, body, int64(20*MB))
|
||||
return
|
||||
}
|
||||
|
||||
// GetLargeFile 获取大文件。2M
|
||||
func GetLargeFile(url string, header map[string]string) (fr *ResponseBody, err error) {
|
||||
fr, err = do(http.MethodGet, url, header, nil, int64(20*MB))
|
||||
return
|
||||
}
|
||||
|
||||
func do(method string, url string, header map[string]string, body io.Reader, size int64) (fr *ResponseBody, err error) {
|
||||
req, err := http.NewRequest(method, url, body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for k, v := range header {
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.ContentLength > size {
|
||||
err = outOfBodySizeErr
|
||||
return
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(io.LimitReader(resp.Body, size))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fr = &ResponseBody{
|
||||
StatusCode: resp.StatusCode,
|
||||
Data: data,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 推送对象到文件服务器
|
||||
func PostObject(ctx context.Context, url string, header map[string]string, body []byte, objName string) (string, error) {
|
||||
base64data := base64.StdEncoding.EncodeToString(body)
|
||||
|
||||
req := struct {
|
||||
Name string `json:"fileName"`
|
||||
Data string `json:"fileData"`
|
||||
}{
|
||||
Name: objName,
|
||||
Data: base64data,
|
||||
}
|
||||
|
||||
jsonBytes, _ := json.Marshal(req)
|
||||
|
||||
resp, err := Post(url, header, bytes.NewReader(jsonBytes))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
type Obj struct {
|
||||
Domain string `json:"domain"`
|
||||
Name string `json:"fileName"`
|
||||
}
|
||||
|
||||
fsResp := struct {
|
||||
Code int `json:"code"`
|
||||
Object Obj `json:"data"`
|
||||
Msg string `json:"msg"`
|
||||
}{}
|
||||
|
||||
if err = json.Unmarshal(resp.Data, &fsResp); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if fsResp.Code != 200 || fsResp.Object.Name == "" {
|
||||
return "", fmt.Errorf("上传fs失败")
|
||||
}
|
||||
|
||||
return fsResp.Object.Name, nil
|
||||
}
|
||||
|
||||
func PostWithBind(ctx context.Context, bind interface{}, url string, body io.Reader) error {
|
||||
if err := verifyBind(bind); err != nil {
|
||||
return err
|
||||
}
|
||||
req, err := http.NewRequestWithContext(ctx, "POST", url, body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("response status code:%d", resp.StatusCode)
|
||||
}
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(data, bind)
|
||||
}
|
||||
|
||||
func verifyBind(bind interface{}) error {
|
||||
bType := reflect.TypeOf(bind)
|
||||
if bType.Kind() != reflect.Ptr {
|
||||
return errors.New("bind must be a Ptr")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package http
|
||||
|
||||
import "fmt"
|
||||
|
||||
func ExampleGet() {
|
||||
urlstr := "https://palce.hzbeisheng.com/api/sms"
|
||||
data, err := Get(urlstr, nil)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(data.Data))
|
||||
|
||||
// Output:
|
||||
|
||||
}
|
||||
@@ -0,0 +1,348 @@
|
||||
package tianyuctrl
|
||||
|
||||
import (
|
||||
"91porn-server/common"
|
||||
"91porn-server/common/log"
|
||||
"91porn-server/common/stderr"
|
||||
"91porn-server/models/v/mediacontentmod"
|
||||
"91porn-server/models/v/mediamod"
|
||||
"91porn-server/models/v/mediatagmod"
|
||||
"91porn-server/models/v/usermod"
|
||||
"91porn-server/models/v/vidmod"
|
||||
"91porn-server/web/api/tianyuctrl/proxy"
|
||||
"91porn-server/web/service/vidser"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
// VideoSearch doc
|
||||
// @Tags 媒体文件
|
||||
// @Summary 根据参数获取视频文件列表
|
||||
// @Description 获取视频列表文件
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param req body proxy.MediaSearchReq true "参数列表"
|
||||
// @Success 200 {object} proxy.MediaSearchResp "成功"
|
||||
// @Failure 400 {string} string "获取失败的返回结果"
|
||||
// @Router /api/web/admin/tianyu/search [post]
|
||||
func VideoSearch(ctx *gin.Context) {
|
||||
var req proxy.MediaSearchReq
|
||||
if err := ctx.ShouldBind(&req); err != nil {
|
||||
common.ServeJSON(ctx, stderr.ErrParamError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
videoUploadDomain := proxy.BucketVideoAddressV2
|
||||
result, err := proxy.PostSearch(&req, videoUploadDomain)
|
||||
if err != nil {
|
||||
common.ServeJSON(ctx, stderr.Failure, err.Error())
|
||||
return
|
||||
}
|
||||
sourceMediaIds := make([]string, 0)
|
||||
for _, mediaInfo := range result.Data.List {
|
||||
sourceMediaIds = append(sourceMediaIds, mediaInfo.ID.Hex())
|
||||
}
|
||||
|
||||
videoList, _ := vidmod.GetList(bson.M{"sourceID": bson.M{"$in": sourceMediaIds}})
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("mediamod queryAllList error:%+v:", err))
|
||||
common.ServeJSON(ctx, stderr.Failure, err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range result.Data.List {
|
||||
if v.Type == "AI" {
|
||||
v.FieldNameFs += ".mp4"
|
||||
}
|
||||
for _, v1 := range videoList {
|
||||
if v.ID.Hex() == v1.SourceID {
|
||||
v.IsAdd = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
common.ServeJSON(ctx, stderr.Success, result.Data)
|
||||
|
||||
}
|
||||
|
||||
// AddOneMedia doc
|
||||
// @Tags 视频
|
||||
// @Summary 添加一个视频视频
|
||||
// @Description 添加一个视频视频
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param param body MediaAdd true "参数列表"
|
||||
// @Success 200 {string} string "成功"
|
||||
// @Failure 400 {string} string "获取失败的返回结果"
|
||||
// @Router /api/web/admin/tianyu/add [post]
|
||||
func AddOneMedia(ctx *gin.Context) {
|
||||
var req = &MediaAdd{}
|
||||
if err := ctx.ShouldBind(req); err != nil {
|
||||
common.ServeJSON(ctx, stderr.ErrParamError, err)
|
||||
return
|
||||
}
|
||||
|
||||
manager, err := common.GetAdminAct(ctx)
|
||||
if err != nil {
|
||||
common.ServeJSON(ctx, stderr.ErrParamError, err.Error())
|
||||
return
|
||||
}
|
||||
var resp = MediaAddResp{SensitiveHits: make([]vidser.SensitiveHit, 0)}
|
||||
terms := vidser.LoadEnabledSensitiveTerms()
|
||||
for _, s := range req.FileId {
|
||||
in := proxy.MediaQueryeReq{
|
||||
Id: s,
|
||||
}
|
||||
|
||||
videoUploadDomain := proxy.BucketVideoAddressV2
|
||||
result, err := proxy.QueryMedia(&in, videoUploadDomain)
|
||||
if err != nil || result.Code != http.StatusOK {
|
||||
resp.FailCount++
|
||||
continue
|
||||
}
|
||||
var hit *vidser.SensitiveHit
|
||||
if result.Data.ContentType == 3 {
|
||||
hit, err = AddMedia(ctx, &result.Data, manager, terms)
|
||||
} else {
|
||||
hit, err = AddVideo(ctx, &result.Data, manager, terms)
|
||||
}
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("add tianyu media error:%+v:", err))
|
||||
resp.FailCount++
|
||||
continue
|
||||
}
|
||||
if hit != nil {
|
||||
resp.SensitiveHits = append(resp.SensitiveHits, *hit)
|
||||
}
|
||||
resp.SuccessCount++
|
||||
}
|
||||
if len(resp.SensitiveHits) > 0 {
|
||||
resp.SensitiveTip = vidser.SensitiveForcedOfflineTip
|
||||
}
|
||||
|
||||
common.ServeJSON(ctx, stderr.Success, resp)
|
||||
}
|
||||
|
||||
func AddMedia(ctx context.Context, data *proxy.MediaResp, manager string, terms []string) (*vidser.SensitiveHit, error) {
|
||||
now := time.Now()
|
||||
mediaResource, err := mediamod.GetListByLsjId(data.FileId)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("mediamod GetListByLsjId error:%+v", err)
|
||||
return nil, err
|
||||
}
|
||||
if !mediaResource.ID.IsZero() {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
tag, err := mediatagmod.FindOneTagOrInset(data.FirstTag)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
media := mediamod.Media{
|
||||
ID: primitive.NewObjectID(),
|
||||
LsjId: data.FileId,
|
||||
SortCode: 0,
|
||||
Status: 1,
|
||||
Title: data.Title,
|
||||
HorizontalCover: data.CoverImg,
|
||||
VerticalCover: "",
|
||||
Tags: []primitive.ObjectID{tag.ID},
|
||||
TagDetails: nil,
|
||||
Summary: data.Desc,
|
||||
TotalEpisode: 1,
|
||||
CurrentEpisode: 1,
|
||||
FreeEpisode: 0,
|
||||
UpdateStatus: 2,
|
||||
MediaType: "video",
|
||||
MediaSubType: 0,
|
||||
Kind: 0,
|
||||
PermissionIconHide: false,
|
||||
Permission: 0,
|
||||
Style: 0,
|
||||
Price: 100,
|
||||
ContentsPrice: 0,
|
||||
Direction: 0,
|
||||
FreeTime: 30,
|
||||
DefaultContent: mediamod.DefaultContent{},
|
||||
MID: primitive.NilObjectID,
|
||||
ModuleName: "",
|
||||
SectionName: "",
|
||||
SID: primitive.NilObjectID,
|
||||
SectionSort: 0,
|
||||
Choice: primitive.NilObjectID,
|
||||
ChoiceSort: 0,
|
||||
CountComment: 0,
|
||||
CountPurchases: 0,
|
||||
CountContentPurchases: 0,
|
||||
CountBrowse: 0,
|
||||
CountCollect: 0,
|
||||
CountLike: 0,
|
||||
CountDisLike: 0,
|
||||
HasFollow: false,
|
||||
CountView: 0,
|
||||
Hot: 0,
|
||||
Number: 0,
|
||||
Anchor: data.Studio,
|
||||
CountPurchasesRate: 0,
|
||||
IsDelete: false,
|
||||
UpdatedAct: "",
|
||||
CreatedAt: now,
|
||||
UpdateTime: time.Now(),
|
||||
//ContentUpdateTime: time.Time{},
|
||||
MediaCenterId: 0,
|
||||
SyncTime: 0,
|
||||
}
|
||||
if data.CoverType == 1 {
|
||||
media.VerticalCover = data.CoverImg
|
||||
}
|
||||
|
||||
// 创建子集
|
||||
mediaContent := mediacontentmod.MediaContent{
|
||||
ID: primitive.ObjectID{},
|
||||
MediaID: media.ID,
|
||||
MediaType: "video",
|
||||
EpisodeNumber: 1,
|
||||
ListenPermission: 0,
|
||||
Cover: data.CoverImg,
|
||||
Price: 100,
|
||||
Name: data.Title,
|
||||
Text: "",
|
||||
Md5: "",
|
||||
AudioUrl: "",
|
||||
Author: "",
|
||||
VideoUrl: strings.TrimSpace(data.FieldNameFs) + ".m3u8",
|
||||
UrlSet: nil,
|
||||
Height: 0,
|
||||
Weight: 0,
|
||||
MediaSize: data.Size,
|
||||
PlayTime: uint(data.VideoTime),
|
||||
Status: 1,
|
||||
IsActive: true,
|
||||
CountComment: 0,
|
||||
CountPurchases: 0,
|
||||
CountBrowse: 0,
|
||||
FakeCountBrowse: 0,
|
||||
CountCollect: 0,
|
||||
CountLike: 0,
|
||||
CountDisLike: 0,
|
||||
Ratio: 0,
|
||||
IsDelete: false,
|
||||
UpdatedAct: "",
|
||||
CreatedAt: time.Now(),
|
||||
HashId: data.FileId,
|
||||
}
|
||||
|
||||
// 敏感词命中 → 强制下架(Status=0)
|
||||
hit := vidser.CheckTextHits(terms, data.FileId, media.Title, media.Summary, "")
|
||||
if hit != nil {
|
||||
media.Status = 0
|
||||
log.Warn("tianyu AddMedia sensitive hit, forced offline",
|
||||
log.Any("sourceId", hit.SourceID),
|
||||
log.Any("title", hit.Title),
|
||||
log.Any("detail", hit.Detail))
|
||||
}
|
||||
// 不处理标签
|
||||
_, err = mediamod.Insert(nil, media)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err = mediacontentmod.Insert(nil, mediaContent); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return hit, nil
|
||||
}
|
||||
|
||||
func AddVideo(ctx context.Context, data *proxy.MediaResp, manager string, terms []string) (*vidser.SensitiveHit, error) {
|
||||
now := time.Now()
|
||||
postList, err := vidmod.GetList(bson.M{"sourceID": bson.M{"$in": []string{data.FileId}}})
|
||||
if err != nil {
|
||||
log.Warn("syncOneMovie GetList failed", log.Any("id", data.FileId), log.E(err))
|
||||
return nil, err
|
||||
}
|
||||
if postList != nil && len(postList) > 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
upUsers, err := usermod.FindMany(bson.M{"uid": bson.M{"$gt": 300000}}, &options.FindOptions{}, 0, 300)
|
||||
if err != nil {
|
||||
log.Warn("PostAddList FindManyUser failed", log.E(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vidInfo := vidmod.VideoModel{
|
||||
ID: primitive.NewObjectID(),
|
||||
Title: data.Title,
|
||||
Content: data.Desc,
|
||||
Tags: make([]primitive.ObjectID, 0),
|
||||
MimeType: "video/mp4",
|
||||
SeriesCover: make([]string, 0),
|
||||
Via: "tianyu",
|
||||
Status: vidmod.CheckPass,
|
||||
Location: primitive.ObjectID{},
|
||||
Actor: strings.Join(data.Actors, " "),
|
||||
NewUpdatedAt: "tianyu",
|
||||
ReviewAt: now,
|
||||
CreatedAt: now,
|
||||
Cover: data.CoverImg,
|
||||
ReviewAccount: manager,
|
||||
}
|
||||
if data.CoverType == 1 {
|
||||
vidInfo.VerticalCover = data.CoverImg
|
||||
}
|
||||
|
||||
if data.CoverType == 1 {
|
||||
vidInfo.NewsType = vidmod.SHORT
|
||||
vidInfo.Cover = data.CoverImg
|
||||
vidInfo.CoverThumb = data.CoverImg
|
||||
vidInfo.Direction = "vertical"
|
||||
} else {
|
||||
vidInfo.NewsType = vidmod.SP
|
||||
vidInfo.Cover = data.CoverImg
|
||||
vidInfo.CoverThumb = data.CoverImg
|
||||
vidInfo.Direction = "horizontal"
|
||||
}
|
||||
|
||||
vidInfo.PlayTime = uint(data.VideoTime)
|
||||
uIndex := rand.Intn(len(upUsers))
|
||||
u := upUsers[uIndex]
|
||||
vidInfo.PublisherID = u.UID
|
||||
|
||||
vidInfo.SourceURL = data.FieldNameFs
|
||||
vidInfo.PreviewURL = data.PreFileName
|
||||
vidInfo.SourceID = data.FileId
|
||||
vidInfo.Filename = data.FieldNameFs
|
||||
|
||||
if !strings.Contains(data.PreFileName, ".m3u8") {
|
||||
vidInfo.SourceURL = strings.TrimSpace(data.PreFileName) + ".m3u8"
|
||||
}
|
||||
|
||||
if !strings.Contains(data.FieldNameFs, ".m3u8") {
|
||||
vidInfo.SourceURL = strings.TrimSpace(data.FieldNameFs) + ".m3u8"
|
||||
}
|
||||
|
||||
// 敏感词命中 → 强制为待审核(WaitingCheck=0)
|
||||
hit := vidser.CheckTextHits(terms, data.FileId, vidInfo.Title, vidInfo.Content, "")
|
||||
if hit != nil {
|
||||
vidInfo.Status = vidmod.WaitingCheck
|
||||
log.Warn("tianyu AddVideo sensitive hit, forced offline",
|
||||
log.Any("sourceId", hit.SourceID),
|
||||
log.Any("title", hit.Title),
|
||||
log.Any("detail", hit.Detail))
|
||||
}
|
||||
// 不处理标签
|
||||
if _, err = vidmod.InsertBase(vidInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return hit, nil
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package tianyuctrl
|
||||
|
||||
import "91porn-server/web/service/vidser"
|
||||
|
||||
type MediaAdd struct {
|
||||
FileId []string `json:"fileId" bson:"fileId,required"` // 媒资库ID
|
||||
}
|
||||
|
||||
type MediaAddResp struct {
|
||||
SuccessCount int `json:"successCount"`
|
||||
FailCount int `json:"failCount"`
|
||||
SensitiveHits []vidser.SensitiveHit `json:"sensitiveHits"` // 命中敏感词被强制下架的记录
|
||||
SensitiveTip string `json:"sensitiveTip,omitempty"` // 命中提示文案;无命中时为空
|
||||
}
|
||||
@@ -0,0 +1,382 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"91porn-server/common/log"
|
||||
"91porn-server/web/api/tianyuctrl/http"
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
apiDomain = BucketVideoAddressV2 + "/file/upload"
|
||||
imgDomain = BucketImageAddressV2 + "/file/upload"
|
||||
)
|
||||
|
||||
var (
|
||||
header = map[string]string{"Content-Type": "application/json"}
|
||||
)
|
||||
|
||||
const (
|
||||
Success = 200
|
||||
)
|
||||
|
||||
func UploadImg(fileName string, data []byte, domain string) (pathStr string, err error) {
|
||||
r := objreq{
|
||||
Name: fileName,
|
||||
Data: base64.StdEncoding.EncodeToString(data),
|
||||
}
|
||||
jsonbytes, err := json.Marshal(r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(domain) == 0 {
|
||||
domain = imgDomain
|
||||
}
|
||||
url := domain
|
||||
if !strings.Contains(domain, "/file/upload") {
|
||||
url = domain + "/file/upload"
|
||||
}
|
||||
resp, err := http.Post(url, header, bytes.NewReader(jsonbytes))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var or objresp
|
||||
if err = json.Unmarshal(resp.Data, &or); err != nil {
|
||||
return
|
||||
}
|
||||
if or.Code != Success {
|
||||
err = fmt.Errorf("上传失败:%s", or.Msg)
|
||||
return
|
||||
}
|
||||
pathStr = or.Object.Name
|
||||
return
|
||||
}
|
||||
|
||||
func UploadBase64Img(fileName string, data string, domain string) (pathStr string, err error) {
|
||||
r := objreq{
|
||||
Name: fileName,
|
||||
Data: data,
|
||||
}
|
||||
jsonbytes, err := json.Marshal(r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(domain) == 0 {
|
||||
domain = apiDomain
|
||||
}
|
||||
url := domain
|
||||
if !strings.Contains(domain, "/file/upload") {
|
||||
url = domain + "/file/upload"
|
||||
}
|
||||
resp, err := http.Post(url, header, bytes.NewReader(jsonbytes))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var or objresp
|
||||
if err = json.Unmarshal(resp.Data, &or); err != nil {
|
||||
return
|
||||
}
|
||||
if or.Code != Success {
|
||||
err = fmt.Errorf("上传失败:%s", or.Msg)
|
||||
return
|
||||
}
|
||||
pathStr = or.Object.Name
|
||||
return
|
||||
}
|
||||
|
||||
func fileServer() (url string) {
|
||||
return BucketVideoAddressV2
|
||||
}
|
||||
|
||||
func PostOk(baseInfo *ShardOk, domain string) (result *VideoOkResult, err error) {
|
||||
result = &VideoOkResult{}
|
||||
paramJson, err := json.Marshal(baseInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(domain) == 0 {
|
||||
domain = fileServer()
|
||||
}
|
||||
url := domain
|
||||
if !strings.Contains(domain, "/file/web/proxy/videoOk") {
|
||||
url = domain + "/file/web/proxy/videoOk"
|
||||
}
|
||||
fmt.Println(paramJson)
|
||||
fr, err := http.Post(url, header, bytes.NewReader(paramJson))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err = json.Unmarshal(fr.Data, result); err != nil {
|
||||
fmt.Println(result)
|
||||
return nil, err
|
||||
}
|
||||
fmt.Println(result)
|
||||
return
|
||||
}
|
||||
func PostOkV2(baseInfo *ShardOk, domain string) (result *VideoOkResult, err error) {
|
||||
result = &VideoOkResult{}
|
||||
paramJson, err := json.Marshal(baseInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(domain) == 0 {
|
||||
domain = fileServer()
|
||||
}
|
||||
url := domain
|
||||
if !strings.Contains(domain, "/file/web/proxy/videoOkv2") {
|
||||
url = domain + "/file/web/proxy/videoOkv2"
|
||||
}
|
||||
fmt.Println(paramJson)
|
||||
fr, err := http.Post(url, header, bytes.NewReader(paramJson))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err = json.Unmarshal(fr.Data, result); err != nil {
|
||||
fmt.Println(result)
|
||||
return nil, err
|
||||
}
|
||||
fmt.Println(result)
|
||||
return
|
||||
}
|
||||
func QueryMedia(baseInfo *MediaQueryeReq, domain string) (result *VideoQueryResult, err error) {
|
||||
result = &VideoQueryResult{}
|
||||
paramJson, err := json.Marshal(baseInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(domain) == 0 {
|
||||
domain = fileServer()
|
||||
}
|
||||
url := domain
|
||||
if !strings.Contains(domain, "/file/web/media/query") {
|
||||
url = domain + "/file/web/media/query"
|
||||
}
|
||||
fr, err := http.Post(url, header, bytes.NewReader(paramJson))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err = json.Unmarshal(fr.Data, result); err != nil {
|
||||
fmt.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func QueryMedias(baseInfo *MediaQueryesReq, domain string) (result *VideoQuerysResult, err error) {
|
||||
result = &VideoQuerysResult{
|
||||
Data: make([]MediaResp, 0),
|
||||
}
|
||||
paramJson, err := json.Marshal(baseInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(domain) == 0 {
|
||||
domain = fileServer()
|
||||
}
|
||||
url := domain
|
||||
if !strings.Contains(domain, "/file/web/media/querys") {
|
||||
url = domain + "/file/web/media/querys"
|
||||
}
|
||||
fr, err := http.Post(url, header, bytes.NewReader(paramJson))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err = json.Unmarshal(fr.Data, result); err != nil {
|
||||
fmt.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
func SyncMedia(baseInfo *MediaSyncReq, domain string) (result *VideoSyncResult, err error) {
|
||||
result = &VideoSyncResult{}
|
||||
paramJson, err := json.Marshal(baseInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(domain) == 0 {
|
||||
domain = fileServer()
|
||||
}
|
||||
url := domain
|
||||
if !strings.Contains(domain, "/file/web/media/search") {
|
||||
url = domain + "/file/web/media/search"
|
||||
}
|
||||
fr, err := http.Post(url, header, bytes.NewReader(paramJson))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err = json.Unmarshal(fr.Data, result); err != nil {
|
||||
fmt.Println(err, string(fr.Data))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func UploadVideo(domain string, body *ShardBody) (result *Result, err error) {
|
||||
if body == nil {
|
||||
return nil, errors.New("no video to upload")
|
||||
}
|
||||
if len(domain) == 0 {
|
||||
domain = fileServer()
|
||||
}
|
||||
url := domain
|
||||
if !strings.Contains(domain, "/file/web/proxy/videoBody") {
|
||||
url = domain + "/file/web/proxy/videoBody"
|
||||
}
|
||||
fmt.Println(url)
|
||||
|
||||
buf, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := http.Post(url, header, bytes.NewBuffer(buf))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Println("resp-->", string(resp.Data))
|
||||
result = new(Result)
|
||||
if err = json.Unmarshal(resp.Data, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
func PostSearch(param *MediaSearchReq, domain string) (result *MediaSearchResult, err error) {
|
||||
result = &MediaSearchResult{}
|
||||
paramJson, err := json.Marshal(param)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(domain) == 0 {
|
||||
domain = fileServer()
|
||||
}
|
||||
url := domain
|
||||
if !strings.Contains(domain, "/file/web/media/search") {
|
||||
url = domain + "/file/web/media/search"
|
||||
}
|
||||
fr, err := http.Post(url, header, bytes.NewReader(paramJson))
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("ty media search err:%v", err))
|
||||
return
|
||||
}
|
||||
if fr.StatusCode != 200 {
|
||||
log.Error(fmt.Sprintf("ty media search fr.StatusCode:%v", fr.StatusCode))
|
||||
return
|
||||
}
|
||||
|
||||
if err = json.Unmarshal(fr.Data, result); err != nil {
|
||||
log.Error(fmt.Sprintf("ty json Unmarshal search err:%v", err))
|
||||
return nil, err
|
||||
}
|
||||
log.Info("proxy:test", log.Any("url", url), log.Any("result", result))
|
||||
return
|
||||
}
|
||||
|
||||
func PostUpdate(param *MediaUpdateReq, domain string) (result *MediaUpdateResult, err error) {
|
||||
result = &MediaUpdateResult{}
|
||||
paramJson, err := json.Marshal(param)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(domain) == 0 {
|
||||
domain = fileServer()
|
||||
}
|
||||
url := domain
|
||||
if !strings.Contains(domain, "/file/web/media/update") {
|
||||
url = domain + "/file/web/media/update"
|
||||
}
|
||||
fr, err := http.Post(url, header, bytes.NewReader(paramJson))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err = json.Unmarshal(fr.Data, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func PostDelete(param *MediaDelReq, domain string) (result *MediaDelResult, err error) {
|
||||
result = &MediaDelResult{}
|
||||
paramJson, err := json.Marshal(param)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(domain) == 0 {
|
||||
domain = fileServer()
|
||||
}
|
||||
url := domain
|
||||
if !strings.Contains(domain, "/file/web/media/delete") {
|
||||
url = domain + "/file/web/media/delete"
|
||||
}
|
||||
fr, err := http.Post(url, header, bytes.NewReader(paramJson))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err = json.Unmarshal(fr.Data, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func PostUpdatePreTime(param *MediaUpdatePreTime, domain string) (result *MediaDelResult, err error) {
|
||||
result = &MediaDelResult{}
|
||||
paramJson, err := json.Marshal(param)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(domain) == 0 {
|
||||
domain = fileServer()
|
||||
}
|
||||
url := domain
|
||||
if !strings.Contains(domain, "/file/web/media/update/prefile") {
|
||||
url = domain + "/file/web/media/update/prefile"
|
||||
}
|
||||
fr, err := http.Post(url, header, bytes.NewReader(paramJson))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err = json.Unmarshal(fr.Data, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func UploadVideoV2(domain string, body *ShardBodyV2) (result *Result, err error) {
|
||||
if body == nil {
|
||||
return nil, errors.New("no video to upload")
|
||||
}
|
||||
if len(domain) == 0 {
|
||||
domain = fileServer()
|
||||
}
|
||||
url := domain
|
||||
if !strings.Contains(domain, "/file/web/proxy/videoBodyV2") {
|
||||
url = domain + "/file/web/proxy/videoBodyV2"
|
||||
}
|
||||
fmt.Println(url)
|
||||
|
||||
buf, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := http.Post(url, header, bytes.NewBuffer(buf))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Println("resp-->", string(resp.Data))
|
||||
result = new(Result)
|
||||
if err = json.Unmarshal(resp.Data, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Println("result-->", result)
|
||||
if result.Code != 200 {
|
||||
err = fmt.Errorf("result code err")
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package proxy
|
||||
@@ -0,0 +1,351 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
type objreq struct {
|
||||
Name string `json:"fileName"`
|
||||
Data string `json:"fileData"`
|
||||
}
|
||||
|
||||
type Obj struct {
|
||||
Domain string `json:"domain"`
|
||||
Name string `json:"fileName"`
|
||||
}
|
||||
|
||||
type objresp struct {
|
||||
Code int `json:"code"`
|
||||
Object Obj `json:"data"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
|
||||
type ShardBody struct {
|
||||
TaskId string `json:"taskId,omitempty"` // 文档md5
|
||||
Pos int `json:"pos,omitempty"` // 位置
|
||||
FileData string `json:"fileData,omitempty"` // 数据
|
||||
Type string `json:"type,omitempty"`
|
||||
TotalPos int `json:"totalPos,omitempty"` // 分片总数
|
||||
}
|
||||
|
||||
type ShardBodyV2 struct {
|
||||
TaskId string `json:"taskId,omitempty"` // 文档md5
|
||||
Pos int `json:"pos,omitempty"` // 位置
|
||||
FileData string `json:"fileData,omitempty"` // 数据
|
||||
Type string `json:"type,omitempty"`
|
||||
TotalPos int `json:"totalPos,omitempty"`
|
||||
FileName string `json:"fileName,omitempty"`
|
||||
Publish string `json:"publish,omitempty"`
|
||||
AppId int `json:"appId,omitempty"`
|
||||
MP4Folder string `json:"mp4Folder"` // 保存mp4的文件夹名,为空表示不需要保存mp4
|
||||
}
|
||||
|
||||
type Data struct {
|
||||
Id string `json:"id,omitempty"`
|
||||
VideoUri string `json:"videoUri,omitempty"`
|
||||
}
|
||||
|
||||
type Result struct {
|
||||
Code int `json:"code,omitempty"` //
|
||||
Data Data `json:"data,omitempty"` //
|
||||
Msg string `json:"msg,omitempty"` //
|
||||
}
|
||||
|
||||
type VideoOkResult struct {
|
||||
Code int `json:"code,omitempty"`
|
||||
Msg string `json:"msg,omitempty"` //
|
||||
Data string `json:"data,omitempty"`
|
||||
}
|
||||
type ShardOk struct {
|
||||
TaskId string `json:"taskId,omitempty"` // 文档md5
|
||||
Id string `json:"id,omitempty"` // Id
|
||||
Title *string `json:"title,omitempty"` // 标题
|
||||
CoverImg *string `json:"coverImg,omitempty"` // 封面
|
||||
}
|
||||
|
||||
type MediaQueryeReq struct {
|
||||
Id string `json:"id"`
|
||||
TaskId string `json:"taskId"`
|
||||
}
|
||||
type MediaQueryesReq struct {
|
||||
Ids []string `json:"ids"`
|
||||
}
|
||||
type VideoQueryResult struct {
|
||||
Code int `json:"code,omitempty"`
|
||||
Msg string `json:"msg,omitempty"` //
|
||||
Data MediaResp `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
type VideoQuerysResult struct {
|
||||
Code int `json:"code,omitempty"`
|
||||
Msg string `json:"msg,omitempty"` //
|
||||
Data []MediaResp `json:"data,omitempty"`
|
||||
}
|
||||
type MediaSyncReq struct {
|
||||
PageNum int64 `json:"pageNum"`
|
||||
PageSize int64 `json:"pageSize"`
|
||||
Param *SyncParam `json:"param"`
|
||||
}
|
||||
type SyncParam struct {
|
||||
Status string `json:"status,omitempty"` // 当前状态
|
||||
FirstTag string `json:"firstTag,omitempty"` // 一级标签
|
||||
Publish string `json:"publish,omitempty"` // 视频发布者
|
||||
// SecondTags string `json:"secondTags,omitempty"` // 二级标签标签
|
||||
}
|
||||
type VideoSyncResult struct {
|
||||
Code int `json:"code,omitempty"`
|
||||
Msg string `json:"msg,omitempty"` //
|
||||
Data MediaSearchResp `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
// type MediaSearchResp struct {
|
||||
// Total int64 `json:"total"`
|
||||
// List []*MediaSync `json:"list"`
|
||||
// }
|
||||
|
||||
type MediaSync struct {
|
||||
ID string `json:"id" binding:"required"`
|
||||
FileId string `json:"fileId" bson:"fileId"` // 媒资库ID
|
||||
Title string `bson:"title" json:"title"` // 标题
|
||||
Publish string `json:"publish" bson:"publish"` // 视频发布者
|
||||
Type string `bson:"type" json:"type"` // 长视频/短视频
|
||||
Country string `bson:"country" json:"country"` // 国家 (国产、日本、欧美.... 前端固定)
|
||||
FirstTag string `bson:"firstTag" json:"firstTag"` // 一级标签
|
||||
SecondTags []string `bson:"secondTags" json:"secondTags"` // 二级标签标签
|
||||
CoverImg string `bson:"coverImg" json:"coverImg"` // 封面
|
||||
PreFileName string `bson:"preFileName" json:"preFileName"` // 预览文件
|
||||
Desc string `bson:"desc" json:"desc"` // 详细描述
|
||||
Size int64 `bson:"size" json:"size"` // 文件size,单位byte
|
||||
Bango string `bson:"bango" json:"bango"` // 番号,唯一
|
||||
Directors []string `bson:"directors" json:"directors"` // 导演
|
||||
Actors []string `bson:"actors" json:"actors"` // 演员
|
||||
Studio string `bson:"studio" json:"studio"` // 工作室/所有者
|
||||
AddedTime time.Time `bson:"addedTime" json:"addedTime"` // 上架时间
|
||||
VideoTime int64 `json:"videoTime" bson:"videoTime"` // 影片时长,单位秒
|
||||
OperatAt time.Time `json:"operatAt" bson:"operatAt"` // 编辑时间(排序时间)
|
||||
FieldNameFs string `bson:"fieldNameFs,omitempty" json:"fieldNameFs,omitempty"` // 文件名称
|
||||
Height int64 `json:"height" bson:"height"` // 分辨率高
|
||||
Width int64 `json:"width" bson:"width"` // 分辨率宽
|
||||
ProxyUpload int32 `bson:"proxyUpload,omitempty" json:"proxyUpload,omitempty"` // 代理上传 1:代理
|
||||
}
|
||||
|
||||
type MediaResp struct {
|
||||
FileId string `json:"id" bson:"_id"` // 媒资库ID
|
||||
SrcId int64 `bson:"srcId,omitempty" json:"srcId"` // 原始ID
|
||||
Title string `bson:"title" json:"title"` // 标题
|
||||
Type string `bson:"type" json:"type"` // 类型:3.AI
|
||||
Publish string `json:"publish" bson:"publish"` // 视频发布者
|
||||
ContentType int64 `bson:"contentType,omitempty" json:"contentType"` // 内容 1:日本 2:国产 3:动漫
|
||||
FormatType int64 `bson:"formatType,omitempty" json:"formatType"` // 视频格式:1:长视频 2:短视频 3:预览
|
||||
CoverType CoverType `bson:"coverType,omitempty" json:"coverType"` // 封面类型: 1:竖版封面 2:横版封面 3:系统设置
|
||||
Country string `bson:"country" json:"country"` // 国家 (国产、日本、欧美.... 前端固定)
|
||||
FirstTag string `bson:"firstTag" json:"firstTag"` // 一级标签
|
||||
SecondTags []string `bson:"secondTags" json:"secondTags"` // 二级标签标签
|
||||
CoverImg string `bson:"coverImg" json:"coverImg"` // 封面
|
||||
PreFileName string `bson:"preFileName" json:"preFileName"` // 预览文件
|
||||
Status string `bson:"status" json:"status"` // 当前状态
|
||||
Desc string `bson:"desc" json:"desc"` // 详细描述
|
||||
MediaSet []string `bson:"mediaSet,omitempty" json:"mediaSet"` // 视频归属系列(连续剧、番剧)
|
||||
Size int64 `bson:"size" json:"size"` // 文件size,单位byte
|
||||
Bango string `bson:"bango" json:"bango"` // 番号,唯一
|
||||
Actors []string `bson:"actors" json:"actors"` // 演员
|
||||
JapanNames []string `json:"japanNames"` // 演员日本名称
|
||||
Studio string `bson:"studio" json:"studio"` // 工作室/所有者
|
||||
AddedTime time.Time `bson:"addedTime" json:"addedTime"` // 上架时间
|
||||
VideoTime int64 `json:"videoTime" bson:"videoTime"` // 影片时长,单位秒
|
||||
OperatAt time.Time `json:"operatAt" bson:"operatAt"` // 编辑时间(排序时间)
|
||||
FieldNameFs string `bson:"fieldNameFs,omitempty" json:"fieldNameFs,omitempty"` // 文件名称
|
||||
Height int64 `json:"height" bson:"height"` // 分辨率高
|
||||
Width int64 `json:"width" bson:"width"` // 分辨率宽
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 更新时间
|
||||
MP4FileName string `json:"mp4FileName" bson:"mp4FileName"`
|
||||
}
|
||||
|
||||
type MediaType int
|
||||
|
||||
const (
|
||||
ContentAv MediaType = 1 // 日本
|
||||
ContentChina MediaType = 2 // 国产
|
||||
ContentCartoon MediaType = 3 // 动漫
|
||||
)
|
||||
|
||||
type CoverType int
|
||||
|
||||
const (
|
||||
CoverHorizontal CoverType = 1 // 竖版封面
|
||||
CoverVertical CoverType = 2 // 横版封面
|
||||
CoverSystem CoverType = 3 // 系统设置封面
|
||||
)
|
||||
|
||||
type FailReason string
|
||||
|
||||
const (
|
||||
FailReasonNone FailReason = ""
|
||||
FailReasonUploadTimeoutError FailReason = "UploadTimeoutError" // 上传超时
|
||||
FailReasonMergeError FailReason = "MergeError" // 合并错误
|
||||
FailReasonCompressError FailReason = "CompressError" // 压缩错误
|
||||
FailReasonSegmentError FailReason = "SegmentError" // 分片错误
|
||||
FailReasonLinodeError FailReason = "LinodeError" // Linode错误
|
||||
)
|
||||
|
||||
type BaseInfo struct {
|
||||
ID primitive.ObjectID `bson:"_id,omitempty" json:"id"`
|
||||
SrcId int64 `bson:"srcId,omitempty" json:"srcId"` // 原始ID
|
||||
Title string `bson:"title,omitempty" json:"title"` // 标题
|
||||
CheckSum string `bson:"checkSum,omitempty" json:"checkSum"` // md5校验码
|
||||
FormatType int64 `bson:"formatType,omitempty" json:"formatType"` // 视频格式:1:长视频 2:短视频 3:预览
|
||||
ContentType MediaType `bson:"contentType,omitempty" json:"contentType"` // 内容 1:日本 2:国产 3:动漫
|
||||
CoverType CoverType `bson:"coverType,omitempty" json:"coverType"` // 封面类型: 1:竖版封面 2:横版封面 3:系统设置
|
||||
CoverImg string `bson:"coverImg,omitempty" json:"coverImg"` // 封面
|
||||
CoverImgNew string `bson:"coverImgNew,omitempty" json:"coverImgNew"` // 封面(自动生成)
|
||||
VideoTime int32 `bson:"videoTime,omitempty" json:"videoTime"` // 影片长度
|
||||
Publish string `json:"publish,omitempty" bson:"publish"` // 视频发布者
|
||||
Type string `bson:"type,omitempty" json:"type"` // 类型:1.AV 2.SP 3.AI
|
||||
Country string `bson:"country,omitempty" json:"country"` // 国家 (国产、日本、欧美.... 前端固定)
|
||||
FirstTag string `bson:"firstTag,omitempty" json:"firstTag"` // 一级标签
|
||||
SecondTags []string `bson:"secondTags,omitempty" json:"secondTags"` // 二级标签标签
|
||||
MediaSet []string `bson:"mediaSet,omitempty" json:"mediaSet"` // 视频归属系列(连续剧、番剧)
|
||||
PreFileName string `bson:"preFileName,omitempty" json:"preFileName"` // 预览文件
|
||||
Status string `bson:"status,omitempty" json:"status"` // 当前状态
|
||||
Desc string `bson:"desc,omitempty" json:"desc"` // 详细描述
|
||||
Size int64 `bson:"size,omitempty" json:"size"` // 文件size,单位byte
|
||||
Bango string `bson:"bango,omitempty" json:"bango"` // 番号,唯一
|
||||
Actors []string `bson:"actors,omitempty" json:"actors"` // 演员
|
||||
Studio string `bson:"studio,omitempty" json:"studio"` // 工作室/所有者
|
||||
AddedTime time.Time `bson:"addedTime,omitempty" json:"addedTime"` // 上架时间
|
||||
AppIds []int64 `bson:"appids,omitempty" json:"appids,omitempty"` // 应用列表
|
||||
JapanNames []string `json:"japanNames"` // 演员日本名称
|
||||
|
||||
// 切片相关信息
|
||||
Filename string `bson:"filename,omitempty" json:"filename"` // 文件名称
|
||||
FieldNameFs string `bson:"fieldNameFs,omitempty" json:"fieldNameFs"` // 文件名称
|
||||
Ext string `bson:"ext,omitempty" json:"ext"` // 视频后缀
|
||||
TaskID string `bson:"taskId,omitempty" json:"taskId"` // 项目组传来的唯一标示
|
||||
Width int `bson:"width,omitempty" json:"width"` // 分辨率宽
|
||||
Height int `bson:"height,omitempty" json:"height"` // 分辨率高
|
||||
Ratio float64 `bson:"ratio,omitempty" json:"ratio"` // 宽高比
|
||||
FrameRate string `bson:"frameRate,omitempty" json:"frameRate"` // 视频贞数
|
||||
SyBitRate string `bson:"syBitRate,omitempty" json:"syBitRate"` // 音频bit率
|
||||
VidBitRate string `bson:"vidBitRate,omitempty" json:"vidBitRate"` // 视频bit率
|
||||
CreatedAt time.Time `bson:"createdAt,omitempty" json:"createdAt"` // 创建时间
|
||||
UpdatedAt time.Time `bson:"updatedAt,omitempty" json:"updatedAt"` // 更新时间
|
||||
ProxyUpload *int32 `bson:"proxyUpload,omitempty" json:"proxyUpload"` // 代理上传
|
||||
|
||||
IsAdd bool `bson:"isAdd,omitempty" json:"isAdd"` // 是否加入到本地
|
||||
Retry int `bson:"retry" json:"retry"` // 重试次数 默认为零 最大重试3次
|
||||
NotifySignal bool `bson:"notifySignal" json:"notifySignal"` //中止通知的信号 false 可以发送通知,true 中止发送通知
|
||||
ShowLocation int64 `bson:"showLocation" json:"showLocation"` // 显示位置
|
||||
|
||||
MergeRetry int `bson:"mergeRetry" json:"mergeRetry"` //合并重试次数
|
||||
CompressRetry int `bson:"compressRetry" json:"compressRetry"` //压缩重试次数
|
||||
SegmentRetry int `bson:"segmentRetry" json:"segmentRetry"` //切片重试次数
|
||||
LinodeRetry int `bson:"linodeRetry" json:"linodeRetry"` //上传linode重试次数
|
||||
FailReason FailReason `bson:"failReason" json:"failReason"` //失败原因
|
||||
DeleteDisk bool `bson:"deleteDisk" json:"deleteDisk"` //是否删除了对于磁盘文件
|
||||
InfoTsName string `bson:"infoTsName" json:"infoTsName"` //从该ts中获取视频分辨率等信息
|
||||
Remark string `bson:"remark,omitempty" json:"remark"` // 备注
|
||||
}
|
||||
|
||||
type MediaUpdate struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Title *string `bson:"title,omitempty" json:"title,omitempty"` // 标题
|
||||
AddedTime *time.Time `bson:"addedTime,omitempty" json:"addedTime,omitempty"` // 上架时间
|
||||
Publish string `json:"publish,omitempty" bson:"publish"` // 视频发布者(麻豆、adday)
|
||||
FormatType *int64 `bson:"formatType,omitempty" json:"formatType"` // 视频格式:1:长视频 2:短视频 3:预览
|
||||
FirstTag *string `bson:"firstTag,omitempty" json:"firstTag"` // 一级标签
|
||||
SecondTags *[]string `bson:"secondTags,omitempty" json:"secondTags"` // 二级标签标签
|
||||
MediaSet *[]string `bson:"mediaSet,omitempty" json:"mediaSet"` // 视频归属系列(连续剧、番剧)
|
||||
Bango *string `bson:"bango,omitempty" json:"bango,omitempty"` // 番号,唯一
|
||||
AppIds *[]int64 `bson:"appids,omitempty" json:"appids,omitempty"` // 应用列表
|
||||
Desc *string `bson:"desc,omitempty" json:"desc,omitempty"` // 详细描述
|
||||
PreFileName *string `bson:"preFileName,omitempty" json:"preFileName,omitempty"` // 预览文件
|
||||
CoverImg *string `bson:"coverImg,omitempty" json:"coverImg,omitempty"` // 封面
|
||||
ContentType *MediaType `bson:"contentType,omitempty" json:"contentType"` // 内容 1:AV(日本) 2:国产(短视频) 3:动漫
|
||||
Actors *[]string `bson:"actors,omitempty" json:"actors"` // 演员
|
||||
Studio *string `bson:"studio,omitempty" json:"studio"` // 工作室/所有者
|
||||
CoverType *CoverType `bson:"coverType,omitempty" json:"coverType"` // 封面类型 1:竖版 2:横版 3:系统
|
||||
CreatedAt *time.Time `bson:"createdAt,omitempty" json:"createdAt,omitempty"` // 创建时间
|
||||
UpdatedAt *time.Time `bson:"updatedAt,omitempty" json:"updatedAt,omitempty"` // 更新时间
|
||||
ShowLocation *int64 `bson:"showLocation,omitempty" json:"showLocation"` // 显示位置
|
||||
}
|
||||
|
||||
type VideoSearch struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Title *string `json:"title,omitempty"` // 标题
|
||||
TaskID *string `json:"taskId,omitempty"` // 项目组传来的唯一标示
|
||||
Publish *string `json:"publish,omitempty"` // 视频发布者
|
||||
FormatType *int64 `json:"formatType,omitempty"` // 视频格式:1:长视频 2:短视频 3:预览
|
||||
ContentType *MediaType `json:"contentType,omitempty"` // 内容
|
||||
CoverType *CoverType `json:"coverType,omitempty"` // 封面类型
|
||||
Appid *int64 `json:"appid"` // 应用ID
|
||||
AppIds *[]int64 `json:"appids"` // 应用IDs
|
||||
FirstTag *string `json:"firstTag,omitempty"` // 一级标签
|
||||
SecondTags *string `json:"secondTags,omitempty"` // 二级标签标签
|
||||
MediaSet *[]string `json:"mediaSet,omitempty"` // 视频归属系列(连续剧、番剧)
|
||||
Status *string `json:"status,omitempty"` // 当前状态
|
||||
Actors *string `json:"actors,omitempty"` // 演员
|
||||
Studio *string `json:"studio,omitempty"` // 工作室
|
||||
Bango *string `json:"bango,omitempty"` // 番号,唯一
|
||||
Remark *string `json:"remark,omitempty"` // 备注
|
||||
AddedTime *string `json:"addedTime,omitempty"` // 上架时间
|
||||
UploadTime *string `json:"uploadTime,omitempty"` // 上传时间
|
||||
Start *time.Time `json:"start"` // 开始时间
|
||||
End *time.Time `json:"end"` // 结束时间
|
||||
Type *string `json:"type,omitempty"` // SP,AV,AI,MP3
|
||||
ShowLocation *int64 `json:"showLocation"` // 显示位置
|
||||
}
|
||||
|
||||
type MediaSearchReq struct {
|
||||
PageNum int64 `json:"pageNum"`
|
||||
PageSize int64 `json:"pageSize"`
|
||||
Param *VideoSearch `json:"param"`
|
||||
}
|
||||
|
||||
// MediaSearchReq 媒体搜索请求返回
|
||||
type MediaSearchResp struct {
|
||||
Total int64 `json:"total"`
|
||||
List []*BaseInfo `json:"list"`
|
||||
}
|
||||
|
||||
type MediaSearchResult struct {
|
||||
Code int `json:"code,omitempty"`
|
||||
Msg string `json:"msg,omitempty"` //
|
||||
Data MediaSearchResp `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
type MediaDelReq struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
// MediasDelResp 请求批量删除媒体回复
|
||||
type MediaDelResp struct {
|
||||
}
|
||||
|
||||
type MediaUpdatePreTime struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
PreFileTime int64 `bson:"preFileTime,omitempty" json:"preFileTime"` // 预览文件(开始时间)
|
||||
}
|
||||
|
||||
type MediaDelResult struct {
|
||||
Code int `json:"code,omitempty"`
|
||||
Msg string `json:"msg,omitempty"` //
|
||||
// Data MediaDelResp `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
type MediaUpdateReq struct {
|
||||
//Ids []string `json:"id"`
|
||||
MediaUpdate
|
||||
}
|
||||
|
||||
// MediasUpdateResp 请求批量更新媒体回复
|
||||
type MediaUpdateResp struct {
|
||||
}
|
||||
|
||||
type MediaUpdateResult struct {
|
||||
Code int `json:"code,omitempty"`
|
||||
Msg string `json:"msg,omitempty"` //
|
||||
Data MediaUpdateResp `json:"data,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// 视频桶地址
|
||||
BucketVideoAddressV1 = "http://ts.bbaazz.me"
|
||||
BucketVideoAddressV2 = "http://tong3yuants.bbaazz.me"
|
||||
// 图片桶地址
|
||||
BucketImageAddressV1 = "http://img.bbaazz.me"
|
||||
BucketImageAddressV2 = "http://tong3yuanimg.bbaazz.me"
|
||||
|
||||
// 上传路径
|
||||
ImageUploadPathV1 = "/file/upload"
|
||||
ImageUploadPathV2 = "/file/upload" // "/file/web/media/uploadImg"
|
||||
VideoBodyPathV1 = "/file/web/proxy/videoBody"
|
||||
VideoBodyPathV2 = "/file/web/proxy/videoBodyV2"
|
||||
VideoOkPathV1 = "/file/web/proxy/videoOk"
|
||||
VideoOkPathV2 = "/file/web/proxy/videoOkv2"
|
||||
)
|
||||
|
||||
func DomainAddressRepair(domain string, defaultBucketAddress ...string) string {
|
||||
if domain == "" {
|
||||
if len(defaultBucketAddress) > 0 && defaultBucketAddress[0] != "" {
|
||||
domain = defaultBucketAddress[0]
|
||||
} else {
|
||||
domain = BucketVideoAddressV2
|
||||
}
|
||||
}
|
||||
return domain
|
||||
}
|
||||
|
||||
func ImageUploadAddressRepair(domain string, defaultBucketAddress ...string) string {
|
||||
domain = DomainAddressRepair(domain, defaultBucketAddress...)
|
||||
if !strings.Contains(domain, ImageUploadPathV1) && !strings.Contains(domain, ImageUploadPathV2) {
|
||||
if strings.HasPrefix(domain, BucketImageAddressV1) {
|
||||
return domain + ImageUploadPathV1
|
||||
} else if strings.HasPrefix(domain, BucketImageAddressV2) {
|
||||
return domain + ImageUploadPathV2
|
||||
}
|
||||
return domain + ImageUploadPathV2
|
||||
}
|
||||
return domain
|
||||
}
|
||||
|
||||
func VideoBodyAddressRepair(domain string, defaultBucketAddress ...string) string {
|
||||
domain = DomainAddressRepair(domain, defaultBucketAddress...)
|
||||
if strings.HasPrefix(domain, BucketVideoAddressV1) {
|
||||
if !strings.Contains(domain, VideoBodyPathV1) {
|
||||
return domain + VideoBodyPathV1
|
||||
}
|
||||
return domain
|
||||
} else if strings.HasPrefix(domain, BucketVideoAddressV2) {
|
||||
if !strings.Contains(domain, VideoBodyPathV2) {
|
||||
return domain + VideoBodyPathV2
|
||||
}
|
||||
return domain
|
||||
} else { // 未知存储桶,默认v2
|
||||
if !strings.Contains(domain, VideoBodyPathV2) {
|
||||
return domain + VideoBodyPathV2
|
||||
}
|
||||
return domain
|
||||
}
|
||||
}
|
||||
|
||||
func VideoOkAddressRepair(domain string, defaultBucketAddress ...string) string {
|
||||
domain = DomainAddressRepair(domain, defaultBucketAddress...)
|
||||
if strings.HasPrefix(domain, BucketVideoAddressV1) {
|
||||
if !strings.Contains(domain, VideoOkPathV1) {
|
||||
return domain + VideoOkPathV1
|
||||
}
|
||||
return domain
|
||||
} else if strings.HasPrefix(domain, BucketVideoAddressV2) {
|
||||
if !strings.Contains(domain, VideoOkPathV2) {
|
||||
return domain + VideoOkPathV2
|
||||
}
|
||||
return domain
|
||||
} else { // 未知存储桶,默认v2
|
||||
if !strings.Contains(domain, VideoOkPathV2) {
|
||||
return domain + VideoOkPathV2
|
||||
}
|
||||
return domain
|
||||
}
|
||||
}
|
||||
|
||||
func GetExistsUrlPathBucketAddress(path string) string {
|
||||
if strings.HasPrefix(path, "v1/") {
|
||||
return BucketVideoAddressV1
|
||||
} else if strings.HasPrefix(path, "v2/") {
|
||||
return BucketVideoAddressV2
|
||||
} else if strings.HasPrefix(path, "v3/") {
|
||||
return BucketVideoAddressV2
|
||||
} else {
|
||||
return BucketVideoAddressV1 // 欲漫涩、微博、快看禁漫 默认用桶2,其他的app,默认用桶1
|
||||
}
|
||||
}
|
||||
|
||||
func AppendV2PrefixToUrlPath(name string) string {
|
||||
if name != "" && !strings.HasPrefix(name, "v2/") && !strings.HasPrefix(name, "v1/") && !strings.HasPrefix(name, "v3/") &&
|
||||
!strings.HasPrefix(name, "/v2") && !strings.HasPrefix(name, "/v1") && !strings.HasPrefix(name, "/v3") {
|
||||
name = fmt.Sprintf("v2/%s", name)
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func AppendV1PrefixToUrlPath(name string) string {
|
||||
if name != "" && !strings.HasPrefix(name, "v2/") && !strings.HasPrefix(name, "v1/") && !strings.HasPrefix(name, "v3/") &&
|
||||
!strings.HasPrefix(name, "/v2") && !strings.HasPrefix(name, "/v1") && !strings.HasPrefix(name, "/v3") {
|
||||
name = fmt.Sprintf("v1/%s", name)
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func AppendsMediaS3Version(name string) string {
|
||||
if strings.Contains(name, "bktadminup") ||
|
||||
strings.Contains(name, "bktappupdata") ||
|
||||
strings.Contains(name, "k12") ||
|
||||
strings.Contains(name, "bktappup") {
|
||||
return ""
|
||||
}
|
||||
// 默认使用V1
|
||||
if name != "" && !strings.HasPrefix(name, "v2/") && !strings.HasPrefix(name, "v1/") && !strings.HasPrefix(name, "v3/") &&
|
||||
!strings.HasPrefix(name, "/v2") && !strings.HasPrefix(name, "/v1") && !strings.HasPrefix(name, "/v3") {
|
||||
return "/v2"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
Reference in New Issue
Block a user