bilibili-backup/app/admin/main/dm/service/subtitle.go
2019-04-22 02:59:20 +00:00

358 lines
10 KiB
Go

package service
import (
"context"
"fmt"
"sync"
"time"
"go-common/app/admin/main/dm/model"
accountApi "go-common/app/service/main/account/api"
"go-common/app/service/main/archive/api"
archiveMdl "go-common/app/service/main/archive/model/archive"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/sync/errgroup"
)
const (
_workFlowSubtitleBid = 14
)
// SubtitleLanList .
func (s *Service) SubtitleLanList(c context.Context) (res map[int64]string, err error) {
var (
sLans []*model.SubtitleLan
)
if sLans, err = s.dao.SubtitleLans(c); err != nil {
return
}
res = make(map[int64]string)
for _, sLan := range sLans {
res[sLan.Code] = sLan.DocZh
}
return
}
// WorkFlowEditSubtitle .
func (s *Service) WorkFlowEditSubtitle(c context.Context, arg *model.WorkFlowSubtitleArg) (err error) {
var (
argEdit *model.EditSubtitleArg
status model.SubtitleStatus
)
if arg == nil || arg.Object == nil || len(arg.Object.Ids) == 0 || len(arg.Targets) == 0 {
err = ecode.RequestErr
return
}
switch arg.Object.DisposeMode {
case model.WorkFlowSubtitleDisposeManagerBack:
status = model.SubtitleStatusManagerBack
case model.WorkFlowSubtitleDisposeManagerDelete:
status = model.SubtitleStatusManagerRemove
default:
return
}
for _, target := range arg.Targets {
if target == nil {
continue
}
argEdit = &model.EditSubtitleArg{
Oid: target.Oid,
SubtileID: target.Eid,
Status: uint8(status),
}
// 容错
if argEdit.Oid == 0 {
continue
}
if err = s.editSubtitle(c, argEdit, false); err != nil {
log.Error("s.EditSubtitle(arg:%+v),error(%v)", argEdit, err)
err = nil // ignore error
return
}
}
return
}
// EditSubtitle .
func (s *Service) EditSubtitle(c context.Context, arg *model.EditSubtitleArg) (err error) {
return s.editSubtitle(c, arg, true)
}
func (s *Service) editSubtitle(c context.Context, arg *model.EditSubtitleArg, removeWorkFlow bool) (err error) {
// 更新表
var (
subtitle *model.Subtitle
argStatus = model.SubtitleStatus(arg.Status)
subtitleLans model.SubtitleLans
sLans []*model.SubtitleLan
err1 error
lanDoc string
archiveInfo *api.Arc
archiveName string
)
if subtitle, err = s.dao.GetSubtitle(c, arg.Oid, arg.SubtileID); err != nil {
log.Error("params(oid:%v,subtitleID:%v),error(%v)", arg.Oid, arg.SubtileID, err)
return
}
if subtitle == nil {
err = ecode.NothingFound
return
}
if argStatus == subtitle.Status {
err = ecode.SubtitleStatusUnValid
return
}
if subtitle.Status != model.SubtitleStatusPublish && argStatus != model.SubtitleStatusPublish {
arg.NotifyUpper = false
}
switch argStatus {
case model.SubtitleStatusDraft, model.SubtitleStatusToAudit,
model.SubtitleStatusAuditBack, model.SubtitleStatusRemove,
model.SubtitleStatusPublish, model.SubtitleStatusManagerBack,
model.SubtitleStatusManagerRemove:
default:
err = ecode.SubtitleStatusUnValid
return
}
if err = s.changeSubtitleStatus(c, subtitle, argStatus); err != nil {
log.Error("params(subtitle:%+v,status:%v),error(%v)", subtitle, arg.Status, err)
return
}
if arg.NotifyAuthor || arg.NotifyUpper {
if sLans, err1 = s.dao.SubtitleLans(c); err1 == nil {
subtitleLans = model.SubtitleLans(sLans)
}
_, lanDoc = subtitleLans.GetByID(int64(subtitle.Lan))
if archiveInfo, err1 = s.arcRPC.Archive3(c, &archiveMdl.ArgAid2{
Aid: subtitle.Aid,
}); err1 != nil {
log.Error("s.arcRPC.Archive3(aid:%v),error(%v)", subtitle.Aid, err1)
err1 = nil
} else {
archiveName = archiveInfo.Title
}
}
if arg.NotifyAuthor {
argUser := &model.NotifySubtitleUser{
Mid: subtitle.Mid,
Aid: subtitle.Aid,
Oid: subtitle.Oid,
SubtitleID: subtitle.ID,
ArchiveName: archiveName,
LanDoc: lanDoc,
Status: model.StatusContent[uint8(subtitle.Status)],
}
if err1 = s.dao.SendMsgToSubtitleUser(c, argUser); err1 != nil {
log.Error("SendMsgToSubtitleUser(argUser:%+v),error(%v)", argUser, err1)
err1 = nil
}
}
if arg.NotifyUpper {
var (
accountInfo *accountApi.InfoReply
authorName string
)
if accountInfo, err1 = s.accountRPC.Info3(c, &accountApi.MidReq{
Mid: subtitle.Mid,
}); err1 != nil {
log.Error("s.accRPC.Info3(mid:%v),error(%v)", subtitle.Mid, err1)
err1 = nil
} else {
authorName = accountInfo.GetInfo().GetName()
}
argUp := &model.NotifySubtitleUp{
Mid: subtitle.UpMid,
AuthorID: subtitle.Mid,
AuthorName: authorName,
Aid: subtitle.Aid,
Oid: subtitle.Oid,
SubtitleID: subtitle.ID,
ArchiveName: archiveName,
LanDoc: lanDoc,
Status: model.StatusContent[uint8(subtitle.Status)],
}
if err1 = s.dao.SendMsgToSubtitleUp(c, argUp); err1 != nil {
log.Error("SendMsgToSubtitleUp(argUp:%+v),error(%v)", argUp, err1)
err1 = nil
}
}
if removeWorkFlow && (argStatus == model.SubtitleStatusRemove || argStatus == model.SubtitleStatusManagerRemove) {
if err1 := s.dao.WorkFlowAppealDelete(c, _workFlowSubtitleBid, subtitle.Oid, subtitle.ID); err1 != nil {
log.Error("s.dao.WorkFlowAppealDelete(oid:%v,subtitleID:%v),error(%v)", subtitle.Oid, subtitle.ID, err1)
return
}
}
return
}
// TODO 确认状态扭转
func (s *Service) changeSubtitleStatus(c context.Context, subtitle *model.Subtitle, status model.SubtitleStatus) (err error) {
var (
sc *model.SubtitleContext
hasDraft bool
)
sc = &model.SubtitleContext{}
sc.Build(subtitle.Status, status)
subtitle.PubTime = time.Now().Unix()
if sc.CheckHasDraft {
if hasDraft, err = s.CheckHasDraft(c, subtitle); err != nil {
log.Error("params(subtitle:%+v),error(%v)", subtitle, err)
return
}
if hasDraft {
err = ecode.SubtitleAlreadyHasDraft
return
}
subtitle.PubTime = 0
}
subtitle.Status = status
if sc.RebuildPub {
if err = s.RebuildSubtitle(c, subtitle); err != nil {
log.Error("RebuildSubtitle.params(subtitle:%+v),error(%v)", subtitle, err)
return
}
} else {
if err = s.dao.UpdateSubtitle(c, subtitle); err != nil {
log.Error("UpdateSubtitle.params(subtitle:%+v),error(%v)", subtitle, err)
return
}
}
if sc.DraftCache {
s.dao.DelSubtitleDraftCache(c, subtitle.Oid, subtitle.Type, subtitle.Mid, subtitle.Lan)
}
if sc.SubtitleCache {
s.dao.DelSubtitleCache(c, subtitle.Oid, subtitle.ID)
}
if sc.RebuildPub {
s.dao.DelVideoSubtitleCache(c, subtitle.Oid, subtitle.Type)
}
return
}
// SubtitleList .
func (s *Service) SubtitleList(c context.Context, arg *model.SubtitleArg) (res *model.SubtitleList, err error) {
var (
searchResult *model.SearchSubtitleResult
oidSubtitleIds map[int64][]int64
eg errgroup.Group
lock sync.Mutex
subtitleMap map[string]*model.Subtitle
searchSubtitles []*model.SearchSubtitle
searchSubtitle *model.SearchSubtitle
subtitle *model.Subtitle
ok bool
aids []int64
aidMap map[int64]struct{}
archives map[int64]*api.Arc
archive *api.Arc
archiveVideo *api.Page
subtitleLans model.SubtitleLans
searchArg *model.SubtitleSearchArg
)
if arg.Ps > 100 {
err = ecode.RequestErr
return
}
key := func(oid, subtitleID int64) string {
return fmt.Sprintf("%d_%d", oid, subtitleID)
}
if sLans, err1 := s.dao.SubtitleLans(c); err1 == nil {
subtitleLans = model.SubtitleLans(sLans)
}
lanCode := subtitleLans.GetByLan(arg.Lan)
searchArg = &model.SubtitleSearchArg{
Aid: arg.Aid,
Oid: arg.Oid,
Mid: arg.Mid,
UpperMid: arg.UpperMid,
Status: arg.Status,
Lan: uint8(lanCode),
Ps: arg.Ps,
Pn: arg.Pn,
}
if searchResult, err = s.dao.SearchSubtitle(c, searchArg); err != nil {
log.Error("params(arg:%+v).error(%v)", arg, err)
return
}
if searchResult == nil || len(searchResult.Result) == 0 {
err = ecode.NothingFound
return
}
oidSubtitleIds = make(map[int64][]int64)
subtitleMap = make(map[string]*model.Subtitle)
aidMap = make(map[int64]struct{})
for _, r := range searchResult.Result {
oidSubtitleIds[r.Oid] = append(oidSubtitleIds[r.Oid], r.ID)
}
for oid, subtitleIds := range oidSubtitleIds {
tempOid := oid
tempSubtitleIds := subtitleIds
eg.Go(func() (err error) {
var subtitles []*model.Subtitle
if subtitles, err = s.dao.GetSubtitles(context.Background(), tempOid, tempSubtitleIds); err != nil {
log.Error("params(oid:%v,subtitleIds:%+v).error(%v)", tempOid, tempSubtitleIds, err)
return
}
for _, subtitle := range subtitles {
lock.Lock()
aidMap[subtitle.Aid] = struct{}{}
subtitleMap[key(subtitle.Oid, subtitle.ID)] = subtitle
lock.Unlock()
}
return
})
}
if err = eg.Wait(); err != nil {
return
}
for aid := range aidMap {
aids = append(aids, aid)
}
if archives, err = s.arcRPC.Archives3(c, &archiveMdl.ArgAids2{
Aids: aids,
}); err != nil {
log.Error("prams(aid:%v),error(%v)", aids, err)
archives = make(map[int64]*api.Arc)
err = nil
}
searchSubtitles = make([]*model.SearchSubtitle, 0, len(searchResult.Result))
for _, r := range searchResult.Result {
if subtitle, ok = subtitleMap[key(r.Oid, r.ID)]; !ok {
continue
}
lan, lanDoc := subtitleLans.GetByID(int64(subtitle.Lan))
searchSubtitle = &model.SearchSubtitle{
ID: subtitle.ID,
Oid: subtitle.Oid,
Aid: subtitle.Aid,
AuthorID: subtitle.Mid,
Status: uint8(subtitle.Status),
Lan: lan,
LanDoc: lanDoc,
IsSign: subtitle.IsSign,
IsLock: subtitle.IsLock,
Mtime: subtitle.Mtime,
SubtitleURL: subtitle.SubtitleURL,
}
if archive, ok = archives[subtitle.Aid]; ok {
searchSubtitle.ArchiveName = archive.Title
}
if archiveVideo, err = s.arcRPC.Video3(c, &archiveMdl.ArgVideo2{
Aid: subtitle.Aid,
Cid: subtitle.Oid,
}); err != nil {
log.Error("params(aid:%v,oid:%v) error(%v)", subtitle.Aid, subtitle.Oid, err)
err = nil
} else {
searchSubtitle.VideoName = archiveVideo.Part
}
searchSubtitles = append(searchSubtitles, searchSubtitle)
}
res = &model.SubtitleList{
Page: searchResult.Page,
}
res.Subtitles = searchSubtitles
return
}