Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

View File

@@ -0,0 +1,101 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"archive_test.go",
"public_test.go",
],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//library/cache/redis:go_default_library",
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["public.go"],
importpath = "go-common/app/interface/main/creative/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/dao/account:go_default_library",
"//app/interface/main/creative/dao/activity:go_default_library",
"//app/interface/main/creative/dao/archive:go_default_library",
"//app/interface/main/creative/dao/article:go_default_library",
"//app/interface/main/creative/dao/creative:go_default_library",
"//app/interface/main/creative/dao/pay:go_default_library",
"//app/interface/main/creative/dao/subtitle:go_default_library",
"//app/interface/main/creative/dao/tag:go_default_library",
"//app/interface/main/creative/dao/up:go_default_library",
"//app/interface/main/creative/model/activity:go_default_library",
"//app/interface/main/creative/model/archive:go_default_library",
"//app/interface/main/creative/model/music:go_default_library",
"//app/interface/main/creative/model/newcomer:go_default_library",
"//app/interface/main/creative/model/tag:go_default_library",
"//app/service/main/account/model:go_default_library",
"//app/service/main/archive/model/archive:go_default_library",
"//library/log:go_default_library",
"//library/queue/databus:go_default_library",
"//library/sync/errgroup:go_default_library",
"//library/time:go_default_library",
"//library/xstr:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/interface/main/creative/service/academy:all-srcs",
"//app/interface/main/creative/service/account:all-srcs",
"//app/interface/main/creative/service/ad:all-srcs",
"//app/interface/main/creative/service/app:all-srcs",
"//app/interface/main/creative/service/appeal:all-srcs",
"//app/interface/main/creative/service/archive:all-srcs",
"//app/interface/main/creative/service/article:all-srcs",
"//app/interface/main/creative/service/assist:all-srcs",
"//app/interface/main/creative/service/danmu:all-srcs",
"//app/interface/main/creative/service/data:all-srcs",
"//app/interface/main/creative/service/dynamic:all-srcs",
"//app/interface/main/creative/service/elec:all-srcs",
"//app/interface/main/creative/service/faq:all-srcs",
"//app/interface/main/creative/service/feedback:all-srcs",
"//app/interface/main/creative/service/geetest:all-srcs",
"//app/interface/main/creative/service/growup:all-srcs",
"//app/interface/main/creative/service/medal:all-srcs",
"//app/interface/main/creative/service/music:all-srcs",
"//app/interface/main/creative/service/newcomer:all-srcs",
"//app/interface/main/creative/service/operation:all-srcs",
"//app/interface/main/creative/service/pay:all-srcs",
"//app/interface/main/creative/service/reply:all-srcs",
"//app/interface/main/creative/service/resource:all-srcs",
"//app/interface/main/creative/service/staff:all-srcs",
"//app/interface/main/creative/service/template:all-srcs",
"//app/interface/main/creative/service/up:all-srcs",
"//app/interface/main/creative/service/version:all-srcs",
"//app/interface/main/creative/service/watermark:all-srcs",
"//app/interface/main/creative/service/weeklyhonor:all-srcs",
"//app/interface/main/creative/service/whitelist:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,66 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/academy:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"academy.go",
"h5.go",
"service.go",
"skill.go",
],
importpath = "go-common/app/interface/main/creative/service/academy",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/dao/academy:go_default_library",
"//app/interface/main/creative/dao/archive:go_default_library",
"//app/interface/main/creative/dao/article:go_default_library",
"//app/interface/main/creative/dao/resource:go_default_library",
"//app/interface/main/creative/dao/tool:go_default_library",
"//app/interface/main/creative/model/academy:go_default_library",
"//app/interface/main/creative/model/newcomer:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//app/interface/openplatform/article/model:go_default_library",
"//app/service/main/archive/api:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/sync/errgroup:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,314 @@
package academy
import (
"context"
"time"
"go-common/app/interface/main/creative/model/academy"
"go-common/app/interface/openplatform/article/model"
"go-common/app/service/main/archive/api"
"go-common/library/log"
"go-common/library/sync/errgroup"
xtime "go-common/library/time"
"github.com/davecgh/go-spew/spew"
)
// TagList get all tag.
func (s *Service) TagList(c context.Context) (res map[string][]*academy.Tag, err error) {
res = s.TagsCache
return
}
// AddFeedBack add feedback.
func (s *Service) AddFeedBack(c context.Context, category, course, suggest string, mid int64) (id int64, err error) {
fb := &academy.FeedBack{
Category: category,
Course: course,
Suggest: suggest,
CTime: xtime.Time(time.Now().Unix()),
MTime: xtime.Time(time.Now().Unix()),
}
if id, err = s.aca.AddFeedBack(c, fb, mid); err != nil {
log.Error("s.aca.AddFeedBack error(%v)", err)
}
return
}
// ArchivesWithES get all archive by es.
func (s *Service) ArchivesWithES(c context.Context, aca *academy.EsParam) (res *academy.ArchiveList, err error) {
var sear *academy.SearchResult
res = &academy.ArchiveList{
Items: []*academy.ArchiveMeta{},
Page: &academy.ArchivePage{},
}
aca.TidsMap = s.filterTIDs(aca.Tid)
if sear, err = s.aca.ArchivesWithES(c, aca); err != nil {
log.Error("s.aca.ArchivesWithES sear(%+v)|param(%+v)|error(%v)", sear, aca, err)
return
}
if sear == nil || len(sear.Result) == 0 {
log.Error("s.aca.ArchivesWithES has no data sear(%+v)|param(%+v)|error(%v)", sear, aca, err)
return
}
res.Page.Total = sear.Page.Total
res.Page.Pn = sear.Page.Num
res.Page.Ps = sear.Page.Size
var searRes []*academy.EsArc
if aca.Keyword != "" { //搜索关键词红点
searRes = make([]*academy.EsArc, 0, len(sear.Result)/2)
for i := 0; i < len(sear.Result)-1; i += 2 {
sear.Result[i].Title = sear.Result[i+1].Title
searRes = append(searRes, sear.Result[i])
}
} else {
searRes = sear.Result
}
oids := make([]int64, 0, len(sear.Result))
aidTIDsMap := make(map[int64][]int64)
busAIDsMap := make(map[int][]int64)
busAidMap := make(map[int64]int)
highTitleMap := make(map[int64][]string)
for _, v := range searRes {
busAIDsMap[v.Business] = append(busAIDsMap[v.Business], v.OID)
oids = append(oids, v.OID)
aidTIDsMap[v.OID] = v.TID
busAidMap[v.OID] = v.Business
if aca.Keyword != "" { //搜索关键词红点
highTitleMap[v.OID] = v.Title
}
}
var (
g, _ = errgroup.WithContext(c)
tagInfo map[int64]map[string][]*academy.Tag
arcs map[int64]*api.Arc
arts map[int64]*model.Meta
st map[int64]*api.Stat
)
g.Go(func() error { //获取各种查询对象信息
switch aca.Business {
case academy.BusinessForAll: //查询所有
if ids, ok := busAIDsMap[academy.BusinessForArchive]; ok { //稿件
g.Go(func() error {
arcs, err = s.arc.Archives(c, ids, aca.IP)
if err != nil {
log.Error("s.arc.Archives oids(%+v)|business(%d)|error(%v)", ids, aca.Business, err)
return err
}
st, err = s.arc.Stats(c, ids, aca.IP)
if err != nil {
log.Error("s.arc.Stats oids(%+v)|business(%d)|error(%v)", ids, aca.Business, err)
}
return err
})
}
if ids, ok := busAIDsMap[academy.BusinessForArticle]; ok { //文章
g.Go(func() error {
arts, err = s.art.ArticleMetas(context.Background(), ids, aca.IP)
if err != nil {
log.Error("s.arc.ArticleMetas oids(%+v)|business(%d)|error(%v)", ids, aca.Business, err)
}
return err
})
}
case academy.BusinessForArchive: //稿件
arcs, err = s.arc.Archives(context.Background(), oids, aca.IP)
if err != nil {
log.Error("s.arc.Archives oids(%+v)|business(%d)|error(%v)", oids, aca.Business, err)
return err
}
st, err = s.arc.Stats(c, oids, aca.IP)
if err != nil {
log.Error("s.arc.Stats oids(%+v)|business(%d)|error(%v)", oids, aca.Business, err)
}
return err
case academy.BusinessForArticle: //文章
arts, err = s.art.ArticleMetas(context.Background(), oids, aca.IP)
if err != nil {
log.Error("s.arc.ArticleMetas oids(%+v)|business(%d)|error(%v)", oids, aca.Business, err)
}
return err
}
return nil
})
g.Go(func() error {
tagInfo, err = s.bindTags(c, aidTIDsMap)
return err
})
if g.Wait() != nil {
log.Error("s.aca.ArchivesWithES g.Wait() error(%v)", err)
return
}
items := make([]*academy.ArchiveMeta, 0, len(oids))
for _, oid := range oids {
a := &academy.ArchiveMeta{
OID: oid,
}
if v, ok := tagInfo[oid]; ok {
a.Tags = v
}
bs, ok := busAidMap[oid]
if !ok {
log.Error("s.aca.ArchivesWithES oid(%d) get invalid business", oid)
return
}
a.Business = bs
switch a.Business {
case academy.BusinessForArchive: //稿件
a = bindArchiveInfo(oid, arcs, a)
if t, ok := st[oid]; ok {
a.ArcStat = t
} else {
a.ArcStat = &api.Stat{}
}
case academy.BusinessForArticle: //文章
a = bindArticleInfo(oid, arts, a)
}
if aca.Keyword != "" {
if ht, ok := highTitleMap[oid]; ok && len(ht) > 0 {
a.HighLightTitle = ht[0]
}
}
items = append(items, a)
}
res.Items = items
return
}
func bindArchiveInfo(oid int64, arcs map[int64]*api.Arc, a *academy.ArchiveMeta) (res *academy.ArchiveMeta) {
if v, ok := arcs[oid]; ok {
a.Title = v.Title
a.State = v.State
a.Type = v.TypeName
a.Cover = v.Pic
a.UName = v.Author.Name
a.Face = v.Author.Face
a.MID = v.Author.Mid
a.Duration = v.Duration
a.Rights = v.Rights
}
res = a
return
}
func bindArticleInfo(oid int64, arts map[int64]*model.Meta, a *academy.ArchiveMeta) (res *academy.ArchiveMeta) {
if v, ok := arts[oid]; ok && v != nil {
a.Title = v.Title
a.State = v.State
a.MID = v.Author.Mid
a.Comment = v.Summary
if v.Category != nil {
a.Type = v.Category.Name
}
if len(v.ImageURLs) > 0 {
a.Cover = v.ImageURLs[0]
}
if v.Author != nil {
a.UName = v.Author.Name
a.Face = v.Author.Face
}
if v.Stats != nil {
a.ArtStat = v.Stats
} else {
a.ArtStat = &model.Stats{}
}
}
res = a
return
}
func (s *Service) bindTags(c context.Context, tidsMap map[int64][]int64) (res map[int64]map[string][]*academy.Tag, err error) {
res = make(map[int64]map[string][]*academy.Tag)
for oid, tids := range tidsMap {
tgs := s.getTagsByTIDs(tids)
if len(tgs) == 0 {
continue
}
oidTag := make(map[string][]*academy.Tag)
ctgs := make(map[int64][]*academy.Tag)
for _, tg := range tgs {
k := academy.TagClassMap(int(tg.Type))
if tg.Type == academy.Classify { //获取多个分类标签
ctgs[tg.ParentID] = append(ctgs[tg.ParentID], tg)
} else {
oidTag[k] = append(oidTag[k], tg)
}
}
for pid, tgs := range ctgs {
if p, ok := s.TagMapCache[pid]; ok {
tp := *p
tp.Children = tgs
oidTag[academy.TagClassMap(academy.Classify)] = append(oidTag[academy.TagClassMap(academy.Classify)], &tp)
}
}
res[oid] = oidTag
}
return
}
func (s *Service) filterTIDs(tids []int64) (res map[int][]int64) {
if len(tids) == 0 {
return
}
log.Info("s.filterTIDs origin tids(%+v)", tids)
res = make(map[int][]int64)
ochs := make([]int64, 0) //原始提交的二级标签
ops := make([]int64, 0) //原始提交的一级标签
qchs := make([]int64, 0) //通过一级标签查询出来的二级标签
for _, id := range tids {
t, ok := s.parentChildMapCache[id]
if !ok || t == nil {
continue
}
if t.Type == academy.Classify {
if t.ParentID != 0 { //原始提交的二级标签
ochs = append(ochs, id)
} else if t.ParentID == 0 && len(t.Children) > 0 { //通过一级标签查询出来的二级标签
for _, v := range t.Children {
qchs = append(qchs, v.ID)
}
} else if t.ParentID == 0 && len(t.Children) == 0 {
ops = append(ops, id)
}
} else {
res[int(t.Type)] = append(res[int(t.Type)], id)
}
}
if len(ochs) > 0 { //如果分类标签中提交了原始的二级标签则认为按该二级标签进行筛选,如果可以查询到二级标签认为筛选全部二级,否则一级参与查询.
res[academy.Classify] = ochs
} else if len(qchs) > 0 {
res[academy.Classify] = qchs
} else if len(ops) > 0 {
res[academy.Classify] = ops
}
log.Info("s.filterTIDs res(%s)", spew.Sdump(res))
return
}
func (s *Service) getTagsByTIDs(tids []int64) (res []*academy.Tag) {
res = make([]*academy.Tag, 0)
if len(tids) == 0 {
return
}
for _, tid := range tids {
tag, ok := s.TagMapCache[tid]
if !ok || tag == nil {
continue
}
res = append(res, tag)
}
return
}

View File

@@ -0,0 +1,561 @@
package academy
import (
"context"
"sort"
"strconv"
"time"
"go-common/app/interface/main/creative/dao/tool"
"go-common/app/interface/main/creative/model/academy"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/sync/errgroup"
"go-common/app/service/main/archive/api"
"github.com/davecgh/go-spew/spew"
)
// Tags get all h5 tags.
func (s *Service) Tags(c context.Context) (res []*academy.Tag) {
if v, ok := s.TagsCache[academy.TagClassMap(academy.H5)]; ok {
res = v
}
return
}
// Archives get all h5 archive.
func (s *Service) Archives(c context.Context, aca *academy.EsParam) (res *academy.ArchiveList, err error) {
tids, err := s.webTags(aca.Tid)
if err != nil {
return
}
aca.Tid = tids
res, err = s.ArchivesWithES(c, aca)
return
}
func (s *Service) webTags(tids []int64) (webTIDs []int64, err error) {
var (
lts []*academy.LinkTag
h5TIDs []int64
)
if len(tids) > 0 {
h5TIDs = tids
} else {
tgs := s.Tags(context.Background())
for _, v := range tgs {
h5TIDs = append(h5TIDs, v.ID)
}
}
lts, err = s.aca.LinkTags(context.Background(), h5TIDs)
if err != nil {
return
}
for _, v := range lts {
webTIDs = append(webTIDs, v.LinkID)
}
return
}
// RecommendV2 get recommend archive.
func (s *Service) RecommendV2(c context.Context, mid int64) (res []*academy.RecArcList, err error) {
mainIDMap := make(map[int64]struct{}) //主题课程aid map for rm dup
tgList, err := s.getRecTag(c, mid)
if err != nil {
return
}
log.Info("Recommend mid(%d)|tgList(%s)", mid, spew.Sdump(tgList))
s.setSeed() //init Seed.
res = make([]*academy.RecArcList, 0)
var (
g, _ = errgroup.WithContext(c)
hotItems []*academy.RecArchive
)
g.Go(func() error {
// get hot archives
hotItems, err = s.hotArchives(c)
if err != nil {
log.Error("Recommend s.hotArchives mid(%d)", mid)
return err
}
return nil
})
for _, t := range tgList {
if t == nil {
continue
}
pid, v := t.PID, t.TIDs
if pid == 0 { //主题课程
var ocid int64
if len(v) > 0 {
ocid = v[0]
}
rec := &academy.RecArcList{
TID: ocid,
Items: []*academy.RecArchive{},
}
tg, o := s.OccMapCache[ocid]
if !o || tg == nil {
log.Error("s.OccMapCache ocid(%d) not exist", ocid)
continue
}
rec.Name = tg.Name
items, themeCourseErr := s.themeCourse(c, v)
if themeCourseErr != nil {
return nil, themeCourseErr
}
for _, v := range items {
mainIDMap[v.OID] = struct{}{}
}
rec.Items = items
res = append(res, rec)
} else if tg, ok := s.TagMapCache[pid]; ok { //标签教程
rec := &academy.RecArcList{
TID: pid,
Name: tg.Name,
Items: []*academy.RecArchive{},
}
items, tagCourseErr := s.tagCourse(c, pid, v, mainIDMap)
if tagCourseErr != nil {
return nil, tagCourseErr
}
rec.Items = items
res = append(res, rec)
}
}
if g.Wait() != nil {
log.Error("Recommend s.hotArchives g.Wait() error(%v)", err)
return
}
// add host archives
hotRec := &academy.RecArcList{
TID: 0,
Name: "热门推荐",
Items: hotItems,
}
res = append(res, hotRec)
return
}
func (s *Service) tagCourse(c context.Context, pid int64, v []int64, aidMap map[int64]struct{}) (res []*academy.RecArchive, err error) {
res = make([]*academy.RecArchive, 0)
aca := &academy.EsParam{
Tid: v,
Pn: 1,
Ps: 10,
}
if s.Seed > 0 { //取材创意/视频制作/个人运营 每日0点请求搜索更换时间种子
aca.Seed = s.Seed
}
arcs, err := s.Archives(c, aca)
if err != nil {
log.Error("Recommend s.Archives EsParam(%+v)|error(%v)", aca, err)
return nil, err
}
if arcs == nil {
err = ecode.CreativeAcademyH5RecommendErr
return nil, err
}
var aids []int64
for _, i := range arcs.Items {
// ignore if exist in resource service
if _, exist := s.ResourceMapCache[i.OID]; exist {
continue
}
// ignore if exist in main topic
if _, exist := aidMap[i.OID]; exist {
continue
}
ra := &academy.RecArchive{
OID: i.OID,
MID: i.MID,
Cover: i.Cover,
Title: i.Title,
Business: i.Business,
Duration: i.Duration,
ArcStat: i.ArcStat,
ArtStat: i.ArtStat,
}
res = append(res, ra)
aids = append(aids, i.OID)
}
// add tags
tags, err := s.getTags(c, aids)
if err != nil {
log.Error("tagCourse s.getTags err(%v)", err)
return
}
s.setTags(res, tags)
return
}
func (s *Service) themeCourse(c context.Context, v []int64) (res []*academy.RecArchive, err error) {
res = make([]*academy.RecArchive, 0)
arcs, err := s.ThemeCourse(c, v, []int64{}, []int64{}, 1, 10, false)
if err != nil {
log.Error("Recommend s.ThemeCourse v(%+v)|error(%v)", v, err)
return nil, err
}
if arcs == nil {
err = ecode.CreativeAcademyH5RecommendErr
return nil, err
}
var aids []int64
for _, i := range arcs.Items {
// ignore if exist in resource service
if _, exist := s.ResourceMapCache[i.AID]; exist {
continue
}
ra := &academy.RecArchive{
OID: i.AID,
MID: i.MID,
Cover: i.Cover,
Title: i.Title,
Duration: i.Duration,
ArcStat: i.ArcStat,
Business: academy.BusinessForArchive,
}
res = append(res, ra)
aids = append(aids, i.AID)
}
// add tags
tags, err := s.getTags(c, aids)
if err != nil {
log.Error("themeCourse s.getTags err(%v)", err)
return
}
s.setTags(res, tags)
s.randomForMainCourse(res) //每日0点随机随机稿件列表
if len(s.RecommendArcs) > 0 {
res = s.RecommendArcs
}
return
}
func (s *Service) getRecTag(c context.Context, mid int64) (res []*academy.RecConf, err error) {
var tyID int64
if mid > 0 {
tyID, err = s.getFavType(c, mid) //获取推荐分区id
if err != nil {
log.Error("getFavType mid(%d)|error(%v)", mid, err)
} else {
log.Info("getFavType mid(%d)|tyID(%d)", mid, tyID)
}
}
if s.c == nil || s.c.AcaRecommend == nil {
log.Error("getRecTag get conf error mid(%d)", mid)
return
}
rec := s.c.AcaRecommend.Recommend
//按 主题课程-取材创意-视频制作-个人运营 排序
var rec1, rec2, rec3, rec4 *academy.RecConf
res = make([]*academy.RecConf, 0, 4)
//主题课程
if rec.Course != nil {
course := rec.Course
rec1 = &academy.RecConf{PID: course.ID}
if tyID != 0 {
if tool.ElementInSlice(tyID, course.Shoot.Val) { //如果最近投稿分区命中配置的分区,则设置当前一级分类下面的标签为最近投稿分区对应的二级标签目录
rec1.TIDs = course.Shoot.Key
} else if tool.ElementInSlice(tyID, course.Scene.Val) {
rec1.TIDs = course.Scene.Key
} else if tool.ElementInSlice(tyID, course.Edit.Val) {
rec1.TIDs = course.Edit.Key
} else if tool.ElementInSlice(tyID, course.Mmd.Val) {
rec1.TIDs = course.Mmd.Key
} else if tool.ElementInSlice(tyID, course.Sing.Val) {
rec1.TIDs = course.Sing.Key
} else if tool.ElementInSlice(tyID, course.Bang.Val) {
rec1.TIDs = course.Bang.Key
}
} else {
rec1.TIDs = course.Other.Key
}
res = append(res, rec1)
} else {
log.Error("getRecTag get cousre conf mid(%d)", mid)
}
//取材创意
if rec.Drawn != nil {
drawn := rec.Drawn
rec2 = &academy.RecConf{PID: drawn.ID}
if tyID != 0 {
if tool.ElementInSlice(tyID, drawn.MobilePlan.Val) { //如果最近投稿分区命中配置的分区,则设置当前一级分类下面的标签为最近投稿分区对应的二级标签目录
rec2.TIDs = drawn.MobilePlan.Key
} else if tool.ElementInSlice(tyID, drawn.ScreenPlan.Val) {
rec2.TIDs = drawn.ScreenPlan.Key
} else if tool.ElementInSlice(tyID, drawn.RecordPlan.Val) {
rec2.TIDs = drawn.RecordPlan.Key
}
} else {
rec2.TIDs = drawn.Other.Key
}
res = append(res, rec2)
} else {
log.Error("getRecTag get drawn conf mid(%d)", mid)
}
//视频制作
if rec.Video != nil {
video := rec.Video
rec3 = &academy.RecConf{PID: video.ID}
if tyID != 0 {
if tool.ElementInSlice(tyID, video.MobileMake.Val) { //如果最近投稿分区命中配置的分区,则设置当前一级分类下面的标签为最近投稿分区对应的二级标签目录
rec3.TIDs = video.MobileMake.Key
} else if tool.ElementInSlice(tyID, video.AudioEdit.Val) {
rec3.TIDs = video.AudioEdit.Key
} else if tool.ElementInSlice(tyID, video.EditCompose.Val) {
rec3.TIDs = video.EditCompose.Key
}
} else {
rec3.TIDs = video.Other.Key
}
res = append(res, rec3)
} else {
log.Error("getRecTag get video conf mid(%d)", mid)
}
//个人运营
if rec.Person != nil {
person := rec.Person
rec4 = &academy.RecConf{PID: person.ID, TIDs: person.Other.Key}
res = append(res, rec4)
} else {
log.Error("getRecTag get person conf mid(%d)", mid)
}
return
}
func (s *Service) getFavType(c context.Context, mid int64) (tyID int64, err error) { //获取最近投稿的一个分区
tys, err := s.arc.FavTypes(c, mid)
if err != nil {
log.Error("s.arc.FavTypes mid(%d)|error(%v)", mid, err)
return
}
if len(tys) == 0 {
return 0, nil
}
type kv struct {
id int64
ptime int64
}
var tps []*kv
for id, t := range tys {
tid, err := strconv.ParseInt(id, 10, 64)
if err != nil {
return 0, err
}
tps = append(tps, &kv{tid, t})
}
sort.Slice(tps, func(i, j int) bool {
return tps[i].ptime > tps[j].ptime
})
if len(tps) > 0 && tps[0] != nil {
tyID = tps[0].id
}
return
}
//randomForMainCourse 主题课程每日0点重新随机排序
func (s *Service) randomForMainCourse(arc []*academy.RecArchive) {
count := len(arc)
if count == 0 {
return
}
keys := tool.RandomSliceKeys(0, count, count, s.Seed)
res := make([]*academy.RecArchive, 0, count)
for _, k := range keys {
res = append(res, arc[k])
}
if len(res) > 0 { //获取随机排序的稿件列表
s.RecommendArcs = res
}
log.Info("randomRecommend s.RecommendArcs (%s)", spew.Sdump(s.RecommendArcs))
}
func (s *Service) setSeed() {
now := time.Now()
last := now
next := now.Add(time.Hour * 24)
last = time.Date(last.Year(), last.Month(), last.Day(), 0, 0, 0, 0, last.Location()) //昨日0点
next = time.Date(next.Year(), next.Month(), next.Day(), 0, 0, 0, 0, next.Location()) //明日0点
if now.Unix() > last.Unix() && now.Unix() < next.Unix() {
s.Seed = last.Unix() //set last seed
} else {
s.Seed = next.Unix() //set next seed
}
log.Info("setSeed s.Seed (%d)", s.Seed)
}
func (s *Service) getTags(c context.Context, aids []int64) (res map[int64]map[string][]*academy.Tag, err error) {
if len(aids) == 0 {
log.Error("getTags len(aids) == 0")
return
}
aidTIDsMap, err := s.aca.ArchiveTagsByOids(c, aids)
if err != nil {
log.Error("getTags s.aca.ArchiveTagsByOids aids(%+v)", aids)
return
}
if len(aidTIDsMap) == 0 {
log.Error("getTags len(aidTIDsMap) == 0 | aids(%+v)", aids)
return
}
res, err = s.bindTags(c, aidTIDsMap)
if err != nil {
log.Error("getTags s.bindTags | err(%v)", err)
return
}
return
}
func (s *Service) setTags(x interface{}, tags map[int64]map[string][]*academy.Tag) {
switch arcs := x.(type) {
case []*academy.RecArchive:
for _, v := range arcs {
if v != nil {
if tag, ok := tags[v.OID]; ok {
v.Tags = tag
}
}
}
case []*academy.ArcMeta:
for _, v := range arcs {
if v != nil {
if tag, ok := tags[v.AID]; ok {
v.Tags = tag
}
}
}
}
}
// HotArchives get host archives
func (s *Service) HotArchives(c context.Context, oids []int64) (res []*academy.ArchiveMeta, err error) {
res = make([]*academy.ArchiveMeta, 0)
if len(oids) == 0 {
log.Error("HotArchives len(oids) == 0")
return
}
var (
g, _ = errgroup.WithContext(c)
arcs map[int64]*api.Arc
st map[int64]*api.Stat
)
g.Go(func() error {
arcs, err = s.arc.Archives(c, oids, "")
if err != nil {
log.Error("HotArchives s.arc.Archives oids(%+v)| error(%v)", oids, err)
return err
}
st, err = s.arc.Stats(c, oids, "")
if err != nil {
log.Error("HotArchives s.arc.Stats oids(%+v)| error(%v)", oids, err)
return err
}
return nil
})
if g.Wait() != nil {
log.Error("HotArchives g.Wait() error(%v)", err)
return
}
for _, oid := range oids {
a := &academy.ArchiveMeta{
OID: oid,
}
a = bindArchiveInfo(oid, arcs, a)
if t, ok := st[oid]; ok {
a.ArcStat = t
} else {
a.ArcStat = &api.Stat{}
}
res = append(res, a)
}
return
}
func (s *Service) hotArchives(c context.Context) (res []*academy.RecArchive, err error) {
if len(s.ResourceMapCache) == 0 {
log.Error("hotArchives len(oids) == 0 | ResourceMapCache(%+v)", s.ResourceMapCache)
return
}
res = make([]*academy.RecArchive, 0)
var oids []int64
for k := range s.ResourceMapCache {
oids = append(oids, k)
}
arcs, err := s.HotArchives(c, oids)
if err != nil {
log.Error("hotArchives s.HotArchives oids(%+v) | error(%v)", oids, err)
return
}
var aids []int64
for _, v := range arcs {
ra := &academy.RecArchive{
OID: v.OID,
MID: v.MID,
Cover: v.Cover,
Title: v.Title,
Business: 1, //热门推荐默认为视频
Duration: v.Duration,
ArcStat: v.ArcStat,
ArtStat: v.ArtStat,
}
res = append(res, ra)
aids = append(aids, v.OID)
}
//add tags
tags, err := s.getTags(c, aids)
if err != nil {
log.Error("hotArchives s.getTags err(%v)", err)
return
}
s.setTags(res, tags)
return
}

View File

@@ -0,0 +1,159 @@
package academy
import (
"context"
"time"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/dao/academy"
"go-common/app/interface/main/creative/dao/archive"
"go-common/app/interface/main/creative/dao/article"
"go-common/app/interface/main/creative/dao/resource"
acaMdl "go-common/app/interface/main/creative/model/academy"
"go-common/app/interface/main/creative/service"
"go-common/library/log"
)
//Service struct
type Service struct {
c *conf.Config
aca *academy.Dao
arc *archive.Dao
art *article.Dao
resource *resource.Dao
TagsCache map[string][]*acaMdl.Tag
TagMapCache map[int64]*acaMdl.Tag
parentChildMapCache map[int64]*acaMdl.Tag
ResourceMapCache map[int64]struct{}
OccCache []*acaMdl.Occupation
OccMapCache map[int64]*acaMdl.Occupation
SkillCache []*acaMdl.Skill
SkillMapCache map[int64]*acaMdl.Skill
OfficialID int64
EditorChoiceID int64
NewbCourseID int64
ResourceID int64
//for recommend
Seed int64
RecommendArcs []*acaMdl.RecArchive
//task
p *service.Public
//keywords
KWsCache []interface{}
}
//New get service
func New(c *conf.Config, rpcdaos *service.RPCDaos, p *service.Public) *Service {
s := &Service{
c: c,
aca: academy.New(c),
arc: rpcdaos.Arc,
art: rpcdaos.Art,
resource: resource.New(c),
OccMapCache: make(map[int64]*acaMdl.Occupation),
SkillMapCache: make(map[int64]*acaMdl.Skill),
OfficialID: c.Academy.OfficialID,
EditorChoiceID: c.Academy.EditorChoiceID,
NewbCourseID: c.Academy.NewbCourseID,
ResourceID: c.Academy.ResourceID,
p: p,
}
s.loadTags()
s.loadOccupations()
s.loadSkills()
s.loadResources()
s.loadKeyWords()
go s.loadProc()
return s
}
// Ping service
func (s *Service) Ping(c context.Context) (err error) {
if err = s.aca.Ping(c); err != nil {
log.Error("s.aca.Ping err(%v)", err)
}
return
}
// Close dao
func (s *Service) Close() {
s.aca.Close()
}
// loadproc
func (s *Service) loadProc() {
for {
time.Sleep(3 * time.Minute)
s.loadTags()
s.loadOccupations()
s.loadSkills()
s.loadResources()
s.loadKeyWords()
}
}
//load tags
func (s *Service) loadTags() {
tgList, tgMap, pcMap, err := s.aca.TagList(context.Background())
if err != nil {
log.Error("s.aca.TagList error(%v)", err)
return
}
s.TagsCache = tgList
s.TagMapCache = tgMap
s.parentChildMapCache = pcMap
}
//load occupations
func (s *Service) loadOccupations() {
ocs, err := s.aca.Occupations(context.Background())
if err != nil {
log.Error("s.aca.Occupations error(%v)", err)
return
}
s.OccCache = ocs
for _, v := range s.OccCache {
s.OccMapCache[v.ID] = v
}
}
//load skills
func (s *Service) loadSkills() {
sks, err := s.aca.Skills(context.Background())
if err != nil {
log.Error("s.aca.Skills error(%v)", err)
return
}
s.SkillCache = sks
for _, v := range s.SkillCache {
s.SkillMapCache[v.ID] = v
}
}
//load skills
func (s *Service) loadResources() {
res, err := s.resource.Resource(context.Background(), int(s.ResourceID))
if err != nil {
log.Error("loadResources ResourceID(%d) error(%v)", int(s.ResourceID), err)
return
}
if res == nil {
return
}
s.ResourceMapCache = res
}
//load keywords
func (s *Service) loadKeyWords() {
res, err := s.aca.Keywords(context.Background())
if err != nil {
return
}
if res == nil {
return
}
s.KWsCache = acaMdl.Trees(res, "ID", "ParentID", "Children")
}

View File

@@ -0,0 +1,95 @@
package academy
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/model/academy"
"go-common/app/interface/main/creative/service"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
p *service.Public
)
func init() {
dir, _ := filepath.Abs("../../cmd/creative.toml")
flag.Set("conf", dir)
conf.Init()
rpcdaos := service.NewRPCDaos(conf.Conf)
p = service.New(conf.Conf, rpcdaos)
s = New(conf.Conf, rpcdaos, p)
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
Reset(func() {})
f(s)
}
}
func Test_TagList(t *testing.T) {
var (
c = context.TODO()
)
Convey("TagList", t, WithService(func(s *Service) {
res, err := s.TagList(c)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
}))
}
func Test_ArchivesWithES(t *testing.T) {
var (
c = context.TODO()
aca = &academy.EsParam{
Tid: []int64{},
Business: 1,
Pn: 1,
Ps: 10,
Keyword: "",
Order: "",
IP: "127.0.0.1",
}
)
Convey("Archives", t, WithService(func(s *Service) {
res, err := s.ArchivesWithES(c, aca)
//spew.Dump(res, err)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
}))
}
func Test_AddFeedBack(t *testing.T) {
var (
c = context.TODO()
category = "视频"
course = "图像处理"
suggest = "画质太差"
mid = int64(123)
)
Convey("AddFeedBack", t, WithService(func(s *Service) {
id, err := s.AddFeedBack(c, category, course, suggest, mid)
So(err, ShouldBeNil)
So(id, ShouldBeGreaterThan, 0)
}))
}
func Test_RecommendV2(t *testing.T) {
var (
c = context.TODO()
mid = int64(123)
)
Convey("RecommendV2", t, WithService(func(s *Service) {
_, err := s.RecommendV2(c, mid)
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,492 @@
package academy
import (
"context"
"sort"
"time"
"go-common/app/interface/main/creative/model/academy"
"go-common/app/interface/main/creative/model/newcomer"
"go-common/app/service/main/archive/api"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/sync/errgroup"
xtime "go-common/library/time"
)
// Occupations get occ.
func (s *Service) Occupations(c context.Context) (res []*academy.Occupation, err error) {
res = s.OccCache
res = make([]*academy.Occupation, 0, len(res))
for _, v := range s.OccCache {
if v.ID == 7 || v.ID == s.NewbCourseID { //7-废弃 NewbCourseID-新人专区
continue
}
res = append(res, v)
}
return
}
// NewbCourse get new up course.
func (s *Service) NewbCourse(c context.Context) (res []*academy.NewbCourseList, err error) {
var (
skids []int64
pids = []int64{}
sids = []int64{}
tcs *academy.ArcList
skMap map[int64]string
aids []int64
)
skMap = make(map[int64]string)
for _, v := range s.SkillCache {
if v.OID == s.NewbCourseID {
skids = append(skids, v.ID)
skMap[v.ID] = v.Name
}
}
tcs, err = s.ThemeCourse(c, pids, skids, sids, 1, 20, true)
if err != nil {
log.Error("NewbCourse s.ThemeCourse pids(%+v)|skids(%+v)|sids(%+v)|error(%v)", pids, skids, sids, err)
return
}
if len(tcs.Items) == 0 {
return
}
// add tags
for _, v := range tcs.Items {
aids = append(aids, v.AID)
}
tags, err := s.getTags(c, aids)
if err != nil {
log.Error("NewbCourse s.getTags err(%v)", err)
return
}
s.setTags(tcs.Items, tags)
newbCourseMap := make(map[int64][]*academy.ArcMeta)
for _, v := range tcs.Items {
if v == nil || v.Skill == nil {
continue
}
newbCourseMap[v.Skill.SkID] = append(newbCourseMap[v.Skill.SkID], v)
}
res = make([]*academy.NewbCourseList, 0)
for _, id := range skids {
l := &academy.NewbCourseList{}
if v, ok := newbCourseMap[id]; ok {
l.Items = v
}
if sname, ok := skMap[id]; ok {
l.Title = sname
l.TID = id
}
res = append(res, l)
}
return
}
// ThemeCourse get theme course.
func (s *Service) ThemeCourse(c context.Context, pids, skids, sids []int64, pn, ps int, isnew bool) (res *academy.ArcList, err error) {
var (
skas []*academy.SkillArc
aids []int64
pidMap map[int64]int64
skidMap map[int64]int64
sidMap map[int64]int64
total int
)
res = &academy.ArcList{
Items: []*academy.ArcMeta{},
Page: &academy.ArchivePage{
Pn: pn,
Ps: ps,
},
}
if !isnew && len(pids) == 0 { //如果不是新人课程并且不传职业课程id则默认全部
for _, v := range s.OccCache {
pids = append(pids, v.ID)
}
}
if !isnew { //不是新人课程,则去掉新人课程
for i := 0; i < len(pids); i++ {
if pids[i] == s.NewbCourseID {
pids = append(pids[:i], pids[i+1:]...)
i--
}
}
}
if skas, err = s.aca.SkillArcs(c, pids, skids, sids, (pn-1)*ps, ps); err != nil {
log.Error("s.aca.SkillArcs pid(%+v)|skid(%+v)|sid(%+v)|error(%v)", pids, skids, sids, err)
return
}
if len(skas) == 0 {
log.Error("s.aca.SkillArcs has no data")
return
}
pidMap = make(map[int64]int64)
skidMap = make(map[int64]int64)
sidMap = make(map[int64]int64)
for _, v := range skas {
aids = append(aids, v.AID)
pidMap[v.AID] = v.PID
skidMap[v.AID] = v.SkID
sidMap[v.AID] = v.SID
}
if total, err = s.aca.SkillArcCount(c, pids, skids, sids); err != nil {
log.Error("s.aca.SkillArcCount pids(%+v)|skids(%+v)|sids(%+v)|error(%v)", pids, skids, sids, err)
return
}
res.Page.Total = total
var (
g, _ = errgroup.WithContext(c)
arcInfo map[int64]*api.Arc
as map[int64]*api.Stat
)
g.Go(func() error {
arcInfo, err = s.arc.Archives(c, aids, "")
if err != nil {
log.Error("s.arc.Archives aids(%+v)|error(%v)", aids, err)
}
return err
})
g.Go(func() error {
as, err = s.arc.Stats(c, aids, "")
if err != nil {
log.Error("s.arc.Stats aids(%+v)|error(%v)", aids, err)
}
return err
})
if g.Wait() != nil {
log.Error("s.aca.ThemeCourse g.Wait() error(%v)", err)
return
}
items := make([]*academy.ArcMeta, 0, len(aids))
for _, aid := range aids {
v, ok := arcInfo[aid]
if !ok || v == nil {
log.Error("ThemeCourse bind ArcInfo aid(%d) error", aid)
return
}
a := &academy.ArcMeta{
AID: aid,
Cover: v.Pic,
Title: v.Title,
Type: v.TypeName,
MID: v.Author.Mid,
Duration: v.Duration,
Skill: &academy.SkillArc{},
Business: 1, //技能树只有视频
}
if st, ok := as[aid]; ok {
a.ArcStat = st
} else {
a.ArcStat = &api.Stat{}
}
if pid, ok := pidMap[aid]; ok {
a.Skill.PID = pid
}
if skid, ok := skidMap[aid]; ok {
a.Skill.SkID = skid
}
if sid, ok := sidMap[aid]; ok {
a.Skill.SID = sid
}
items = append(items, a)
}
res.Items = items
return
}
// ViewPlay view play archive by aid & mid & business.
func (s *Service) ViewPlay(c context.Context, mid, aid int64, bus int8) (play *academy.Play, err error) {
p := &academy.Play{
MID: mid,
AID: aid,
Business: bus,
}
play, err = s.aca.Play(c, p)
if err != nil {
log.Error("ViewPlay s.aca.Play error(%v)", err)
}
return
}
// PlayAdd add play archive by aid & mid.
func (s *Service) PlayAdd(c context.Context, mid, aid int64, bus, watch int8) (id int64, err error) {
py := &academy.Play{
MID: mid,
AID: aid,
Business: bus,
Watch: watch,
CTime: xtime.Time(time.Now().Unix()),
MTime: xtime.Time(time.Now().Unix()),
}
if id, err = s.aca.PlayAdd(c, py); err != nil {
log.Error("s.aca.PlayAdd error(%v)", err)
return
}
s.p.TaskPub(mid, newcomer.MsgForAcademyFavVideo, newcomer.MsgFinishedCount)
return
}
// PlayDel del play archive by aid & mid & business.
func (s *Service) PlayDel(c context.Context, mid, aid int64, bus int8) (id int64, err error) {
p := &academy.Play{
MID: mid,
AID: aid,
Business: bus,
}
play, err := s.aca.Play(c, p)
if err != nil {
log.Error("PlayDel s.aca.Play error(%v)", err)
return
}
if play == nil {
err = ecode.NothingFound
return
}
if id, err = s.aca.PlayDel(c, p); err != nil {
log.Error("s.aca.PlayDel error(%v)", err)
}
return
}
// PlayList get play list.
func (s *Service) PlayList(c context.Context, mid int64, pn, ps int) (res *academy.ArcList, err error) {
var (
pls []*academy.Play
total int
aids, cids []int64
playMap map[int64]*academy.Play
)
res = &academy.ArcList{
Items: []*academy.ArcMeta{},
Page: &academy.ArchivePage{
Pn: pn,
Ps: ps,
},
}
if pls, err = s.aca.Plays(c, mid, (pn-1)*ps, ps); err != nil {
log.Error("s.aca.Plays mid(%d)|error(%v)", mid, err)
return
}
if len(pls) == 0 {
log.Error("s.aca.Plays has no mid(%d)", mid)
return
}
playMap = make(map[int64]*academy.Play)
for _, v := range pls {
if v.Business == 1 {
aids = append(aids, v.AID)
} else if v.Business == 2 {
cids = append(cids, v.AID)
}
playMap[v.AID] = v
}
if total, err = s.aca.PlayCount(c, mid); err != nil {
log.Error("s.aca.PlayCount error(%v)", err)
return
}
res.Page.Total = total
var (
arcs []*academy.ArcMeta
arts []*academy.ArcMeta
g, _ = errgroup.WithContext(c)
)
g.Go(func() error {
arcs, err = s.getArcInfo(c, aids, playMap)
return err
})
g.Go(func() error {
arts, err = s.getArtInfo(c, cids, playMap)
return err
})
if g.Wait() != nil {
log.Error("s.PlayList g.Wait() error(%v)", err)
return
}
tItems := make([]*academy.ArcMeta, 0, len(arcs)+len(arts))
tItems = append(tItems, arcs...)
tItems = append(tItems, arts...)
sort.Slice(tItems, func(i, j int) bool { //按播放时间倒序
return tItems[i].PlayTime > tItems[j].PlayTime
})
unReadItems := make([]*academy.ArcMeta, 0)
readItems := make([]*academy.ArcMeta, 0)
for _, v := range tItems {
if v.Watch == 1 {
unReadItems = append(unReadItems, v)
} else if v.Watch == 2 {
readItems = append(readItems, v)
}
}
res.Items = append(res.Items, unReadItems...) //未观看最先展示
res.Items = append(res.Items, readItems...)
return
}
func (s *Service) getArcInfo(c context.Context, aids []int64, playMap map[int64]*academy.Play) (items []*academy.ArcMeta, err error) {
arcs, err := s.arc.Archives(c, aids, "")
if err != nil {
log.Error("s.arc.Archives aids(%+v)|error(%v)", aids, err)
return
}
items = make([]*academy.ArcMeta, 0, len(aids))
for _, aid := range aids {
v, ok := arcs[aid]
if !ok || v == nil {
log.Error("PlayList bind ArcInfo aid(%d) error", aid)
return
}
a := &academy.ArcMeta{
AID: aid,
Cover: v.Pic,
Title: v.Title,
Type: v.TypeName,
MID: v.Author.Mid,
Duration: v.Duration,
}
if p, ok := playMap[aid]; ok {
a.PlayTime = p.MTime
a.Watch = p.Watch
a.Business = p.Business
}
items = append(items, a)
}
return
}
func (s *Service) getArtInfo(c context.Context, cids []int64, playMap map[int64]*academy.Play) (items []*academy.ArcMeta, err error) {
arts, err := s.art.ArticleMetas(c, cids, "")
if err != nil {
log.Error("s.arc.ArticleMetas cids(%+v) error(%v)", cids, err)
return
}
items = make([]*academy.ArcMeta, 0, len(cids))
for _, cid := range cids {
v, ok := arts[cid]
if !ok || v == nil {
log.Error("PlayList bind ArtInfo cid(%d) error", cid)
return
}
a := &academy.ArcMeta{
AID: cid,
Title: v.Title,
MID: v.Author.Mid,
}
if v.Category != nil {
a.Type = v.Category.Name
}
if len(v.ImageURLs) > 0 {
a.Cover = v.ImageURLs[0]
}
if p, ok := playMap[cid]; ok {
a.PlayTime = p.MTime
a.Watch = p.Watch
a.Business = p.Business
}
items = append(items, a)
}
return
}
// ProfessionSkill get theme course.
func (s *Service) ProfessionSkill(c context.Context, pids, skids, sids []int64, pn, ps int, isnew bool) (res []*academy.NewbCourseList, err error) {
var (
tcs *academy.ArcList
skMap map[int64]string
aids []int64
)
// 取消分页默认最大获取100条
tcs, err = s.ThemeCourse(c, pids, skids, sids, 1, 100, false)
if err != nil {
log.Error("ProfessionSkill s.ThemeCourse pids(%+v)|skids(%+v)|sids(%+v)|error(%v)", pids, skids, sids, err)
return
}
if len(tcs.Items) == 0 {
return
}
skMap = make(map[int64]string)
for _, v := range s.SkillCache {
skids = append(skids, v.ID)
skMap[v.ID] = v.Name
}
// add tags
for _, v := range tcs.Items {
if v == nil {
continue
}
aids = append(aids, v.AID)
}
tags, err := s.getTags(c, aids)
if err != nil {
log.Error("ProfessionSkill s.getTags err(%v)", err)
return
}
s.setTags(tcs.Items, tags)
newbCourseMap := make(map[int64][]*academy.ArcMeta)
for _, v := range tcs.Items {
if v == nil || v.Skill == nil {
continue
}
newbCourseMap[v.Skill.SkID] = append(newbCourseMap[v.Skill.SkID], v)
}
res = make([]*academy.NewbCourseList, 0)
for _, id := range skids {
l := &academy.NewbCourseList{}
if v, ok := newbCourseMap[id]; ok {
l.Items = v
}
if sname, ok := skMap[id]; ok {
l.Title = sname
l.TID = id
}
if len(l.Items) == 0 {
continue
}
res = append(res, l)
}
return
}
// Keywords get keywords.
func (s *Service) Keywords(c context.Context) (res []interface{}) {
res = s.KWsCache
return
}

View File

@@ -0,0 +1,62 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/account:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"account.go",
"service.go",
],
importpath = "go-common/app/interface/main/creative/service/account",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/dao/account:go_default_library",
"//app/interface/main/creative/dao/archive:go_default_library",
"//app/interface/main/creative/dao/article:go_default_library",
"//app/interface/main/creative/dao/up:go_default_library",
"//app/interface/main/creative/model/account:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//app/service/main/account/model:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/metadata:go_default_library",
"//library/stat/prom:go_default_library",
"//library/sync/errgroup:go_default_library",
"//library/time:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,219 @@
package account
import (
"context"
"go-common/library/log"
"go-common/library/net/metadata"
"go-common/library/sync/errgroup"
"time"
accmdl "go-common/app/interface/main/creative/model/account"
account "go-common/app/service/main/account/model"
"go-common/library/ecode"
xtime "go-common/library/time"
"sync"
)
const creatorMID = 37090048
// MyInfo get use level.
func (s *Service) MyInfo(c context.Context, mid int64, ip string, now time.Time) (m *accmdl.MyInfo, err error) {
var (
idCkCode = 0
res *account.Profile
)
// init myinfo
m = &accmdl.MyInfo{
Mid: mid,
Level: 1,
Activated: true,
Deftime: xtime.Time(now.Add(time.Duration(14400) * time.Second).Unix()),
DeftimeEnd: xtime.Time(now.Add(time.Duration(15*24) * time.Hour).Unix()),
DeftimeMsg: ecode.String(ecode.VideoupDelayTimeErr.Error()).Message(),
IdentifyInfo: &accmdl.IdentifyInfo{
Code: idCkCode,
Msg: accmdl.IdentifyEnum[idCkCode],
},
UploadSize: map[string]bool{
"4-8": false,
"8-16": false,
},
DmSubtitle: true,
}
if res, err = s.acc.Profile(c, mid, ip); err != nil {
log.Error("s.acc.Profile (%d) error(%v)", mid, err)
return
}
if res == nil {
err = ecode.NothingFound
return
}
if res.Silence == 1 {
m.Banned = true
}
if res.EmailStatus == 1 || res.TelStatus == 1 {
m.Activated = true
}
m.Name = res.Name
m.Face = res.Face
m.Level = int(res.Level)
if _, ok := s.exemptIDCheckUps[mid]; ok {
log.Info("s.exemptIDCheckUps (%d) info(%v)", mid, s.exemptIDCheckUps)
idCkCode = 0
} else {
idCkCode, _ = s.acc.IdentifyInfo(c, mid, 0, ip)
}
m.IdentifyInfo.Code = idCkCode
m.IdentifyInfo.Msg = accmdl.IdentifyEnum[idCkCode] // NOTE: exist check
m = s.ignoreLevelUpAndActivated(m, mid, s.exemptZeroLevelAndAnswerUps)
if _, ok := s.uploadTopSizeUps[mid]; ok {
m.UploadSize["4-8"] = true
m.UploadSize["8-16"] = true
}
return
}
// type为12的白名单人员免账号激活免账号升级到1级
func (s *Service) ignoreLevelUpAndActivated(m *accmdl.MyInfo, mid int64, exemptZeroLevelAndAnswerUps map[int64]int64) *accmdl.MyInfo {
if len(exemptZeroLevelAndAnswerUps) > 0 {
_, ok := exemptZeroLevelAndAnswerUps[mid]
if ok && (m.Level < 1 || !m.Activated) {
m.Activated = true
m.Level = 1
}
}
return m
}
// UpInfo get video article pic blink up infos.
func (s *Service) UpInfo(c context.Context, mid int64, ip string) (v *accmdl.UpInfo, err error) {
cache := true
if v, err = s.acc.UpInfoCache(c, mid); err != nil {
s.pCacheMiss.Incr("upinfo_cache")
err = nil
cache = false
} else if v != nil {
s.pCacheHit.Incr("upinfo_cache")
return
}
s.pCacheMiss.Incr("upinfo_cache")
var (
g = &errgroup.Group{}
ctx = context.TODO()
)
v = &accmdl.UpInfo{
Archive: accmdl.NotUp,
Article: accmdl.NotUp,
Pic: accmdl.NotUp,
Blink: accmdl.NotUp,
}
g.Go(func() error {
blikCnt, _ := s.acc.Blink(ctx, mid, ip)
if blikCnt > 0 {
v.Blink = accmdl.IsUp
}
return nil
})
g.Go(func() error {
picCnt, _ := s.acc.Pic(c, mid, ip)
if picCnt > 0 {
v.Pic = accmdl.IsUp
}
return nil
})
g.Go(func() error {
arcCnt, _ := s.archive.UpCount(c, mid)
if arcCnt > 0 {
v.Archive = accmdl.IsUp
}
return nil
})
g.Go(func() error {
isAuthor, _ := s.article.IsAuthor(c, mid, ip)
if isAuthor {
v.Article = accmdl.IsUp
}
return nil
})
g.Wait()
if cache {
s.addCache(func() {
s.acc.AddUpInfoCache(context.Background(), mid, v)
})
}
return
}
// RecFollows 推荐关注
func (s *Service) RecFollows(c context.Context, mid int64) (fs []*accmdl.Friend, err error) {
var (
fsMids = []int64{creatorMID}
shouldFollowMids = []int64{}
infos = make(map[int64]*account.Info)
)
ip := metadata.String(c, metadata.RemoteIP)
if shouldFollowMids, err = s.acc.ShouldFollow(c, mid, fsMids, ip); err != nil {
log.Error("s.acc.ShouldFollow mid(%d)|ip(%s)|error(%v)", mid, ip, err)
return
}
if len(shouldFollowMids) > 0 {
if infos, err = s.acc.Infos(c, shouldFollowMids, ip); err != nil {
log.Error("s.acc.Infos mid(%d)|ip(%s)|shouldFollowMids(%+v)|error(%v)", mid, ip, shouldFollowMids, err)
return
}
for mid, info := range infos {
f := &accmdl.Friend{
Mid: mid,
Sign: info.Sign,
Face: info.Face,
Name: info.Name,
}
if mid == creatorMID {
f.Comment = "关注创作中心,获取更多创作情报"
f.ShouldFollow = 0
}
fs = append(fs, f)
}
}
return
}
// Infos 获取多个UP主的信息
func (s *Service) Infos(c context.Context, mids []int64, ip string) (res map[int64]*account.Info, err error) {
return s.acc.Infos(c, mids, ip)
}
// Relations 批量获取mid与其它用户的关系
func (s *Service) Relations(c context.Context, mid int64, fids []int64, ip string) (res map[int64]int, err error) {
return s.acc.Relations(c, mid, fids, ip)
}
// FRelations 获取用户与mid的关系Relations的反向
func (s *Service) FRelations(c context.Context, mid int64, fids []int64, ip string) (res map[int64]int, err error) {
var (
g errgroup.Group
sm sync.RWMutex
)
res = make(map[int64]int)
for _, v := range fids {
g.Go(func() error {
var r map[int64]int
if r, err = s.acc.Relations(c, v, []int64{mid}, ip); err != nil {
return err
}
sm.Lock()
res[v] = r[mid]
sm.Unlock()
return nil
})
}
if err = g.Wait(); err != nil {
log.Error("s.FRelations(%d,%v) error(%v)", mid, fids, err)
}
return
}
// Cards 批量获取用户的Card
func (s *Service) Cards(c context.Context, mids []int64, ip string) (cards map[int64]*account.Card, err error) {
return s.acc.Cards(c, mids, ip)
}

View File

@@ -0,0 +1,105 @@
package account
import (
"context"
"time"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/dao/account"
"go-common/app/interface/main/creative/dao/archive"
"go-common/app/interface/main/creative/dao/article"
"go-common/app/interface/main/creative/dao/up"
"go-common/app/interface/main/creative/service"
"go-common/library/log"
"go-common/library/stat/prom"
)
//Service struct.
type Service struct {
c *conf.Config
acc *account.Dao
article *article.Dao
archive *archive.Dao
up *up.Dao
exemptIDCheckUps map[int64]int64
exemptZeroLevelAndAnswerUps map[int64]int64
uploadTopSizeUps map[int64]int64
missch chan func()
pCacheHit *prom.Prom
pCacheMiss *prom.Prom
}
//New get service.
func New(c *conf.Config, rpcdaos *service.RPCDaos) *Service {
s := &Service{
c: c,
acc: rpcdaos.Acc,
article: rpcdaos.Art,
archive: rpcdaos.Arc,
up: rpcdaos.Up,
missch: make(chan func(), 1024),
pCacheHit: prom.CacheHit,
pCacheMiss: prom.CacheMiss,
}
s.loadExemptIDCheckUps()
s.loadExemptZeroLevelAndAnswer()
s.loadUpSpecialUploadTopSize()
go s.loadproc()
go s.cacheproc()
return s
}
// loadproc
func (s *Service) loadproc() {
for {
time.Sleep(5 * time.Minute)
s.loadExemptIDCheckUps()
s.loadExemptZeroLevelAndAnswer()
s.loadUpSpecialUploadTopSize()
}
}
// loadExemptIDCheckUps 白名单人员,免实名认证 type=8.
func (s *Service) loadExemptIDCheckUps() {
ups, err := s.up.UpSpecial(context.TODO(), 8)
if err != nil {
return
}
s.exemptIDCheckUps = ups
log.Info("exemptIDCheckUps ups: (%v)", len(ups))
}
// loadExemptIDCheckUps 白名单人员免账号激活免账号升级到1级 type=12
func (s *Service) loadExemptZeroLevelAndAnswer() {
ups, err := s.up.UpSpecial(context.TODO(), 12)
if err != nil {
return
}
s.exemptZeroLevelAndAnswerUps = ups
}
// loadUpSpecialUploadTopSize 投稿名单限制升级 上传视频可以超过4G,但是在8G以下 type=16
func (s *Service) loadUpSpecialUploadTopSize() {
ups, err := s.up.UpSpecial(context.TODO(), 16)
if err != nil {
return
}
s.uploadTopSizeUps = ups
}
// AddCache add to chan for cache
func (s *Service) addCache(f func()) {
select {
case s.missch <- f:
default:
log.Warn("cacheproc chan full")
}
}
// cacheproc is a routine for execute closure.
func (s *Service) cacheproc() {
for {
f := <-s.missch
f()
}
}

View File

@@ -0,0 +1,57 @@
package account
import (
"context"
"flag"
"go-common/app/interface/main/creative/conf"
accmdl "go-common/app/interface/main/creative/model/account"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/creative/service"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func init() {
dir, _ := filepath.Abs("../../cmd/creative.toml")
flag.Set("conf", dir)
conf.Init()
rpcdaos := service.NewRPCDaos(conf.Conf)
s = New(conf.Conf, rpcdaos)
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
Reset(func() {})
f(s)
}
}
func Test_Account(t *testing.T) {
var (
c = context.TODO()
err error
MID = int64(2089809)
localHost = "127.0.0.1"
v *accmdl.UpInfo
m *accmdl.MyInfo
ip = ""
)
Convey("MyInfo", t, WithService(func(s *Service) {
m, err = s.MyInfo(c, MID, ip, time.Now())
So(err, ShouldBeNil)
So(m, ShouldNotBeNil)
}))
Convey("UpInfo", t, WithService(func(s *Service) {
v, err = s.UpInfo(c, MID, localHost)
So(err, ShouldBeNil)
So(v, ShouldNotBeNil)
}))
}

View File

@@ -0,0 +1,52 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/game:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["service.go"],
importpath = "go-common/app/interface/main/creative/service/ad",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/dao/game:go_default_library",
"//app/interface/main/creative/dao/porder:go_default_library",
"//app/interface/main/creative/model/game:go_default_library",
"//app/interface/main/creative/model/porder:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,114 @@
package ad
import (
"context"
"sort"
"strings"
"time"
"go-common/app/interface/main/creative/conf"
gD "go-common/app/interface/main/creative/dao/game"
porderD "go-common/app/interface/main/creative/dao/porder"
gM "go-common/app/interface/main/creative/model/game"
porderM "go-common/app/interface/main/creative/model/porder"
"go-common/app/interface/main/creative/service"
"go-common/library/log"
)
//Service struct.
type Service struct {
c *conf.Config
game *gD.Dao
porder *porderD.Dao
industryList []*porderM.Config
showList []*porderM.Config
}
//New get service.
func New(c *conf.Config, rpcdaos *service.RPCDaos) *Service {
s := &Service{
c: c,
game: gD.New(c),
porder: porderD.New(c),
industryList: []*porderM.Config{},
showList: []*porderM.Config{},
}
s.loadPorderConfigList()
go s.loadproc()
return s
}
// GameList fn
func (s *Service) GameList(c context.Context, keywordStr, letterStr string, pn, ps int, ip string) (glist *gM.ListWithPager, err error) {
list, err := s.game.List(context.TODO(), keywordStr, ip)
if err != nil || len(list) == 0 {
return
}
res := []*gM.ListItem{}
if len(letterStr) > 0 {
letterStr = strings.ToUpper(string(letterStr[0]))
for _, ele := range list {
if ele.Letter == letterStr {
res = append(res, ele)
}
}
} else {
res = list
}
sort.Slice(res, func(i, j int) bool { return res[i].GameBaseID > res[j].GameBaseID })
total := len(res)
start := (pn - 1) * ps
end := pn * ps
glist = &gM.ListWithPager{
Pn: pn,
Ps: ps,
Total: total,
}
if total <= start {
glist.List = make([]*gM.ListItem, 0)
} else if total <= end {
glist.List = res[start:total]
} else {
glist.List = res[start:end]
}
return
}
// IndustryList fn
func (s *Service) IndustryList(c context.Context) (list []*porderM.Config, err error) {
list = s.industryList
return
}
// ShowList fn
func (s *Service) ShowList(c context.Context) (list []*porderM.Config, err error) {
list = s.showList
return
}
func (s *Service) loadproc() {
//for wait rpc client connect
time.Sleep(time.Duration(2 * time.Second))
for {
s.loadPorderConfigList()
time.Sleep(time.Duration(2 * time.Minute))
}
}
func (s *Service) loadPorderConfigList() {
list, err := s.porder.ListConfig(context.TODO())
if err != nil || list == nil || len(list) == 0 {
return
}
s.industryList = []*porderM.Config{}
s.showList = []*porderM.Config{}
for _, v := range list {
if v.Tp == porderM.ConfigTypeIndustry {
s.industryList = append(s.industryList, v)
}
if v.Tp == porderM.ConfigTypeShow {
s.showList = append(s.showList, v)
}
}
log.Info("ListConfig (%d)|(%d)", len(s.showList), len(s.industryList))
}

View File

@@ -0,0 +1,51 @@
package ad
import (
"context"
"flag"
"go-common/app/interface/main/creative/conf"
gM "go-common/app/interface/main/creative/model/game"
"path/filepath"
"testing"
"time"
. "github.com/smartystreets/goconvey/convey"
"go-common/app/interface/main/creative/service"
)
var (
s *Service
)
func init() {
dir, _ := filepath.Abs("../../cmd/creative.toml")
flag.Set("conf", dir)
conf.Init()
rpcdaos := service.NewRPCDaos(conf.Conf)
s = New(conf.Conf, rpcdaos)
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
Reset(func() {})
f(s)
}
}
func Test_GameList(t *testing.T) {
var (
c = context.TODO()
err error
localHost = "127.0.0.1"
glist *gM.ListWithPager
)
Convey("GameList", t, WithService(func(s *Service) {
glist, err = s.GameList(c, "", "", 1, 20, localHost)
So(err, ShouldBeNil)
So(glist, ShouldNotBeNil)
So(glist.Pn, ShouldEqual, 1)
So(glist.Ps, ShouldEqual, 20)
So(glist.List[0].GameBaseID, ShouldBeGreaterThanOrEqualTo, glist.List[1].GameBaseID)
}))
}

View File

@@ -0,0 +1,56 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/app:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"app.go",
"service.go",
],
importpath = "go-common/app/interface/main/creative/service/app",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/dao/app:go_default_library",
"//app/interface/main/creative/dao/message:go_default_library",
"//app/interface/main/creative/model/app:go_default_library",
"//app/interface/main/creative/model/message:go_default_library",
"//app/interface/main/creative/model/resource:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,246 @@
package app
import (
"context"
"encoding/json"
"fmt"
"go-common/app/interface/main/creative/conf"
appMdl "go-common/app/interface/main/creative/model/app"
resMdl "go-common/app/interface/main/creative/model/resource"
"go-common/library/log"
)
// Portals for app portal config.
func (s *Service) Portals(c context.Context, mid int64, artAuthor, build, ty int, plat string, resMdlPlat int8) (pts []*appMdl.Portal, err error) {
var apms []*appMdl.PortalMeta
if ty == appMdl.PortalIntro {
if resMdlPlat == resMdl.PlatIPad {
plat = "ipad"
}
apms = s.PortalIntro
} else if ty == appMdl.PortalNotice {
apms = s.PortalNotice
}
pts = make([]*appMdl.Portal, 0, len(apms))
for _, v := range apms {
shouldAppend := false
if v.Title == appMdl.MyArticle || v.Title == appMdl.OpenArticle {
if artAuthor == 1 && v.Title == appMdl.MyArticle && v.AllowMaterial(plat, build) {
shouldAppend = true
} else if artAuthor == 0 && v.Title == appMdl.OpenArticle && v.AllowMaterial(plat, build) {
shouldAppend = true
}
} else if v.AllowMaterial(plat, build) {
shouldAppend = true
}
if ty == appMdl.PortalIntro && !s.AllowWhiteCategory(mid, v) {
shouldAppend = false
}
if shouldAppend {
pts = append(pts, &appMdl.Portal{
Icon: v.Icon,
Title: v.Title,
Pos: v.Pos,
URL: v.URL,
New: v.Mark,
More: v.More,
SubTitle: v.SubTitle,
MTime: v.MTime,
})
}
}
return
}
// AllowWhiteCategory fn
func (s *Service) AllowWhiteCategory(mid int64, p *appMdl.PortalMeta) (ret bool) {
if len(p.WhiteExps) == 0 {
return true
}
var (
percentOK, groupOK bool
)
for _, v := range p.WhiteExps {
// for WhitePercentType
if v.TP == appMdl.WhitePercentType {
mod := mid % 100
fac := v.Value * 10
switch v.Value {
case appMdl.WhitePercentV10, appMdl.WhitePercentV20, appMdl.WhitePercentV50:
log.Warn("whiteexp WhitePercentV p(%+v), mid(%d), percentOK(%+v)", p.WhiteExps, mid, percentOK)
if mod <= fac {
percentOK = true
}
case appMdl.WhitePercentV00:
percentOK = true
default:
percentOK = false
}
log.Warn("whiteexp WhitePercentType p(%+v), mid(%d), percentOK(%+v)", p.WhiteExps, mid, percentOK)
}
// for WhiteGroupType
if v.TP == appMdl.WhiteGroupType {
if midMaps, ok := s.p.AppWhiteMidsByGroups[v.Value]; ok {
isWhite := false
for _, m := range midMaps {
if m == mid {
isWhite = true
break
}
}
if isWhite {
groupOK = true
}
}
log.Warn("whiteexp WhiteGroupType p(%+v), mid(%d), groupOK(%+v)", p.WhiteExps, mid, groupOK)
}
}
return percentOK || groupOK
}
// UploadMaterial fn
func (s *Service) UploadMaterial(c context.Context, aid int64, editors []*appMdl.Editor) (err error) {
if len(editors) < 0 || aid < 0 {
return nil
}
for _, editor := range editors {
materialDatas := s.splitMaterials(aid, editor)
for _, data := range materialDatas {
s.app.AddMaterialData(c, data)
}
}
return
}
func (s *Service) splitMaterials(aid int64, pe *appMdl.Editor) (pds []*appMdl.EditorData) {
pds = []*appMdl.EditorData{}
if pe.CID <= 0 {
return
}
subStr := pe.ParseSubtitles()
if len(subStr) > 0 {
pds = append(pds, &appMdl.EditorData{
AID: aid,
CID: pe.CID,
Type: appMdl.TypeSubtitle,
Data: subStr,
})
}
fonStr := pe.ParseFonts()
if len(fonStr) > 0 {
pds = append(pds, &appMdl.EditorData{
AID: aid,
CID: pe.CID,
Type: appMdl.TypeFont,
Data: fonStr,
})
}
filStr := pe.ParseFilters()
if len(filStr) > 0 {
pds = append(pds, &appMdl.EditorData{
AID: aid,
CID: pe.CID,
Type: appMdl.TypeFilter,
Data: filStr,
})
}
bgmStr := pe.ParseBgms()
if len(bgmStr) > 0 {
pds = append(pds, &appMdl.EditorData{
AID: aid,
CID: pe.CID,
Type: appMdl.TypeBGM,
Data: bgmStr,
})
}
stiStr := pe.ParseStickers()
if len(stiStr) > 0 {
pds = append(pds, &appMdl.EditorData{
AID: aid,
CID: pe.CID,
Type: appMdl.TypeSticker,
Data: stiStr,
})
}
vstStr := pe.ParseVStickers()
if len(vstStr) > 0 {
pds = append(pds, &appMdl.EditorData{
AID: aid,
CID: pe.CID,
Type: appMdl.TypeVideoupSticker,
Data: vstStr,
})
}
traStr := pe.ParseTransitions()
if len(traStr) > 0 {
pds = append(pds, &appMdl.EditorData{
AID: aid,
CID: pe.CID,
Type: appMdl.TypeTransition,
Data: traStr,
})
}
cooStr := pe.ParseCooperates()
if len(cooStr) > 0 {
pds = append(pds, &appMdl.EditorData{
AID: aid,
CID: pe.CID,
Type: appMdl.TypeCooperate,
Data: cooStr,
})
}
theStr := pe.ParseThemes()
if len(theStr) > 0 {
pds = append(pds, &appMdl.EditorData{
AID: aid,
CID: pe.CID,
Type: appMdl.TypeTheme,
Data: theStr,
})
}
switchMap := make(map[string]int8)
if pe.AudioRecord == 1 {
switchMap["audio_record"] = 1
}
if pe.Camera == 1 {
switchMap["camera"] = 1
}
if pe.Speed == 1 {
switchMap["speed"] = 1
}
if pe.CameraRotate == 1 {
switchMap["camera_rotate"] = 1
}
if len(switchMap) > 0 {
switchMapData, _ := json.Marshal(switchMap)
pds = append(pds, &appMdl.EditorData{
AID: aid,
CID: pe.CID,
Type: appMdl.TypeSwitch,
Data: string(switchMapData),
})
}
return
}
// Icons fn
func (s *Service) Icons() (res *conf.AppIcon) {
return s.c.AppIcon
}
// H5Page fn
func (s *Service) H5Page() (res *conf.H5Page) {
return s.c.H5Page
}
// BlockIntros fn
func (s *Service) BlockIntros(build int, platStr string) (res map[string]string) {
res = make(map[string]string)
res["college"] = s.c.H5Page.CreativeCollege
if (build >= 5350000 && platStr == "android") || (build >= 8240 && platStr == "ios") {
res["college"] = fmt.Sprintf("%s?from=rcmd&navhide=1", res["college"])
} else {
res["college"] = fmt.Sprintf("%s?from=rcmd", res["college"])
}
return
}

View File

@@ -0,0 +1,106 @@
package app
import (
"context"
"time"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/dao/app"
"go-common/app/interface/main/creative/dao/message"
appDML "go-common/app/interface/main/creative/model/app"
msgDML "go-common/app/interface/main/creative/model/message"
"go-common/app/interface/main/creative/service"
"go-common/library/log"
)
//Service struct.
type Service struct {
c *conf.Config
app *app.Dao
msg *message.Dao
PortalIntro, PortalNotice []*appDML.PortalMeta
CameraCfg map[string]interface{}
p *service.Public
}
func (s *Service) initCameraCfg() {
s.CameraCfg = map[string]interface{}{
"videoup_min_sec": 5,
"videoup_max_sec": 300,
"dyna_min_sec": 5,
"dyna_max_sec": 300,
"coo_min_sec": 5,
"coo_max_sec": 300,
}
}
//New get service.
func New(c *conf.Config, rpcdaos *service.RPCDaos, p *service.Public) *Service {
s := &Service{
c: c,
msg: message.New(c),
app: app.New(c),
PortalIntro: make([]*appDML.PortalMeta, 0),
PortalNotice: make([]*appDML.PortalMeta, 0),
p: p,
}
s.initCameraCfg()
s.loadPortal()
go s.loadproc()
return s
}
// Ping service
func (s *Service) Ping(c context.Context) (err error) {
if err = s.app.Ping(c); err != nil {
log.Error("s.appDao.PingDb err(%v)", err)
}
return
}
// Close dao
func (s *Service) Close() {
s.app.Close()
}
// loadproc
func (s *Service) loadproc() {
for {
time.Sleep(2 * time.Minute)
s.loadPortal()
}
}
//load db
func (s *Service) loadPortal() {
intro, err := s.app.Portals(context.TODO(), appDML.PortalIntro)
if err != nil {
log.Error("s.app.intro error(%v)", err)
return
}
s.PortalIntro = intro
// 创作激励 + 征稿公告
notice, err := s.app.Portals(context.TODO(), appDML.PortalIntro)
if err != nil {
log.Error("s.app.notice error(%v)", err)
return
}
s.PortalNotice = notice
}
// TopMsg fn.
func (s *Service) TopMsg(c context.Context, mid int64, build int, os, app, ak, ck, ip string) (data []*msgDML.Message, err error) {
if build > 5332000 && os == "android" {
return
} else if build > 8220 && app == "iphone" {
return
} else if build > 7339 && build < 8000 && app == "iphone_b" {
return
}
data, err = s.msg.GetUpList(c, mid, ak, ck, ip)
topLen := 1
if len(data) > topLen {
data = data[:topLen]
}
return
}

View File

@@ -0,0 +1,55 @@
package app
import (
"context"
"flag"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/model/app"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/creative/service"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
p *service.Public
)
func init() {
dir, _ := filepath.Abs("../../cmd/creative.toml")
flag.Set("conf", dir)
conf.Init()
rpcdaos := service.NewRPCDaos(conf.Conf)
p = service.New(conf.Conf, rpcdaos)
s = New(conf.Conf, rpcdaos, p)
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
Reset(func() {})
f(s)
}
}
func Test_PortalConfig(t *testing.T) {
var (
c = context.TODO()
err error
res []*app.Portal
artAuthor = 1
build = 524000
ty = 0
plat = "android"
mid = int64(2089809)
)
Convey("Portals", t, WithService(func(s *Service) {
res, err = s.Portals(c, mid, artAuthor, build, ty, plat, 2)
So(err, ShouldBeNil)
So(len(res), ShouldBeGreaterThan, 0)
}))
}

View File

@@ -0,0 +1,61 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/appeal:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"appeal.go",
"service.go",
],
importpath = "go-common/app/interface/main/creative/service/appeal",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/dao/account:go_default_library",
"//app/interface/main/creative/dao/appeal:go_default_library",
"//app/interface/main/creative/dao/archive:go_default_library",
"//app/interface/main/creative/dao/tag:go_default_library",
"//app/interface/main/creative/model/appeal:go_default_library",
"//app/interface/main/creative/model/archive:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//app/service/main/account/model:go_default_library",
"//app/service/main/archive/api:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/time:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,356 @@
package appeal
import (
"context"
xtime "go-common/library/time"
"hash/crc32"
"strconv"
"strings"
"time"
"go-common/app/interface/main/creative/model/appeal"
"go-common/app/interface/main/creative/model/archive"
"go-common/app/service/main/account/model"
"go-common/app/service/main/archive/api"
"go-common/library/ecode"
"go-common/library/log"
)
// List get appeal List.
func (s *Service) List(c context.Context, mid int64, pn, ps int, tp, ip string) (all, open, closed int, res []*appeal.Appeal, err error) {
list, err := s.ap.AppealList(c, mid, appeal.Business, ip)
if err != nil {
log.Error("s.ap.Appeals error(%v)", err)
return
}
if len(list) == 0 {
return
}
var (
start, end int
oaps []*appeal.Appeal // open appeal
caps []*appeal.Appeal // close appeal
apTmp []*appeal.Appeal // tmp appeal .
)
aps := make([]*appeal.Appeal, 0, len(list))
for _, v := range list {
ap := &appeal.Appeal{}
ap.ID = v.ID
ap.Oid = v.Oid
ap.Cid = v.ID
ap.Mid = v.Mid
ap.State = v.BusinessState
ap.Content = v.Desc
ap.Description = v.Desc
ap.CTime = v.CTime
ap.MTime = v.MTime
aps = append(aps, ap)
}
for _, v := range aps {
if appeal.IsOpen(v.State) {
oaps = append(oaps, v)
} else {
caps = append(caps, v)
}
}
all = len(aps)
open = len(oaps)
closed = len(caps)
if pn > 1 {
start = (pn - 1) * ps
} else {
start = 0
}
end = pn * ps
if tp == "open" {
apTmp = oaps
} else if tp == "closed" {
apTmp = caps
} else {
apTmp = aps
}
total := len(apTmp)
if total == 0 {
return
}
if total <= start {
res = make([]*appeal.Appeal, 0)
} else if total <= end {
res = apTmp[start:total]
} else {
res = apTmp[start:end]
}
if len(res) > 0 {
var (
aids []int64
aMap map[int64]*archive.ArcVideo
)
for _, v := range res {
aids = append(aids, v.Oid)
}
if len(aids) > 0 {
if aMap, err = s.arc.Views(c, mid, aids, ip); err != nil {
log.Error("s.arc.Archives aids(%v), ip(%s) err(%v)", aids, ip, err)
return
}
}
for _, v := range res {
if _, ok := aMap[v.Oid]; !ok {
continue
}
arc := &api.Arc{
Aid: aMap[v.Oid].Archive.Aid,
Pic: coverURL(aMap[v.Oid].Archive.Cover),
Title: aMap[v.Oid].Archive.Title,
State: int32(aMap[v.Oid].Archive.State),
}
v.ID = v.Cid
v.Title = arc.Title
v.Pics = arc.Pic
v.Archive = arc
}
}
return
}
// Detail get a appeal and events.
func (s *Service) Detail(c context.Context, mid, cid int64, ip string) (ap *appeal.Appeal, err error) {
var apmeta *appeal.AppealMeta
if apmeta, err = s.ap.AppealDetail(c, mid, cid, appeal.Business, ip); err != nil {
log.Error("s.ap.AppealDetail error(%v)", err)
return
}
if apmeta == nil {
err = ecode.AppealNotExist
return
}
var (
av *archive.ArcVideo
arc *api.Arc
starStr, etimeStr string
star, etime int64
)
ap = &appeal.Appeal{}
ap.ID = apmeta.ID
ap.Oid = apmeta.Oid
ap.Cid = apmeta.ID
ap.Mid = apmeta.Mid
ap.State = apmeta.BusinessState
ap.Content = apmeta.Desc
ap.Description = apmeta.Desc
ap.CTime = apmeta.CTime
ap.MTime = apmeta.MTime
ap.Attachments = apmeta.Attachments
if starStr, etimeStr, err = s.ap.AppealStarInfo(c, mid, cid, appeal.Business, ip); err != nil {
log.Error("s.ap.AppealStarInfo(%d,%d) error(%v)", mid, cid, err)
err = nil
}
if starStr != "" {
star, err = strconv.ParseInt(starStr, 10, 64)
if err != nil {
log.Error("strconv.Atoi(%s) applealid(%d) error(%v)", starStr, cid, err)
err = nil
}
ap.Star = int8(star)
}
if etimeStr != "" {
etime, err = strconv.ParseInt(etimeStr, 10, 64)
if err != nil {
log.Error("strconv.Atoi(%s) applealid(%d) error(%v)", etimeStr, cid, err)
err = nil
}
ap.MTime = xtime.Time(etime)
}
if av, err = s.arc.View(c, mid, ap.Oid, ip, 0, 0); err != nil {
log.Error("s.arc.View(%d,%d) error(%v)", mid, ap.Oid, err)
err = ecode.ArchiveNotExist
return
}
if av != nil && av.Archive != nil {
arc = &api.Arc{
Aid: av.Archive.Aid,
Pic: coverURL(av.Archive.Cover),
Title: av.Archive.Title,
State: int32(av.Archive.State),
}
}
if arc == nil {
arc = &api.Arc{}
}
ap.Title = arc.Title
ap.Aid = arc.Aid
ap.Archive = arc
eventTmp := make([]*appeal.Event, 0, len(apmeta.Events))
for _, v := range apmeta.Events { // Attachments 过滤管理员备注.
if v.Event == 2 {
continue
}
apev := &appeal.Event{}
apev.ID = v.ID
apev.AdminID = v.Adminid
apev.Content = v.Content
apev.ApID = v.Cid
apev.Pics = v.Attachments
apev.Event = v.Event
apev.Attachments = v.Attachments
apev.CTime = v.CTime
apev.MTime = v.MTime
eventTmp = append(eventTmp, apev)
}
ap.Events = eventTmp
var strTmp []string
for _, v := range ap.Attachments {
strTmp = append(strTmp, v.Path)
}
ap.Pics = strings.Join(strTmp, ";")
if ap.State == appeal.StateNoRead {
if err = s.ap.AppealState(c, mid, cid, appeal.Business, appeal.StateReply, ip); err != nil {
log.Error("s.ap.AppealState error(%v)", err)
err = nil
}
}
var (
pf *model.Profile
)
if pf, err = s.acc.Profile(c, mid, ip); err != nil {
log.Error("s.acc.Profile(%d) mid(%d)|ip(%s)|error(%v)", mid, ip, err)
return
}
if pf != nil {
ap.UserInfo = &appeal.UserInfo{
MID: pf.Mid,
Name: pf.Name,
Sex: pf.Sex,
Face: pf.Face,
Rank: pf.Rank,
Level: pf.Level,
}
}
return
}
// State shutdown an appeal.
func (s *Service) State(c context.Context, mid, cid, state int64, ip string) (err error) {
if err = s.ap.AppealState(c, mid, cid, appeal.Business, state, ip); err != nil {
log.Error("s.ap.AppealState error(%v)", err)
}
return
}
// Add create an appeal.
func (s *Service) Add(c context.Context, mid, aid int64, qq, phone, email, desc, attachments, ip string, ap *appeal.BusinessAppeal) (apID int64, err error) {
arc, err := s.arc.View(c, mid, aid, ip, 0, 0)
if err != nil {
log.Error("s.arc.Archive error(%v)", err)
err = ecode.CreativeArcServiceErr
return
}
if arc == nil {
log.Error("archive not exist")
err = ecode.ArchiveNotExist
return
}
if arc.Archive.Mid != mid {
log.Error("login mid(%d) and archive mid(%d) are different ", mid, arc.Archive.Mid)
err = ecode.AppealOwner
return
}
if !appeal.Allow(arc.Archive.State) {
log.Error("archive aid(%d) mid(%d) state(%d) ", aid, mid, arc.Archive.State)
err = ecode.AppealLimit
return
}
appeals, err := s.ap.AppealList(c, mid, appeal.Business, ip)
if err != nil {
log.Error("s.ap.AppealList error (%v)", err)
return
}
for _, k := range appeals {
if aid == k.Oid && appeal.IsOpen(k.BusinessState) {
err = ecode.AppealOpen
return
}
}
var tid int64
tid, err = s.tag.AppealTag(c, aid, ip)
if err != nil {
log.Error("s.tag.AppealTag error(%v)", err)
return
}
if tid == 0 && s.appealTag != 0 {
tid = s.appealTag
}
if tid == 0 {
log.Error("s.tag.AppealTag tid(%d)", tid)
return
}
if apID, err = s.ap.AddAppeal(c, tid, aid, mid, appeal.Business, qq, phone, email, desc, attachments, ip, ap); err != nil {
log.Error("s.ap.AddAppeal error(%v)", err)
}
return
}
// Reply add reply an appeal.
func (s *Service) Reply(c context.Context, mid, cid, event int64, content, attachments, ip string) (err error) {
if err = s.ap.AddReply(c, cid, event, content, attachments, ip); err != nil {
log.Error("s.ap.AddReply error(%v)", err)
return
}
if err = s.ap.AppealState(c, mid, cid, appeal.Business, appeal.StateCreate, ip); err != nil {
log.Error("user add reply s.ap.AppealState error(%v)", err)
err = nil
}
return
}
// PhoneEmail get user phone & email
func (s *Service) PhoneEmail(c context.Context, ck, ip string) (ct *appeal.Contact, err error) {
if ct, err = s.acc.PhoneEmail(c, ck, ip); err != nil {
log.Error("s.acc.PhoneEmail error(%v)", err)
}
if ct == nil {
err = ecode.NothingFound
}
return
}
// Star give star to appeal.
func (s *Service) Star(c context.Context, mid, cid, star int64, ip string) (err error) {
if err = s.ap.AppealExtra(c, mid, cid, appeal.Business, star, "star", ip); err != nil {
log.Error("s.ap.AppealExtra error(%v)", err)
return
}
if err = s.ap.AppealExtra(c, mid, cid, appeal.Business, time.Now().Unix(), "etime", ip); err != nil {
log.Error("s.ap.AppealExtra error(%v)", err)
return
}
if s.ap.AppealState(c, mid, cid, appeal.Business, appeal.StateUserFinished, ip); err != nil {
log.Error("star change stats s.ap.AppealState error(%v)", err)
err = nil
}
return
}
// coverURL convert cover url to full url.
func coverURL(uri string) (cover string) {
if uri == "" {
return
}
cover = uri
if strings.Index(uri, "http://") == 0 {
return
}
if len(uri) >= 10 && uri[:10] == "/templets/" {
return
}
if strings.HasPrefix(uri, "group1") {
cover = "http://i0.hdslb.com/" + uri
return
}
if pos := strings.Index(uri, "/uploads/"); pos != -1 && (pos == 0 || pos == 3) {
cover = uri[pos+8:]
}
cover = strings.Replace(cover, "{IMG}", "", -1)
cover = "http://i" + strconv.FormatInt(int64(crc32.ChecksumIEEE([]byte(cover)))%3, 10) + ".hdslb.com" + cover
return
}

View File

@@ -0,0 +1,44 @@
package appeal
import (
"context"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/dao/account"
"go-common/app/interface/main/creative/dao/appeal"
"go-common/app/interface/main/creative/dao/archive"
"go-common/app/interface/main/creative/dao/tag"
"go-common/app/interface/main/creative/service"
)
//Service struct
type Service struct {
c *conf.Config
ap *appeal.Dao
arc *archive.Dao
acc *account.Dao
tag *tag.Dao
appealTag int64
}
//New get service
func New(c *conf.Config, rpcdaos *service.RPCDaos) *Service {
s := &Service{
c: c,
ap: appeal.New(c),
arc: rpcdaos.Arc,
acc: rpcdaos.Acc,
tag: tag.New(c),
appealTag: c.AppealTag,
}
return s
}
// Ping service
func (s *Service) Ping(c context.Context) (err error) {
return
}
// Close dao
func (s *Service) Close() {
}

View File

@@ -0,0 +1,110 @@
package appeal
import (
"context"
"flag"
"fmt"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/model/appeal"
"go-common/app/interface/main/creative/service"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func init() {
dir, _ := filepath.Abs("../../cmd/creative.toml")
flag.Set("conf", dir)
conf.Init()
rpcdaos := service.NewRPCDaos(conf.Conf)
s = New(conf.Conf, rpcdaos)
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
Reset(func() {})
f(s)
}
}
var (
mid = int64(27515256)
cid = int64(123)
aid = int64(10109136)
tp = "open"
ip = "127.0.0.1"
c = context.TODO()
)
func Test_List(t *testing.T) {
Convey("List", t, WithService(func(s *Service) {
all, open, closed, res, err := s.List(c, mid, 1, 10, tp, ip)
So(err, ShouldBeNil)
fmt.Println(all, open, closed, res)
}))
}
func Test_Detail(t *testing.T) {
Convey("Detail", t, WithService(func(s *Service) {
res, err := s.Detail(c, mid, cid, ip)
So(err, ShouldBeNil)
fmt.Println(res)
}))
}
func Test_State(t *testing.T) {
Convey("State", t, WithService(func(s *Service) {
err := s.State(c, mid, cid, 2, ip)
So(err, ShouldBeNil)
}))
}
func Test_Add(t *testing.T) {
Convey("Add", t, WithService(func(s *Service) {
qq := "2322"
phone := "122333"
email := "ddsds@qq.com"
desc := "dedsds"
attachments := "sddds"
ap := &appeal.BusinessAppeal{}
res, err := s.Add(c, mid, aid, qq, phone, email, desc, attachments, ip, ap)
So(err, ShouldBeNil)
fmt.Println(res)
}))
}
func Test_Reply(t *testing.T) {
Convey("Reply", t, WithService(func(s *Service) {
event := int64(2)
content := "122333"
attachments := "sddds"
err := s.Reply(c, mid, cid, event, content, attachments, ip)
So(err, ShouldBeNil)
}))
}
func Test_PhoneEmail(t *testing.T) {
Convey("PhoneEmail", t, WithService(func(s *Service) {
ck := ""
res, err := s.PhoneEmail(c, ck, ip)
So(err, ShouldBeNil)
fmt.Println(res)
}))
}
func Test_Star(t *testing.T) {
Convey("Star", t, WithService(func(s *Service) {
star := int64(2)
err := s.Star(c, mid, cid, star, ip)
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,89 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/archive:go_default_library",
"//app/interface/main/creative/model/order:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"archive.go",
"biz.go",
"fav.go",
"history.go",
"mission.go",
"myinfo.go",
"netsafe.go",
"order.go",
"porder.go",
"rules.go",
"service.go",
"staff.go",
"tag.go",
"viewpoint.go",
],
importpath = "go-common/app/interface/main/creative/service/archive",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/videoup/model/archive:go_default_library",
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/dao/account:go_default_library",
"//app/interface/main/creative/dao/activity:go_default_library",
"//app/interface/main/creative/dao/appeal:go_default_library",
"//app/interface/main/creative/dao/archive:go_default_library",
"//app/interface/main/creative/dao/coin:go_default_library",
"//app/interface/main/creative/dao/game:go_default_library",
"//app/interface/main/creative/dao/order:go_default_library",
"//app/interface/main/creative/dao/search:go_default_library",
"//app/interface/main/creative/dao/tag:go_default_library",
"//app/interface/main/creative/dao/template:go_default_library",
"//app/interface/main/creative/model/activity:go_default_library",
"//app/interface/main/creative/model/appeal:go_default_library",
"//app/interface/main/creative/model/archive:go_default_library",
"//app/interface/main/creative/model/game:go_default_library",
"//app/interface/main/creative/model/order:go_default_library",
"//app/interface/main/creative/model/search:go_default_library",
"//app/interface/main/creative/model/tag:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//app/service/main/archive/api:go_default_library",
"//app/service/main/archive/model/archive:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/stat/prom:go_default_library",
"//library/sync/errgroup:go_default_library",
"//library/time:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,713 @@
package archive
import (
"context"
"encoding/json"
"fmt"
"go-common/app/interface/main/creative/model/activity"
"go-common/app/interface/main/creative/model/appeal"
"go-common/app/interface/main/creative/model/archive"
"go-common/app/interface/main/creative/model/search"
"go-common/app/interface/main/creative/model/tag"
pubSvc "go-common/app/interface/main/creative/service"
"go-common/app/service/main/archive/api"
mdlarc "go-common/app/service/main/archive/model/archive"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/sync/errgroup"
xtime "go-common/library/time"
"strings"
"time"
)
// SimpleArchiveVideos fn
func (s *Service) SimpleArchiveVideos(c context.Context, mid, aid int64, ak, ck, ip string) (ap *archive.SimpleArchiveVideos, err error) {
var (
sa *archive.SpArchive
svs []*archive.SpVideo
)
// User identity && permission check, logic from project 'member'
card, err := s.acc.Card(c, mid, ip)
if err != nil {
log.Error("s.acc.Profile(%d,%s) error(%v)", mid, ck, err)
return
}
if sa, err = s.arc.SimpleArchive(c, aid, ip); err != nil {
log.Error("s.arc.SimpleArchive(%d) error(%v)", aid, err)
return
}
if sa == nil {
log.Error("s.arc.SimpleArchive(%d) not found", aid)
err = ecode.NothingFound
return
}
if sa.Mid != mid {
err = ecode.NothingFound
return
}
if svs, err = s.arc.SimpleVideos(c, aid, ip); err != nil {
log.Error("s.arc.SimpleVideos(%d) error(%v)", aid, err)
return
}
for index, sv := range svs {
if sv.Status == -100 {
sv.DmActive = 0
} else {
sv.DmActive = 1
}
svs[index] = sv
}
acceptAss := card.Rank > 15000 || card.Rank == 20000
ap = &archive.SimpleArchiveVideos{Archive: sa, SpVideos: svs, AcceptAss: acceptAss}
return
}
// View get archive.
func (s *Service) View(c context.Context, mid, aid int64, ip, platform string) (av *archive.ArcVideo, err error) {
if av, err = s.arc.View(c, mid, aid, ip, archive.NeedPoi(platform), archive.NeedVote(platform)); err != nil {
log.Error("s.arc.View(%d,%d) error(%v)", mid, aid, err)
return
}
if av == nil || av.Archive == nil {
log.Error("s.arc.View(%d) not found", mid)
err = ecode.NothingFound
return
}
av.Archive.NilPoiObj(platform)
av.Archive.NilVote()
// check white
isWhite := false
for _, m := range s.c.Whitelist.ArcMids {
if m == mid {
isWhite = true
break
}
}
if !isWhite {
if av.Archive.Mid != mid {
err = ecode.AccessDenied
return
}
}
var (
a = av.Archive
vs = av.Videos
)
// add reject reason
if (a.State == mdlarc.StateForbidRecicle || a.State == mdlarc.StateForbidLock) && a.RejectReason == "" {
var c = 0
for _, v := range vs {
if v.Status == mdlarc.StateForbidRecicle ||
v.Status == mdlarc.StateForbidLock ||
v.Status == mdlarc.StateForbidXcodeFail {
c++
}
}
a.RejectReason = fmt.Sprintf("稿件中发现%d个问题。", c)
}
a.Cover = pubSvc.CoverURL(a.Cover)
if a.OrderID != 0 {
if a.OrderID, a.OrderName, _, err = s.order.OrderByAid(c, aid); err != nil {
log.Error("s.order.OrderByAid(%d,%d) error(%v)", mid, aid, err)
err = nil
}
}
if a.MissionID > 0 {
var act *activity.Activity
if act, err = s.act.Subject(c, a.MissionID); err != nil {
log.Error("s.act.Subject a.MissionID(%d) error(%v)", a.MissionID, err)
err = nil
return
}
a.MissionName = act.Name
}
if a.Porder != nil && a.Porder.Official == 1 && a.Porder.IndustryID == 1 {
if v, ok := s.gameMap[a.Porder.BrandID]; ok {
a.Porder.BrandName = v.GameName
}
}
if a.UgcPay == 1 {
a.UgcPayInfo = s.p.FillPayInfo(c, a, s.c.UgcPay, ip)
}
return
}
// Del fn
// 1,unbind act;2,decrease coin;3,unbind order;4,clean memcache
func (s *Service) Del(c context.Context, mid, aid int64, ip string) (err error) {
av, err := s.View(c, mid, aid, ip, archive.PlatformWeb)
if err != nil {
return
}
if av == nil || av.Archive == nil {
log.Error("s.arc.Del NothingFound (%d,%d,%d) error(%v)", mid, av.Archive.Mid, aid, err)
err = ecode.NothingFound
return
}
if av.Archive.Mid != mid {
log.Error("s.arc.Del AccessDenied (%d,%d,%d) error(%v)", mid, av.Archive.Mid, aid, err)
err = ecode.AccessDenied
return
}
if av.Archive.UgcPay == 1 {
canDelTime := xtime.Time(av.Archive.PTime.Time().AddDate(0, 0, s.c.UgcPay.AllowDeleteDays).Unix())
if av.Archive.CTime != av.Archive.PTime && xtime.Time(time.Now().Unix()) < canDelTime {
log.Error("checkEditPay CreativePayForbidDeleteAfterOpen aid(%d) ctime(%v) ptime(%v)", av.Archive.Aid, av.Archive.CTime, av.Archive.PTime)
err = ecode.CreativePayForbidDeleteAfterOpen
return
}
}
if err = s.arc.Del(c, mid, aid, ip); err != nil {
log.Error("s.arc.Del(%d,%d) error(%v)", mid, aid, err)
return
}
var (
a = av.Archive
g = &errgroup.Group{}
ctx = context.TODO()
)
g.Go(func() error {
if e := s.act.Unbind(ctx, aid, a.MissionID, ip); e != nil {
log.Error("s.act.UpdateByAid(%d,%d) error(%v)", aid, a.MissionID, e)
}
return nil
})
g.Go(func() error {
var coins float64
if a.State >= 0 {
coins = -2
} else {
coins = -1
}
if e := s.coin.AddCoin(ctx, mid, aid, coins, ip); e != nil {
log.Error("s.coin.AddCoin(%d,%d,%f,%s) error(%v)", mid, aid, coins, ip, e)
}
return nil
})
g.Go(func() error {
if e := s.order.Unbind(ctx, mid, aid, ip); e != nil {
log.Error("s.order.Unbind(%d,%d,%s) error(%v)", mid, aid, ip, e)
}
return nil
})
g.Go(func() error {
if e := s.arc.DelSubmitCache(ctx, mid, a.Title); e != nil {
log.Error("s.arc.DelSubmitCache (%d,%s,%s) error(%v)", mid, a.Title, ip, e)
}
return nil
})
g.Wait()
s.prom.Incr("archive_del")
return
}
// Archives for app all achives.
func (s *Service) Archives(c context.Context, mid int64, tid int16, kw, order, class, ip string, pn, ps, coop int) (res *search.Result, err error) {
if res, err = s.Search(c, mid, tid, kw, order, class, ip, pn, ps, coop); err != nil {
log.Error("s.Search err(%v)", err)
return
}
if res == nil || res.Archives == nil || len(res.Archives) == 0 {
return
}
for _, av := range res.Archives {
a := &api.Arc{
Aid: av.Archive.Aid,
TypeID: int32(av.Archive.TypeID),
TypeName: av.TypeName,
Copyright: int32(av.Archive.Copyright),
Title: av.Archive.Title,
Desc: av.Archive.Desc,
Attribute: av.Archive.Attribute,
Videos: int64(len(av.Videos)),
Pic: pubSvc.CoverURL(av.Archive.Cover),
State: int32(av.Archive.State),
Access: int32(av.Archive.Access),
Tags: strings.Split(av.Archive.Tag, ","),
Duration: av.Archive.Duration,
MissionID: av.Archive.MissionID,
OrderID: av.Archive.OrderID,
PubDate: av.Archive.PTime,
Ctime: av.Archive.CTime,
}
a.Author = api.Author{
Mid: av.Archive.Mid,
Name: av.Archive.Author,
}
a.Stat = api.Stat{
Aid: av.Stat.Aid,
View: int32(av.Stat.View),
Danmaku: int32(av.Stat.Danmaku),
Reply: int32(av.Stat.Reply),
Fav: int32(av.Stat.Fav),
Coin: int32(av.Stat.Coin),
Share: int32(av.Stat.Share),
NowRank: int32(av.Stat.NowRank),
HisRank: int32(av.Stat.HisRank),
}
ava := &archive.OldArchiveVideoAudit{
Arc: a,
StatePanel: av.StatePanel,
ParentTName: av.ParentTName,
Dtime: av.Archive.DTime,
StateDesc: av.Archive.StateDesc,
RejectReson: av.Archive.RejectReason,
UgcPay: av.Archive.UgcPay,
Attrs: av.Archive.Attrs,
}
if len(av.ArcVideo.Videos) > 0 {
var vas = make([]*archive.OldVideoAudit, 0, len(av.ArcVideo.Videos))
for _, vd := range av.ArcVideo.Videos {
va := &archive.OldVideoAudit{
IndexOrder: vd.Index,
Eptitle: vd.Title,
Reason: vd.RejectReason,
}
ava.VideoAudits = append(vas, va)
}
}
res.OldArchives = append(res.OldArchives, ava)
}
return
}
// Search all achive.
func (s *Service) Search(c context.Context, mid int64, tid int16, keyword, order, class, ip string, pn, ps, coop int) (res *search.Result, err error) {
defer func() {
if res != nil {
// get pending apply num
if coop > 0 {
count, _ := s.arc.CountByMID(c, mid)
res.Applies = &search.ApplyStateCount{
Pending: count,
}
}
}
}()
if res, err = s.sear.ArchivesES(c, mid, tid, keyword, order, class, ip, pn, ps, coop); err != nil {
// search err, use archive-service
log.Error("s.arc.Search(%d) error(%v)", mid, err)
res, err = s.ArchivesFromService(c, mid, class, ip, pn, ps)
if err != nil {
return
}
}
// add arctype *must return
res.ArrType = []*search.TypeCount{}
for _, v := range s.p.TopTypesCache {
t := &search.TypeCount{
Tid: v.ID,
Name: v.Name,
}
if _, ok := res.Type[v.ID]; ok {
t.Count = res.Type[v.ID].Count
}
res.ArrType = append(res.ArrType, t)
}
if res == nil || len(res.Aids) == 0 {
return
}
avm, err := s.arc.Views(c, mid, res.Aids, ip)
if err != nil {
log.Error("s.arc.Views res.Aids(%v), ip(%s) err(%v)", res.Aids, ip, err)
return
}
// get arc stats
as, _ := s.arc.Stats(c, res.Aids, ip)
// archives
for _, aid := range res.Aids {
av := avm[aid]
if av == nil {
continue
}
a := av.Archive
a.Cover = pubSvc.CoverURL(a.Cover)
ava := &archive.ArcVideoAudit{ArcVideo: av}
// arc stat info
if _, ok := as[aid]; ok {
ava.Stat = as[aid]
} else {
ava.Stat = &api.Stat{}
}
// typename
if _, ok := s.p.TypeMapCache[a.TypeID]; ok {
ava.TypeName = s.p.TypeMapCache[a.TypeID].Name
}
// parent typename
if _, ok := s.p.TypeMapCache[a.TypeID]; ok {
if _, ok := s.p.TypeMapCache[s.p.TypeMapCache[a.TypeID].Parent]; ok {
ava.ParentTName = s.p.TypeMapCache[s.p.TypeMapCache[a.TypeID].Parent].Name
}
}
// state panel
ava.StatePanel = archive.StatePanel(a.State)
// state desc
ava.Archive.StateDesc = s.c.StatDesc(int(a.State))
// not pubbed videos for reason
unpubedVideos := make([]*archive.Video, 0, len(ava.Videos))
for _, v := range ava.Videos {
if v.Status == -2 || v.Status == -4 || v.Status == -16 {
unpubedVideos = append(unpubedVideos, v)
}
}
c := len(unpubedVideos)
if c > 0 {
a.RejectReason = fmt.Sprintf("稿件中发现%d个问题。", c)
}
// set attrs
attrs := &archive.Attrs{
IsCoop: int8(ava.AttrVal(archive.AttrBitIsCoop)),
IsOwner: ava.IsOwner(mid),
}
ava.Archive.Attrs = attrs
ava.Videos = unpubedVideos
res.Archives = append(res.Archives, ava)
}
return
}
// ApplySearch all achive.
func (s *Service) ApplySearch(c context.Context, mid int64, tid int16, keyword, state string, pn, ps int) (res *search.StaffApplyResult, err error) {
var mids []int64
if res, err = s.sear.ArchivesStaffES(c, mid, tid, keyword, state, pn, ps); err != nil {
log.Error("s.arc.ArchivesStaffES(%d) error(%v)", mid, err)
return
}
// add arctype *must return
res.ArrType = []*search.TypeCount{}
for _, v := range s.p.TopTypesCache {
t := &search.TypeCount{
Tid: v.ID,
Name: v.Name,
}
if _, ok := res.Type[v.ID]; ok {
t.Count = res.Type[v.ID].Count
}
res.ArrType = append(res.ArrType, t)
}
if res == nil || len(res.Aids) == 0 {
return
}
// get archives
avm, err := s.arc.Views(c, mid, res.Aids, "")
if err != nil {
log.Error("s.arc.Views res.Aids(%v), ip(%s) err(%v)", res.Aids, err)
return
}
// get applies
apm := make(map[int64]*archive.StaffApply)
applies, err := s.arc.StaffApplies(c, mid, res.Aids)
for _, ap := range applies {
apm[ap.ApplyAID] = ap
}
// combine
for _, aid := range res.Aids {
av := avm[aid]
if av == nil {
continue
}
a := av.Archive
a.Cover = pubSvc.CoverURL(a.Cover)
ava := &archive.ArcVideoAudit{ArcVideo: av}
// typename
if _, ok := s.p.TypeMapCache[a.TypeID]; ok {
ava.TypeName = s.p.TypeMapCache[a.TypeID].Name
}
// parent typename
if _, ok := s.p.TypeMapCache[a.TypeID]; ok {
if _, ok := s.p.TypeMapCache[s.p.TypeMapCache[a.TypeID].Parent]; ok {
ava.ParentTName = s.p.TypeMapCache[s.p.TypeMapCache[a.TypeID].Parent].Name
}
}
// state panel
ava.StatePanel = archive.StatePanel(a.State)
// state desc
ava.Archive.StateDesc = s.c.StatDesc(int(a.State))
// not pubbed videos for reason
unpubedVideos := make([]*archive.Video, 0, len(ava.Videos))
for _, v := range ava.Videos {
if v.Status == -2 || v.Status == -4 || v.Status == -16 {
unpubedVideos = append(unpubedVideos, v)
}
}
c := len(unpubedVideos)
if c > 0 {
a.RejectReason = fmt.Sprintf("稿件中发现%d个问题。", c)
}
ava.Videos = unpubedVideos
// get apply
apply := &search.StaffApply{}
if v, ok := apm[aid]; ok {
apply.ID = v.ID
apply.Type = v.Type
apply.Mid = v.ApplyUpMID
apply.State = v.StaffState
apply.ApplyState = v.State
apply.ApplyTitle = v.ApplyTitle
}
// set archive
apply.Archive = ava
mids = append(mids, apply.Mid)
res.Applies = append(res.Applies, apply)
}
// get name
users, _ := s.acc.Infos(c, mids, "")
for _, v := range res.Applies {
if u, ok := users[v.Mid]; ok {
v.Uname = u.Name
}
}
return
}
// Types get typelist.
func (s *Service) Types(c context.Context, lang string) (tps []*archive.Type) {
if _, ok := s.p.TypesCache[lang]; !ok {
lang = "ch"
}
tps = s.p.TypesCache[lang]
return
}
// StaffTitles get staff titles.
func (s *Service) StaffTitles(c context.Context) (titles []*tag.StaffTitle) {
return s.p.StaffTitlesCache
}
// AppTypes fn
func (s *Service) AppTypes(c context.Context, lang string) (tps []*archive.Type) {
if _, ok := s.p.CTypesCache[lang]; !ok {
lang = "ch"
}
tps = s.p.CTypesCache[lang]
for _, val := range tps {
for _, child := range val.Children {
child.Notice = child.AppNotice
}
}
return
}
// Activities get activity list.
func (s *Service) Activities(c context.Context) (acts []*activity.Activity) {
acts = s.p.ActVideoAllCache
return
}
// WebArchives achive list with appeal.
func (s *Service) WebArchives(c context.Context, mid int64, tid int16, keyword, order, class, ip string, pn, ps, coop int) (res *search.Result, err error) {
if res, err = s.Search(c, mid, tid, keyword, order, class, ip, pn, ps, coop); err != nil {
log.Error("s.Search err(%v)", err)
return
}
if res == nil || len(res.Aids) == 0 {
return
}
//做降级
aps, err := s.ap.AppealList(c, mid, appeal.Business, ip)
if err != nil {
log.Error("s.ap.AppealList error(%v)", err)
err = nil
}
if len(aps) == 0 {
return
}
aaMap := make(map[int64]int64, len(aps))
for _, v := range aps {
if appeal.IsOpen(v.BusinessState) {
aaMap[v.Oid] = v.ID
}
}
for _, v := range res.Archives {
v.OpenAppeal = aaMap[v.Archive.Aid]
}
return
}
// Videos get Simple Archive and Videos Info.
func (s *Service) Videos(c context.Context, mid, aid int64, ip string) (sa archive.SimpleArchive, svs []*archive.SimpleVideo, err error) {
var av *archive.ArcVideo
if av, err = s.arc.View(c, mid, aid, ip, 0, 0); err != nil {
log.Error("s.arc.View(%d,%d) error(%v)", mid, aid, err)
return
}
if av == nil {
log.Error("s.arc.View(%d) not found", mid)
err = ecode.RequestErr
return
}
// white list check
isWhite := false
for _, m := range s.c.Whitelist.DataMids {
if m == mid {
isWhite = true
break
}
}
var (
a = av.Archive
vs = av.Videos
)
if !isWhite {
if a.Mid != mid {
err = ecode.AccessDenied
return
}
}
sa.Aid = a.Aid
sa.Title = a.Title
for _, v := range vs {
svs = append(svs, &archive.SimpleVideo{
Cid: v.Cid,
Title: v.Title,
Index: v.Index,
})
}
return
}
// ArchivesFromService get archives from service
func (s *Service) ArchivesFromService(c context.Context, mid int64, class, ip string, pn, ps int) (sres *search.Result, err error) {
aids, count, err := s.arc.UpArchives(c, mid, int64(pn), int64(ps), 0, ip)
if err != nil {
return
}
sres = &search.Result{}
sres.Aids = aids
sres.Page.Pn = pn
sres.Page.Ps = ps
sres.Page.Count = int(count)
return
}
// DescFormat get desc format
func (s *Service) DescFormat(c context.Context, typeid, copyright int64, langStr, ip string) (desc *archive.DescFormat, err error) {
lang := archive.ToLang(langStr)
desc, ok := s.p.DescFmtsCache[typeid][int8(copyright)][lang]
if !ok {
err = nil
}
if desc != nil {
var Components []*struct {
Name interface{}
}
if err = json.Unmarshal([]byte(desc.Components), &Components); err != nil || len(Components) == 0 {
desc = nil
err = nil
}
}
return
}
// AppFormats for app portal list.
func (s *Service) AppFormats(c context.Context) (af []*archive.AppFormat, err error) {
for _, f := range s.p.DescFmtsArrCache {
format := &archive.AppFormat{ID: f.ID, Copyright: f.Copyright, TypeID: f.TypeID}
af = append(af, format)
}
return
}
// Video get video by aid and cid
func (s *Service) Video(c context.Context, mid, aid, cid int64, ip string) (video *api.Page, err error) {
if video, err = s.arc.Video(c, aid, cid, ip); err != nil {
log.Error("s.arc.Video %d,%d,%s | err(%v)", aid, cid, ip, err)
}
return
}
// VideoJam get video traffic jam level from service
// level为0的时候可以忽略错误处理映射表里已经做了前端容错
func (s *Service) VideoJam(c context.Context, ip string) (j *archive.VideoJam, err error) {
level, _ := s.arc.VideoJam(c, ip)
if jam, ok := archive.VjInfo[level]; ok {
j = jam
} else {
j = archive.VjInfo[0]
}
return
}
// DescFormatForApp get desc format length
func (s *Service) DescFormatForApp(c context.Context, typeid, copyright int64, langStr, ip string) (desc *archive.DescFormat, length int, err error) {
var (
descLengthMax = 2000
descLengthMin = 250
ok bool
)
lang := archive.ToLang("")
if desc, ok = s.p.DescFmtsCache[typeid][int8(copyright)][lang]; !ok {
err = nil
}
if typeid == 0 {
length = descLengthMin
} else if desc != nil {
length = descLengthMax
} else {
length = descLengthMin
}
return
}
// Dpub for app view.
func (s *Service) Dpub() (dpub *archive.Dpub) {
now := time.Now()
dpub = &archive.Dpub{
Deftime: xtime.Time(now.Add(time.Duration(14400) * time.Second).Unix()),
DeftimeEnd: xtime.Time(now.Add(time.Duration(15*24) * time.Hour).Unix()),
DeftimeMsg: ecode.String(ecode.VideoupDelayTimeErr.Error()).Message(),
}
return
}
// SimpleArcVideos fn
func (s *Service) SimpleArcVideos(c context.Context, mid int64, tid int16, kw, order, class, ip string, pn, ps, coop int) (res *search.SimpleResult, err error) {
var sres *search.Result
res = &search.SimpleResult{}
if sres, err = s.sear.ArchivesES(c, mid, tid, kw, order, class, ip, pn, ps, coop); err != nil {
log.Error("s.arc.Search mid(%d)|error(%v)", mid, err)
sres, err = s.ArchivesFromService(c, mid, class, ip, pn, ps) // search err, use archive-service
if err != nil {
log.Error("s.ArchivesFromService mid(%d)|error(%v)", mid, err)
return
}
}
if sres == nil || len(sres.Aids) == 0 {
return
}
res.Class = sres.Class
res.Page = sres.Page
avm, err := s.arc.Views(c, mid, sres.Aids, ip)
if err != nil {
log.Error("s.arc.Views mid(%d)|aids(%v)|ip(%s)|err(%v)", mid, sres.Aids, ip, err)
return
}
savs := make([]*search.SimpleArcVideos, 0, len(avm))
for _, aid := range sres.Aids {
av, ok := avm[aid]
if !ok || av == nil || av.Archive == nil {
continue
}
vds := make([]*archive.SimpleVideo, 0, len(av.Videos))
for _, v := range av.Videos {
if v == nil {
continue
}
vd := &archive.SimpleVideo{
Cid: v.Cid,
Title: v.Title,
Index: v.Index,
}
vds = append(vds, vd)
}
sav := &search.SimpleArcVideos{}
sav.Archive = &archive.SimpleArchive{
Aid: av.Archive.Aid,
Title: av.Archive.Title,
}
sav.Videos = vds
savs = append(savs, sav)
}
res.ArchivesVideos = savs
return
}

View File

@@ -0,0 +1,17 @@
package archive
import (
"context"
"time"
model "go-common/app/interface/main/creative/model/archive"
"go-common/library/log"
)
// BIZsByTime list bizs by time and type
func (s *Service) BIZsByTime(c context.Context, start, end *time.Time, tp int8) (bizs []*model.BIZ, err error) {
if bizs, err = s.arc.BIZsByTime(c, start, end, tp); err != nil {
log.Error("s.arc.BIZsByTime error(%+v)", err)
}
return
}

View File

@@ -0,0 +1,43 @@
package archive
import (
"context"
"sort"
"strconv"
"go-common/app/interface/main/creative/model/archive"
)
// get max 5 fav types
func (s *Service) favTypes(c context.Context, mid int64) (favTps []*archive.Type) {
favTps = make([]*archive.Type, 0)
var res map[string]int64
res, _ = s.arc.FavTypes(c, mid)
if len(res) > 0 {
type kv struct {
TidStr string
Timestamp int64
}
var kvSlice []kv
for k, v := range res {
kvSlice = append(kvSlice, kv{k, v})
}
sort.Slice(kvSlice, func(i, j int) bool {
return kvSlice[i].Timestamp > kvSlice[j].Timestamp
})
for _, v := range kvSlice {
tid, _ := strconv.Atoi(v.TidStr)
if tp, ok := s.p.TypeMapCache[int16(tid)]; ok && len(favTps) < 5 {
favTps = append(favTps, tp)
}
}
}
return
}
// Fav fn
func (s *Service) Fav(c context.Context, mid int64) (res map[string]interface{}) {
res = make(map[string]interface{})
res["typelist"] = s.favTypes(c, mid)
return
}

View File

@@ -0,0 +1,41 @@
package archive
import (
"context"
"go-common/app/interface/main/creative/model/archive"
pubSvc "go-common/app/interface/main/creative/service"
"go-common/library/ecode"
"go-common/library/log"
)
// HistoryList get the history of aid
func (s *Service) HistoryList(c context.Context, mid, aid int64, ip string) (historys []*archive.ArcHistory, err error) {
if historys, err = s.arc.HistoryList(c, mid, aid, ip); err != nil {
log.Error("s.arc.HistoryList(%d,%d) err(%v)", mid, aid, err)
return
}
for key, history := range historys {
if history.Mid > 0 && history.Mid != mid {
err = ecode.ArchiveOwnerErr
return
}
historys[key].Cover = pubSvc.CoverURL(history.Cover)
}
return
}
// HistoryView get the history of hid
func (s *Service) HistoryView(c context.Context, mid, hid int64, ip string) (history *archive.ArcHistory, err error) {
if history, err = s.arc.HistoryView(c, mid, hid, ip); err != nil {
log.Error("s.arc.HistoryView(%d,%d) err(%v)", mid, hid, err)
return
}
if history.Mid > 0 && history.Mid != mid {
err = ecode.ArchiveOwnerErr
history = nil
return
}
history.Cover = pubSvc.CoverURL(history.Cover)
return
}

View File

@@ -0,0 +1,25 @@
package archive
import (
"context"
"go-common/app/interface/main/creative/model/activity"
"go-common/library/log"
)
// MissionProtocol fn
func (s *Service) MissionProtocol(c context.Context, missionID int64) (p *activity.Protocol, err error) {
if p, err = s.act.Protocol(c, missionID); err != nil {
log.Error("s.act.Protocol(%d) err(%v)", missionID, err)
return
}
return
}
// MissionOnlineByTid fn
func (s *Service) MissionOnlineByTid(c context.Context, tid, plat int16) (res []*activity.ActWithTP, err error) {
if res, err = s.act.MissionOnlineByTid(c, tid, plat); err != nil {
log.Error("s.act.MissionOnlineByTid(%d,%d) err(%+v)", tid, plat, err)
return
}
return
}

View File

@@ -0,0 +1,54 @@
package archive
import (
"context"
"go-common/library/log"
)
// AllowCommercial fn
func (s *Service) AllowCommercial(c context.Context, mid int64) (ok int) {
isOrder := s.AllowOrderUps(mid)
if isOrder {
log.Info("s.AllowOrderUps mid(%d)", mid)
ok = 1
}
return
}
// AppModuleShowMap fn
// 编辑的时候暂时不允许重新开启动态抽奖或者修改动态抽奖
func (s *Service) AppModuleShowMap(mid int64, lotteryCheck bool) (ret map[string]bool) {
ret = map[string]bool{
"cooperate": true,
"vote": true,
"subtitle": true,
"filter": true,
"audio_record": true,
"camera": true,
"sticker": true,
"videoup_sticker": true,
"theme": true,
"lottery": false,
}
// define by dymc check
if lotteryCheck {
ret["lottery"] = true
}
// isWhite := false
// for _, m := range s.c.Whitelist.ArcMids {
// if m == mid {
// isWhite = true
// break
// }
// }
// define for app module
// if isWhite {
// ret["theme"] = true
// return
// }
// mod := mid % 100
// if mod <= 20 {
// ret["theme"] = true
// }
return
}

View File

@@ -0,0 +1,18 @@
package archive
import (
"context"
)
// AddNetSafeMd5 fn
func (s *Service) AddNetSafeMd5(c context.Context, nid int64, md5 string) (err error) {
err = s.arc.AddNetSafeMd5(c, nid, md5)
go s.NotifyNetSafe(c, nid)
return
}
// NotifyNetSafe fn
func (s *Service) NotifyNetSafe(c context.Context, nid int64) (err error) {
_ = s.arc.NotifyNetSafe(c, nid)
return
}

View File

@@ -0,0 +1,170 @@
package archive
import (
"context"
"time"
"go-common/app/interface/main/creative/model/archive"
"go-common/app/interface/main/creative/model/game"
"go-common/app/interface/main/creative/model/order"
"go-common/app/service/main/archive/api"
arcMdl "go-common/app/service/main/archive/model/archive"
"go-common/library/ecode"
"go-common/library/log"
xtime "go-common/library/time"
)
// ExecuteOrders fn
func (s *Service) ExecuteOrders(c context.Context, mid int64, ip string) (orders []*order.Order, err error) {
if orders, err = s.order.ExecuteOrders(c, mid, ip); err != nil {
log.Error("s.order.ExecuteOrders mid(%d) err(%v)", mid, err)
return
}
return
}
// Oasis for orders.
func (s *Service) Oasis(c context.Context, mid int64, ip string) (oa *order.Oasis, err error) {
if oa, err = s.order.Oasis(c, mid, ip); err != nil {
log.Error("s.order.Oasis mid(%d) err(%v)", mid, err)
return
}
return
}
// ArcOrderGameInfo fn
// platform 1:android;2:ios
func (s *Service) ArcOrderGameInfo(c context.Context, aid int64, platform int, ip string) (gameInfo *game.Info, err error) {
var (
orderID, gameBaseID int64
beginDate xtime.Time
)
if orderID, _, gameBaseID, err = s.order.OrderByAid(c, aid); err != nil {
log.Error("s.order.OrderByAid aid(%d)|ip(%s)|err(%+v)", aid, ip, err)
err = ecode.NothingFound
return
}
if gameBaseID == 0 || orderID == 0 {
log.Error("s.order.OrderByAid aid(%d)|ip(%s) not found", aid, ip)
err = ecode.NothingFound
return
}
if gameInfo, err = s.game.Info(c, gameBaseID, platform, ip); err != nil {
log.Error("s.game.Info aid(%d)|orderID(%d)|gameBaseID(%d)|ip(%s)|err(%+v)", aid, orderID, gameBaseID, ip, err)
err = ecode.NothingFound
return
}
if !gameInfo.IsOnline {
log.Error("s.game.Info IsOnline is false aid(%d)|orderID(%d)|gameBaseID(%d)|ip(%s)|err(%+v)", aid, orderID, gameBaseID, ip, err)
err = ecode.NothingFound
return
}
if beginDate, err = s.order.LaunchTime(c, orderID, ip); err != nil {
log.Error("s.order.LaunchTime aid(%d)|orderID(%d)|gameBaseID(%d)|ip(%s)|err(%+v)", aid, orderID, gameBaseID, ip, err)
return
}
gameInfo.BeginDate = beginDate
gameInfo.BaseID = gameBaseID
return
}
// ArcCommercial fn
func (s *Service) ArcCommercial(c context.Context, aid int64, ip string) (cm *archive.Commercial, err error) {
var (
orderID, gameBaseID int64
beginDate xtime.Time
a *api.Arc
cache = true
)
// try cache
if cm, err = s.arc.ArcCMCache(c, aid); err != nil {
err = nil
cache = false
} else if cm != nil {
s.pCacheHit.Incr("cmarc_cache")
cache = false
return
}
s.pCacheMiss.Incr("cmarc_cache")
// get archive
a, err = s.arc.Archive(c, aid, ip)
if err != nil {
log.Error("arcCommercial aid(%d)|ip(%s)|err(%+v)", aid, ip, err)
err = ecode.NothingFound
return
}
if a == nil {
log.Error("arcCommercial nil aid(%d)|ip(%s)|err(%+v)", aid, ip, err)
err = ecode.NothingFound
return
}
// add cache
defer func() {
if cache {
s.addCache(func() {
if cm == nil {
cm = &archive.Commercial{}
}
s.arc.AddArcCMCache(context.Background(), aid, cm)
})
}
}()
// check order or porder
if a.OrderID > 0 {
// order
if orderID, _, gameBaseID, err = s.order.OrderByAid(c, aid); err != nil {
log.Error("arcCommercial aid(%d)|ip(%s)|error(%+v)", aid, ip, err)
err = ecode.NothingFound
return
}
if gameBaseID == 0 || orderID == 0 {
log.Error("arcCommercial aid(%d)|ip(%s) not found", aid, ip)
err = ecode.NothingFound
return
}
if beginDate, err = s.order.LaunchTime(c, orderID, ip); err != nil {
log.Error("arcCommercial get launch time failed. aid(%d)|orderID(%d)|gameBaseID(%d)|ip(%s)|error(%+v)", aid, orderID, gameBaseID, ip, err)
return
}
// check time
if time.Now().Unix() < beginDate.Time().Unix() {
log.Error("arcCommercial launch time invalid. aid(%d)|orderID(%d)|gameBaseID(%d) beginDate(%+v)", aid, orderID, gameBaseID, beginDate)
err = ecode.NothingFound
return
}
cm = &archive.Commercial{}
cm.AID = a.Aid
cm.OrderID = orderID
cm.GameID = gameBaseID
} else if a.AttrVal(arcMdl.AttrBitIsPorder) == arcMdl.AttrYes {
// porder
var pd *archive.Porder
if pd, err = s.arc.Porder(c, aid); err != nil {
log.Error("arcCommercial aid(%d) error(%v)", aid, err)
err = ecode.NothingFound
return
}
if pd == nil {
log.Error("arcCommercial porder not show aid(%d)", aid)
err = ecode.CreativePorderForbidShowFront
return
}
cm = &archive.Commercial{}
cm.AID = a.Aid
cm.POrderID = pd.ID
cm.GameID = pd.BrandID
} else {
log.Error("arcCommercial is not commercial. aid(%d)|ip(%s)|", aid, ip)
err = ecode.NothingFound
return
}
return
}
// UpValidate func
func (s *Service) UpValidate(c context.Context, mid int64, ip string) (uv *order.UpValidate, err error) {
if uv, err = s.order.UpValidate(c, mid, ip); err != nil {
log.Error("s.order.UpValidate mid(%d)|ip(%s)|err(%v)", mid, ip, err)
}
return
}

View File

@@ -0,0 +1,44 @@
package archive
import (
"context"
"go-common/app/interface/main/creative/model/archive"
"go-common/library/log"
)
// Porder fn
func (s *Service) Porder(c context.Context, aid int64) (pd *archive.Porder, err error) {
log.Warn("Porder with aid (%+v)", aid)
cache := true
if pd, err = s.arc.POrderCache(c, aid); err != nil {
err = nil
cache = false
} else if pd != nil {
s.pCacheHit.Incr("porder_cache")
return
}
s.pCacheMiss.Incr("porder_cache")
if pd, err = s.arc.Porder(c, aid); err != nil {
log.Error("s.porder.Porder aid(%d) err(%v)", aid, err)
return
}
if cache {
s.addCache(func() {
if pd == nil {
pd = &archive.Porder{}
}
s.arc.AddPOrderCache(context.Background(), aid, pd)
})
}
return
}
// FlowJudge fn
func (s *Service) FlowJudge(c context.Context, business, groupID int64, oids []int64) (hitOids []int64, err error) {
if hitOids, err = s.arc.FlowJudge(c, business, groupID, oids); err != nil {
log.Error("s.porder.FlowJudge business(%d) groupID(%d) err(%v)", business, groupID, err)
return
}
return
}

View File

@@ -0,0 +1,113 @@
package archive
import (
"context"
a "go-common/app/admin/main/videoup/model/archive"
)
// EditRules fn
func (s *Service) EditRules(c context.Context, white int, state int8, lotteryBind bool) (rules map[string]bool) {
var (
exist bool
rulesByArcState = make(map[int8]map[string]bool)
)
groupAllCan := map[string]bool{
"tid": true,
"title": true,
"tag": true,
"desc": true,
"dynamic": true,
"del_video": true,
"elec": true,
"add_video": true,
"dtime": true,
"source": true,
"no_reprint": true,
"cover": true,
"copyright": true,
"mission_tag": true,
"bind_lottery": false,
}
groupAllForbid := map[string]bool{
"tid": false,
"title": false,
"tag": false,
"desc": false,
"dynamic": false,
"del_video": false,
"elec": false,
"add_video": false,
"dtime": false,
"source": false,
"no_reprint": false,
"cover": false,
"copyright": false,
"mission_tag": false,
"bind_lottery": false,
}
groupForbidTidAndCopyright := map[string]bool{
"tid": false,
"title": true,
"tag": true,
"desc": true,
"dynamic": true,
"del_video": true,
"elec": true,
"add_video": true,
"dtime": true,
"source": true,
"no_reprint": true,
"cover": true,
"copyright": false,
"mission_tag": false,
"bind_lottery": false,
}
groupForbidTidAndCopyrightDtime := map[string]bool{
"tid": false,
"title": true,
"tag": true,
"desc": true,
"dynamic": true,
"del_video": true,
"elec": true,
"add_video": true,
"dtime": false,
"source": true,
"no_reprint": true,
"cover": true,
"copyright": false,
"mission_tag": false,
"bind_lottery": false,
}
rulesByArcState[a.StateOrange] = groupForbidTidAndCopyrightDtime
rulesByArcState[a.StateOpen] = groupForbidTidAndCopyrightDtime
rulesByArcState[a.StateForbidWait] = groupForbidTidAndCopyright
rulesByArcState[a.StateForbidAdminDelay] = groupForbidTidAndCopyright
rulesByArcState[a.StateForbidSubmit] = groupForbidTidAndCopyright
rulesByArcState[a.StateForbidUserDelay] = groupForbidTidAndCopyrightDtime
rulesByArcState[a.StateForbidXcodeFail] = groupForbidTidAndCopyright
rulesByArcState[a.StateForbidPolice] = groupAllForbid
rulesByArcState[a.StateForbidLock] = groupAllForbid
rulesByArcState[a.StateForbidFackLock] = groupAllForbid
rulesByArcState[a.StateForbidUpDelete] = groupAllForbid
rulesByArcState[a.StateForbitUpLoad] = groupForbidTidAndCopyright
rulesByArcState[a.StateForbidOnlyComment] = groupForbidTidAndCopyright
rulesByArcState[a.StateForbidDispatch] = groupForbidTidAndCopyright
rulesByArcState[a.StateForbidFixing] = groupForbidTidAndCopyright
rulesByArcState[a.StateForbidStorageFail] = groupForbidTidAndCopyright
rulesByArcState[a.StateForbidWaitXcode] = groupForbidTidAndCopyright
rulesByArcState[a.StateForbidTmpRecicle] = groupAllCan
rulesByArcState[a.StateForbidRecycle] = groupAllCan
rulesByArcState[a.StateForbidFixed] = groupForbidTidAndCopyrightDtime
rulesByArcState[a.StateForbidLater] = groupForbidTidAndCopyrightDtime
rulesByArcState[a.StateForbidPatched] = groupForbidTidAndCopyrightDtime
if rules, exist = rulesByArcState[state]; exist {
if white == 0 {
rules["add_video"] = false
}
rules["bind_lottery"] = lotteryBind
}
return
}

View File

@@ -0,0 +1,144 @@
package archive
import (
"context"
"time"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/dao/account"
"go-common/app/interface/main/creative/dao/activity"
"go-common/app/interface/main/creative/dao/appeal"
"go-common/app/interface/main/creative/dao/archive"
"go-common/app/interface/main/creative/dao/coin"
gD "go-common/app/interface/main/creative/dao/game"
"go-common/app/interface/main/creative/dao/order"
"go-common/app/interface/main/creative/dao/search"
"go-common/app/interface/main/creative/dao/tag"
"go-common/app/interface/main/creative/dao/template"
actmdl "go-common/app/interface/main/creative/model/activity"
"go-common/app/interface/main/creative/model/game"
"go-common/app/interface/main/creative/service"
"go-common/library/log"
"go-common/library/stat/prom"
)
//Service struct
type Service struct {
c *conf.Config
arc *archive.Dao
acc *account.Dao
sear *search.Dao
act *activity.Dao
tpl *template.Dao
coin *coin.Dao
order *order.Dao
ap *appeal.Dao
tag *tag.Dao
game *gD.Dao
p *service.Public
prom *prom.Prom
missch chan func()
pCacheHit *prom.Prom
pCacheMiss *prom.Prom
// cache
orderUps map[int64]int64
gameMap map[int64]*game.ListItem
ArcTip string
}
//New get service
func New(c *conf.Config, rpcdaos *service.RPCDaos, p *service.Public) *Service {
s := &Service{
c: c,
arc: rpcdaos.Arc,
acc: rpcdaos.Acc,
sear: search.New(c),
act: activity.New(c),
tpl: template.New(c),
tag: tag.New(c),
coin: coin.New(c),
order: order.New(c),
ap: appeal.New(c),
game: gD.New(c),
p: p,
prom: prom.BusinessInfoCount,
missch: make(chan func(), 1024),
pCacheHit: prom.CacheHit,
pCacheMiss: prom.CacheMiss,
ArcTip: c.Host.ArcTip,
}
s.loadOrderUps()
s.loadAllGameMap()
go s.loadproc()
go s.cacheproc()
return s
}
// TopAct fn
func (s *Service) TopAct() (ret []*actmdl.Activity) {
return s.p.TopActCache
}
func (s *Service) loadOrderUps() {
orderUps, err := s.order.Ups(context.TODO())
if err != nil {
return
}
s.orderUps = orderUps
}
func (s *Service) loadAllGameMap() {
list, err := s.game.List(context.TODO(), "", "")
if err != nil || list == nil || len(list) == 0 {
return
}
s.gameMap = make(map[int64]*game.ListItem)
for _, v := range list {
s.gameMap[v.GameBaseID] = v
}
log.Info("s.loadAllGameMap: s.gameMapLen(%d)", len(s.gameMap))
}
// loadproc
func (s *Service) loadproc() {
for {
time.Sleep(5 * time.Minute)
s.loadOrderUps()
s.loadAllGameMap()
}
}
// AllowOrderUps 检查用户商单信息
func (s *Service) AllowOrderUps(mid int64) (ok bool) {
_, ok = s.orderUps[mid]
return
}
// AddCache add to chan for cache
func (s *Service) addCache(f func()) {
select {
case s.missch <- f:
default:
log.Warn("cacheproc chan full")
}
}
// cacheproc is a routine for execute closure.
func (s *Service) cacheproc() {
for {
f := <-s.missch
f()
}
}
// Ping service
func (s *Service) Ping(c context.Context) (err error) {
if err = s.arc.Ping(c); err != nil {
log.Error("s.archive.Dao.PingDb err(%v)", err)
}
return
}
// Close dao
func (s *Service) Close() {
s.arc.Close()
}

View File

@@ -0,0 +1,175 @@
package archive
import (
"context"
"flag"
"fmt"
"path/filepath"
"testing"
"time"
"github.com/davecgh/go-spew/spew"
"go-common/app/interface/main/creative/conf"
arcmdl "go-common/app/interface/main/creative/model/archive"
"go-common/app/interface/main/creative/model/order"
"go-common/app/interface/main/creative/service"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
p *service.Public
)
func init() {
dir, _ := filepath.Abs("../../cmd/creative.toml")
flag.Set("conf", dir)
conf.Init()
rpcdaos := service.NewRPCDaos(conf.Conf)
p = service.New(conf.Conf, rpcdaos)
s = New(conf.Conf, rpcdaos, p)
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
Reset(func() {})
f(s)
}
}
func ctx() context.Context {
return context.Background()
}
func Test_Oasis(t *testing.T) {
Convey("should get user oasis info", t, func() {
res, err := s.Oasis(ctx(), 27515256, "127.0.0.1")
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}
func Test_Order(t *testing.T) {
var (
c = ctx()
err error
MID = int64(27515256)
orders []*order.Order
oasis *order.Oasis
)
Convey("ExecuteOrders", t, WithService(func(s *Service) {
orders, err = s.ExecuteOrders(c, MID, "127.0.0.1")
So(err, ShouldBeNil)
spew.Dump(orders)
}))
Convey("Oasis", t, WithService(func(s *Service) {
oasis, err = s.Oasis(c, MID, "127.0.0.1")
So(err, ShouldBeNil)
spew.Dump(oasis)
}))
}
func Test_ServiceBasic(t *testing.T) {
var (
c = context.Background()
err error
)
Convey("ServiceClose", t, WithService(func(s *Service) {
s.Close()
}))
Convey("Ping", t, WithService(func(s *Service) {
err = s.Ping(c)
So(err, ShouldBeNil)
}))
Convey("AppModuleShowMap", t, WithService(func(s *Service) {
var res map[string]bool
mid := int64(91513044)
res = s.AppModuleShowMap(mid, false)
So(res, ShouldNotBeNil)
}))
}
func Test_NetSafe(t *testing.T) {
var (
c = context.Background()
err error
nid int64
md5 string
)
nid = 123
md5 = "iamamd5string"
Convey("AddNetSafeMd5", t, WithService(func(s *Service) {
err = s.AddNetSafeMd5(c, nid, md5)
So(err, ShouldBeNil)
}))
Convey("NotifyNetSafe", t, WithService(func(s *Service) {
err = s.NotifyNetSafe(c, nid)
So(err, ShouldBeNil)
}))
}
func Test_DescFormat(t *testing.T) {
var (
c = context.Background()
err error
typeid, copyright int64
langStr, ip string
desc *arcmdl.DescFormat
af []*arcmdl.AppFormat
length int
)
Convey("DescFormat", t, WithService(func(s *Service) {
desc, err = s.DescFormat(c, typeid, copyright, langStr, ip)
So(err, ShouldBeNil)
So(desc, ShouldNotBeNil)
}))
Convey("DescFormatForApp", t, WithService(func(s *Service) {
desc, length, err = s.DescFormatForApp(c, typeid, copyright, langStr, ip)
So(err, ShouldBeNil)
So(desc, ShouldNotBeNil)
So(length, ShouldNotBeNil)
So(length, ShouldBeGreaterThanOrEqualTo, 0)
}))
Convey("AppFormats", t, WithService(func(s *Service) {
af, err = s.AppFormats(c)
So(err, ShouldBeNil)
So(af, ShouldNotBeNil)
So(len(af), ShouldBeGreaterThanOrEqualTo, 0)
}))
}
func Test_Arc(t *testing.T) {
var (
c = context.Background()
err error
mid, aid int64
ak, ck, ip = "", "", ""
ap *arcmdl.SimpleArchiveVideos
)
Convey("SimpleArchiveVideos", t, WithService(func(s *Service) {
ap, err = s.SimpleArchiveVideos(c, mid, aid, ak, ck, ip)
So(err, ShouldBeNil)
So(ap, ShouldNotBeNil)
}))
}
func TestArchiveBIZsByTime(t *testing.T) {
Convey("BIZsByTime", t, WithService(func(s *Service) {
var (
c = context.Background()
start = time.Unix(1544000000, 0)
end = time.Unix(1544008000, 0)
tp = int8(2)
)
// mock bizs
Convey("When everything gose positive", WithService(func(s *Service) {
bizs, err := s.BIZsByTime(c, &start, &end, tp)
Convey("Then err should be nil.bizs should not be nil.", func(ctx C) {
So(err, ShouldBeNil)
So(bizs, ShouldNotBeNil)
fmt.Println(bizs[0])
})
}))
}))
}

View File

@@ -0,0 +1,15 @@
package archive
import (
"context"
)
// StaffApplySubmit fn
func (s *Service) StaffApplySubmit(c context.Context, id, aid, mid, state, atype int64, flagAddBlack, flagRefuse int) (err error) {
return s.arc.StaffApplySubmit(c, id, aid, mid, state, atype, flagAddBlack, flagRefuse)
}
// StaffValidate func
func (s *Service) StaffValidate(c context.Context, mid int64) (uv int, err error) {
return s.arc.StaffMidValidate(c, mid)
}

View File

@@ -0,0 +1,38 @@
package archive
import (
"context"
"go-common/app/interface/main/creative/model/tag"
"go-common/library/ecode"
"go-common/library/log"
)
// TagCheck fn
func (s *Service) TagCheck(c context.Context, mid int64, tagName string) (code int, msg string) {
var (
err error
t *tag.Tag
)
for _, act := range s.p.ActVideoAllCache {
if act.Tags == tagName {
code = 1
msg = "当前tag为活动专用不允许自定义添加请先删除之后重选对应的活动"
return
}
}
if t, err = s.tag.TagCheck(c, mid, tagName); err != nil {
log.Error("s.tag.TagCheck mid(%d)|tagName(%s)|err(%v)", mid, tagName, err)
code = 1
msg = ecode.String(err.Error()).Message()
return
}
if t != nil && (t.State == tag.TagStateDel ||
t.State == tag.TagStateHide ||
t.Type == tag.OfficailActiveTag) {
code = 1
msg = "非法Tag不允许Up主使用"
return
}
return
}

View File

@@ -0,0 +1,32 @@
package archive
import (
"context"
"go-common/app/interface/main/creative/model/archive"
"go-common/library/ecode"
"go-common/library/log"
)
// VideoPoints 获取视频最新生效的高能看点
func (s *Service) VideoPoints(c context.Context, aid, cid int64) (vp *archive.ViewPointRow, err error) {
vp, err = s.arc.ViewPoint(c, aid, cid)
return
}
// WebViewPoints 创作中心高能看点接口
func (s *Service) WebViewPoints(c context.Context, aid, cid, mid int64, ip string) (vps []*archive.ViewPointRow, err error) {
a, err := s.arc.Archive(c, aid, ip)
if err != nil {
return
}
if a.Author.Mid != mid {
err = ecode.AccessDenied
log.Error("WebViewPoints() wrong auth. Login mid(%d) archive mid(%d)", mid, a.Author.Mid)
return
}
if vps, err = s.arc.RawViewPoints(c, aid, cid, 3); err != nil {
log.Error("s.arc.RawViewPoints(%d,%d) error(%v)", aid, cid, err)
return
}
return
}

View File

@@ -0,0 +1,46 @@
package service
import (
"testing"
"context"
"github.com/davecgh/go-spew/spew"
. "github.com/smartystreets/goconvey/convey"
)
func Test_BGM(t *testing.T) {
Convey("bgm", t, WithService(func(p *Public) {
Convey("bgm", func() {
res, err := p.BgmBindList(context.TODO(), 10110983, 10135130, 3, false)
if err == nil {
spew.Dump(res)
}
spew.Dump("bgm")
})
}))
}
func Test_Type(t *testing.T) {
Convey("Type", t, WithService(func(p *Public) {
Convey("loadTypes", func() {
p.loadTypes()
spew.Dump(p.TopTypesCache)
})
// Convey("loadDescFormat", func() {
// p.loadDescFormat()
// spew.Dump(p.DescFmtsCache)
// })
}))
}
func Test_Staff(t *testing.T) {
Convey("Staff", t, WithService(func(p *Public) {
Convey("Staff", func() {
res, err := p.StaffList(context.TODO(), 10110983, false)
if err == nil {
spew.Dump(res)
}
spew.Dump("Staff")
})
}))
}

View File

@@ -0,0 +1,61 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//app/interface/openplatform/article/model:go_default_library",
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"article.go",
"draft.go",
"pre.go",
"service.go",
],
importpath = "go-common/app/interface/main/creative/service/article",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/dao/account:go_default_library",
"//app/interface/main/creative/dao/activity:go_default_library",
"//app/interface/main/creative/dao/article:go_default_library",
"//app/interface/main/creative/dao/bfs:go_default_library",
"//app/interface/main/creative/model/article:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//app/interface/openplatform/article/model:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,206 @@
package article
import (
"context"
artMdl "go-common/app/interface/main/creative/model/article"
article "go-common/app/interface/openplatform/article/model"
"go-common/library/ecode"
"go-common/library/log"
"strconv"
)
// SubArticle submit article.
func (s *Service) SubArticle(c context.Context, mid int64, art *artMdl.ArtParam, ak, ck, ip string) (aid int64, err error) {
identified, _ := s.acc.IdentifyInfo(c, mid, 0, ip)
if err = s.acc.CheckIdentify(identified); err != nil {
log.Error("s.acc.IdentifyInfo mid(%d),ip(%s)", mid, ip)
return
}
aid, err = s.art.AddArticle(c, art)
return
}
// UpdateArticle update article.
func (s *Service) UpdateArticle(c context.Context, mid int64, art *artMdl.ArtParam, ak, ck, ip string) (err error) {
identified, _ := s.acc.IdentifyInfo(c, mid, 0, ip)
if err = s.acc.CheckIdentify(identified); err != nil {
log.Error("s.acc.IdentifyInfo mid(%d),ip(%s)", mid, ip)
return
}
return s.art.UpdateArticle(c, art)
}
// DelArticle delete article.
func (s *Service) DelArticle(c context.Context, aid, mid int64, ip string) (err error) {
if err = s.art.DelArticle(c, aid, mid, ip); err != nil {
log.Error("s.art.DelArticle(%d) error(%v)", aid, err)
return
}
return
}
// View get article detail.
func (s *Service) View(c context.Context, aid, mid int64, ip string) (res *artMdl.Meta, err error) {
var art *article.Article
if art, err = s.art.Article(c, aid, mid, ip); err != nil {
return
}
res = &artMdl.Meta{
ID: art.ID,
Category: art.Category,
Title: art.Title,
Content: art.Content,
Summary: art.Summary,
BannerURL: art.BannerURL,
TemplateID: art.TemplateID,
State: art.State,
Reprint: art.Reprint,
Reason: art.Reason,
PTime: art.PublishTime,
Author: art.Author,
Stats: art.Stats,
CTime: art.Ctime,
MTime: art.Mtime,
DynamicIntro: art.Dynamic,
ImageURLs: art.ImageURLs,
OriginImageURLs: art.OriginImageURLs,
}
if res.ImageURLs == nil {
res.ImageURLs = []string{}
}
if res.OriginImageURLs == nil {
res.OriginImageURLs = []string{}
}
if len(art.Tags) > 0 {
var tags []string
for _, v := range art.Tags {
tags = append(tags, v.Name)
}
res.Tags = tags
}
return
}
// Articles get article list.
func (s *Service) Articles(c context.Context, mid int64, pn, ps, sort, group, category int, ip string) (arts *artMdl.ArtList, err error) {
var res *article.CreationArts
res, err = s.art.Articles(c, mid, pn, ps, sort, group, category, ip)
if err != nil || res == nil || res.Articles == nil || len(res.Articles) <= 0 {
if err != nil {
log.Error("s.art.Articles(%d) res(%v) error(%v)", mid, res, err)
}
return
}
ms := make([]*artMdl.Meta, 0, len(res.Articles))
for _, v := range res.Articles {
id := strconv.FormatInt(v.ID, 10)
m := &artMdl.Meta{
ID: v.ID,
Category: v.Category,
Title: v.Title,
Summary: v.Summary,
BannerURL: v.BannerURL,
TemplateID: v.TemplateID,
State: v.State,
Reprint: v.Reprint,
Reason: v.Reason,
PTime: v.PublishTime,
Author: v.Author,
Stats: v.Stats,
CTime: v.Ctime,
MTime: v.Mtime,
EditURL: "https://member.bilibili.com/article-text/mobile?aid=" + id + "&type=2",
DynamicIntro: v.Dynamic,
ImageURLs: v.ImageURLs,
OriginImageURLs: v.OriginImageURLs,
}
if m.ImageURLs == nil {
m.ImageURLs = []string{}
}
if m.OriginImageURLs == nil {
m.OriginImageURLs = []string{}
}
if m.State == 0 {
m.ViewURL = "https://www.bilibili.com/read/cv" + id
m.IsPreview = 0
} else { //预览
m.ViewURL = "https://www.bilibili.com/read/preview/" + id
m.IsPreview = 1
}
tags := []string{}
m.Tags = tags
if len(v.Tags) > 0 {
for _, vv := range v.Tags {
tags = append(tags, vv.Name)
}
m.Tags = tags
}
ms = append(ms, m)
}
arts = &artMdl.ArtList{}
arts.Articles = ms
arts.Page = res.Page
arts.Type = res.Type
return
}
// Categories get article category.
func (s *Service) Categories(c context.Context) (*article.Categories, error) {
return s.art.Categories(c, "")
}
// WithDrawArticle withdraw article.
func (s *Service) WithDrawArticle(c context.Context, aid, mid int64, ip string) (err error) {
if err = s.art.WithDrawArticle(c, aid, mid, ip); err != nil {
log.Error("s.art.WithdrawArticle(%d,%d) error(%v)", aid, mid, err)
}
return
}
// ArticleUpCover article upload cover.
func (s *Service) ArticleUpCover(c context.Context, fileType string, body []byte) (url string, err error) {
if len(body) == 0 {
err = ecode.FileNotExists
log.Error("s.ArticleUpCover file not exist")
return
}
if len(body) > s.c.BFS.MaxFileSize {
log.Error("s.ArticleUpCover too max file size")
err = ecode.FileTooLarge
return
}
url, err = s.bfs.Upload(c, fileType, body)
if err != nil {
log.Error("s.bfs.Upload error(%v)", err)
}
return
}
// IsAuthor checks that whether user has permission to write article.
func (s *Service) IsAuthor(c context.Context, mid int64, ip string) (ok bool, err error) {
if ok, err = s.art.IsAuthor(c, mid, ip); err != nil {
log.Error("s.art.IsAuthor(%v)", err)
}
return
}
// RemainCount article up limit.
func (s *Service) RemainCount(c context.Context, mid int64, ip string) (rc int, err error) {
rc, err = s.art.RemainCount(c, mid, ip)
return
}
// ArticleCapture article capture.
func (s *Service) ArticleCapture(c context.Context, url string) (loc string, size int, err error) {
loc, size, err = s.bfs.Capture(c, url)
if err != nil {
log.Error("s.bfs.Capture error(%v)", err)
}
return
}
// ArticleStat get article base data.
func (s *Service) ArticleStat(c context.Context, mid int64, ip string) (stat article.UpStat, err error) {
stat, err = s.art.ArticleStat(c, mid, ip)
return
}

View File

@@ -0,0 +1,117 @@
package article
import (
"context"
artMdl "go-common/app/interface/main/creative/model/article"
article "go-common/app/interface/openplatform/article/model"
"go-common/library/ecode"
"go-common/library/log"
)
// AddDraft add draft.
func (s *Service) AddDraft(c context.Context, mid int64, art *artMdl.ArtParam) (aid int64, err error) {
return s.art.AddDraft(c, art)
}
// DelDraft delete draft.
func (s *Service) DelDraft(c context.Context, aid, mid int64, ip string) (err error) {
if err = s.art.DelDraft(c, aid, mid, ip); err != nil {
log.Error("s.art.DelArticle(%d) error(%v)", aid, err)
}
return
}
// Draft get draft.
func (s *Service) Draft(c context.Context, aid, mid int64, ip string) (res *artMdl.Meta, err error) {
var df *article.Draft
if df, err = s.art.Draft(c, aid, mid, ip); err != nil {
return
}
if df == nil || df.Article == nil {
err = ecode.CreativeArticleNotExist
return
}
res = &artMdl.Meta{
ID: df.Article.ID,
Category: df.Article.Category,
Title: df.Article.Title,
Content: df.Article.Content,
Summary: df.Article.Summary,
BannerURL: df.Article.BannerURL,
TemplateID: df.Article.TemplateID,
State: df.Article.State,
Author: df.Article.Author,
Stats: df.Article.Stats,
Reprint: df.Article.Reprint,
Reason: df.Article.Reason,
PTime: df.Article.PublishTime,
CTime: df.Article.Ctime,
MTime: df.Article.Mtime,
DynamicIntro: df.Article.Dynamic,
ImageURLs: df.ImageURLs,
OriginImageURLs: df.OriginImageURLs,
}
if res.ImageURLs == nil {
res.ImageURLs = []string{}
}
if res.OriginImageURLs == nil {
res.OriginImageURLs = []string{}
}
res.Tags = df.Tags
if len(df.Tags) == 0 {
res.Tags = []string{}
}
return
}
// Drafts get draft list.
func (s *Service) Drafts(c context.Context, mid int64, pn, ps int, ip string) (dls *artMdl.DraftList, err error) {
var res *article.Drafts
res, err = s.art.Drafts(c, mid, pn, ps, ip)
if err != nil || res == nil || res.Drafts == nil || len(res.Drafts) <= 0 {
if err != nil {
log.Error("s.art.Drafts(%d) res(%v) error(%v)", mid, res, err)
}
return
}
ms := make([]*artMdl.Meta, 0, len(res.Drafts))
for _, v := range res.Drafts {
m := &artMdl.Meta{
ID: v.ID,
Category: v.Category,
Title: v.Title,
Summary: v.Summary,
BannerURL: v.BannerURL,
TemplateID: v.TemplateID,
State: v.State,
Reprint: v.Reprint,
Reason: v.Reason,
PTime: v.PublishTime,
Author: v.Author,
Stats: v.Stats,
CTime: v.Ctime,
MTime: v.Mtime,
DynamicIntro: v.Dynamic,
ImageURLs: v.ImageURLs,
OriginImageURLs: v.OriginImageURLs,
}
if m.ImageURLs == nil {
m.ImageURLs = []string{}
}
if m.OriginImageURLs == nil {
m.OriginImageURLs = []string{}
}
m.Tags = v.Tags
if len(v.Tags) == 0 {
m.Tags = []string{}
}
ms = append(ms, m)
}
dls = &artMdl.DraftList{
DraftURL: s.c.H5Page.Draft,
}
dls.Drafts = ms
dls.Page = res.Page
return
}

View File

@@ -0,0 +1,99 @@
package article
import (
"context"
"strconv"
"strings"
artMdl "go-common/app/interface/main/creative/model/article"
"go-common/library/ecode"
)
// ParseParam parse article param which type is int.
func (s *Service) ParseParam(c context.Context, categoryStr, reprintStr, tidStr, imageURLs, originImageURLs string) (art *artMdl.ArtParam, err error) {
var (
category int64
tid, reprint int
)
category, err = strconv.ParseInt(categoryStr, 10, 64)
if err != nil || category <= 0 { //文章要求必须传大于0的分类
err = ecode.CreativeArticleCategoryErr
return
}
tid, err = strconv.Atoi(tidStr)
if err != nil || tid < 0 {
err = ecode.CreativeArticleTIDErr
return
}
reprint, err = strconv.Atoi(reprintStr)
if err != nil || reprint < 0 {
err = ecode.CreativeArticleReprintErr
return
}
imgs, oimgs, err := ParseImageURLs(imageURLs, originImageURLs)
if err != nil {
return
}
art = &artMdl.ArtParam{
Category: category,
TemplateID: int32(tid),
Reprint: int32(reprint),
ImageURLs: imgs,
OriginImageURLs: oimgs,
}
return
}
// ParseDraftParam parse draft param which type is int.
func (s *Service) ParseDraftParam(c context.Context, categoryStr, reprintStr, tidStr, imageURLs, originImageURLs string) (art *artMdl.ArtParam, err error) {
var (
category int64
tid, reprint int
)
if categoryStr != "" {
category, err = strconv.ParseInt(categoryStr, 10, 64)
if err != nil || category < 0 {
err = ecode.CreativeArticleCategoryErr
return
}
}
if tidStr != "" {
tid, err = strconv.Atoi(tidStr)
if err != nil || tid < 0 {
err = ecode.CreativeArticleTIDErr
return
}
}
if reprintStr != "" {
reprint, err = strconv.Atoi(reprintStr)
if err != nil || reprint < 0 {
err = ecode.CreativeArticleReprintErr
return
}
}
imgs, oimgs, err := ParseImageURLs(imageURLs, originImageURLs)
if err != nil {
return
}
art = &artMdl.ArtParam{
Category: category,
TemplateID: int32(tid),
Reprint: int32(reprint),
ImageURLs: imgs,
OriginImageURLs: oimgs,
}
return
}
//ParseImageURLs parse img urls to []string.
func ParseImageURLs(imageURLs, originImageURLs string) (imgs, oimgs []string, err error) {
if originImageURLs == "" {
originImageURLs = imageURLs
}
imgs = strings.Split(imageURLs, ",")
oimgs = strings.Split(originImageURLs, ",")
if len(imgs) != len(oimgs) {
err = ecode.CreativeArticleImageURLsErr
}
return
}

View File

@@ -0,0 +1,31 @@
package article
import (
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/dao/account"
"go-common/app/interface/main/creative/dao/activity"
"go-common/app/interface/main/creative/dao/article"
"go-common/app/interface/main/creative/dao/bfs"
"go-common/app/interface/main/creative/service"
)
//Service struct.
type Service struct {
c *conf.Config
art *article.Dao
acc *account.Dao
bfs *bfs.Dao
act *activity.Dao
}
//New get service.
func New(c *conf.Config, rpcdaos *service.RPCDaos) *Service {
s := &Service{
c: c,
art: rpcdaos.Art,
acc: rpcdaos.Acc,
bfs: bfs.New(c),
act: activity.New(c),
}
return s
}

View File

@@ -0,0 +1,64 @@
package article
import (
"context"
"flag"
"go-common/app/interface/main/creative/conf"
article "go-common/app/interface/openplatform/article/model"
"path/filepath"
"testing"
"time"
"github.com/davecgh/go-spew/spew"
. "github.com/smartystreets/goconvey/convey"
"go-common/app/interface/main/creative/service"
)
var (
s *Service
)
func init() {
dir, _ := filepath.Abs("../../cmd/creative.toml")
flag.Set("conf", dir)
conf.Init()
rpcdaos := service.NewRPCDaos(conf.Conf)
s = New(conf.Conf, rpcdaos)
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
Reset(func() {})
f(s)
}
}
func Test_Categories(t *testing.T) {
var (
c = context.TODO()
err error
res *article.Categories
)
Convey("Categories", t, WithService(func(s *Service) {
res, err = s.Categories(c)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
}))
}
func Test_Article(t *testing.T) {
var (
c = context.TODO()
err error
size int
loc string
url = "https://i0.hdslb.com/bfs/article/8fce42a26ce128140d2ee7dec599a46cd1bccbb6.jpg"
)
Convey("Capture", t, WithService(func(s *Service) {
loc, size, err = s.ArticleCapture(c, url)
So(err, ShouldBeNil)
spew.Dump(loc, size)
}))
}

View File

@@ -0,0 +1,60 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/assist:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"assist.go",
"live.go",
"revoc.go",
"service.go",
],
importpath = "go-common/app/interface/main/creative/service/assist",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/dao/account:go_default_library",
"//app/interface/main/creative/dao/assist:go_default_library",
"//app/interface/main/creative/dao/danmu:go_default_library",
"//app/interface/main/creative/dao/reply:go_default_library",
"//app/interface/main/creative/model/assist:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//app/service/main/account/model:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,255 @@
package assist
import (
"context"
"go-common/app/interface/main/creative/model/assist"
account "go-common/app/service/main/account/model"
"go-common/library/ecode"
"go-common/library/log"
"strconv"
)
// Assists get assists
func (s *Service) Assists(c context.Context, mid int64, ip string) (assists []*assist.Assist, err error) {
var (
mainAssists []*assist.Assist
liveAssists []*assist.LiveAssist
rightsMap = make(map[int64]*assist.Rights, 20)
mainMap = make(map[int64]*assist.Assist, 10)
assistMids []int64
liveAssistMids []int64
liveAssistsTotal map[int64]map[int8]map[int8]int
)
// main assists
if mainAssists, err = s.assist.Assists(c, mid, ip); err != nil {
log.Error("s.assist.Assists err(%v) | mid(%d), ip(%s)", err, mid, ip)
return
}
// live assists
if liveAssists, err = s.assist.LiveAssists(c, mid, ip); err != nil {
log.Error("s.assist.Assists err(%v) | mid(%d), ip(%s)", err, mid, ip)
return
}
// rights info
for _, ass := range mainAssists {
rightsMap[ass.AssistMid] = &assist.Rights{Main: 1}
mainMap[ass.AssistMid] = ass
}
for _, ass := range liveAssists {
if _, ok := rightsMap[ass.AssistMid]; !ok {
rightsMap[ass.AssistMid] = &assist.Rights{Live: 1}
} else {
rightsMap[ass.AssistMid].Live = 1
}
liveAssistMids = append(liveAssistMids, ass.AssistMid)
}
// get live assist total
if len(liveAssistMids) > 0 {
liveAssistsTotal, _ = s.assist.Stat(c, mid, liveAssistMids, ip)
}
// get user info
for mid := range rightsMap {
assistMids = append(assistMids, mid)
}
users, err := s.acc.Infos(c, assistMids, ip)
if err != nil {
log.Error("s.acc.Infos() err(%v)", err)
return
}
for _, ast := range mainAssists {
if _, ok := users[ast.AssistMid]; ok {
ast.AssistAvatar = users[ast.AssistMid].Face
ast.AssistName = users[ast.AssistMid].Name
ast.Banned, _ = s.userBanned(c, ast.AssistMid)
ast.Rights = rightsMap[ast.AssistMid]
assists = append(assists, ast)
}
}
for _, ass := range liveAssists {
if _, ok := mainMap[ass.AssistMid]; !ok {
if _, ok := users[ass.AssistMid]; ok {
ast := &assist.Assist{}
ast.AssistMid = ass.AssistMid
ast.AssistAvatar = users[ass.AssistMid].Face
ast.AssistName = users[ass.AssistMid].Name
ast.CTime = ass.CTime
ast.MTime = ass.CTime
ast.Banned, _ = s.userBanned(c, ass.AssistMid)
ast.Rights = rightsMap[ass.AssistMid]
if _, ok := liveAssistsTotal[ass.AssistMid]; ok {
ast.Total = liveAssistsTotal[ast.AssistMid]
}
assists = append(assists, ast)
}
}
}
return
}
// AssistLogs get all assistlog by Mid, and format by typeid
func (s *Service) AssistLogs(c context.Context, mid, assistMid, pn, ps, stime, etime int64, ip string) (assistLogs []*assist.AssistLog, pager map[string]int64, err error) {
if assistLogs, pager, err = s.assist.AssistLogs(c, mid, assistMid, pn, ps, stime, etime, ip); err != nil {
log.Error("s.creative.Assist err(%v) | mid(%d),assistMid(%d),pn(%d),ps(%d),stime(%d),etime(%d),ip(%s)",
err, mid, assistMid, pn, ps, stime, etime, ip)
return
}
var assistMids []int64
for _, ass := range assistLogs {
assistMids = append(assistMids, ass.AssistMid)
}
users, err := s.acc.Infos(c, assistMids, ip)
if err != nil {
log.Error("s.acc.Profiles() err(%v)", err)
return
}
for _, assist := range assistLogs {
if _, ok := users[assist.AssistMid]; ok {
assist.AssistAvatar = users[assist.AssistMid].Face
assist.AssistName = users[assist.AssistMid].Name
}
}
return
}
// AddAssist add mid to any assist
func (s *Service) AddAssist(c context.Context, mid, assistMid int64, main, live int8, ip, ak, ck string) (err error) {
if main == 1 {
if err = s.addAssist(c, mid, assistMid, ip, ak, ck); err != nil {
return
}
}
if live == 1 {
if err = s.liveAddAssist(c, mid, assistMid, ak, ck, ip); err != nil {
return
}
}
return
}
func (s *Service) addAssist(c context.Context, mid, assistMid int64, ip, ak, ck string) (err error) {
var (
card *account.Card
)
if card, err = s.acc.Card(c, mid, ip); err != nil {
log.Error("s.assist.AddAssist err(%v) | mid(%d), assistMid(%d), ip(%s)", err, mid, assistMid, ip)
return
}
if err = s.assist.AddAssist(c, mid, assistMid, ip, card.Name); err != nil {
log.Error("s.assist.AddAssist err(%v) | mid(%d), assistMid(%d), ip(%s)", err, mid, assistMid, ip)
return
}
return
}
// DelAssist delete all the assist
func (s *Service) DelAssist(c context.Context, mid, assistMid int64, ip, ak, ck string) (err error) {
isMainAss, _ := s.assist.Info(c, mid, assistMid, ip)
if isMainAss == 1 {
err = s.delAssist(c, mid, assistMid, ip, ak, ck)
}
isLiveAss, _ := s.LiveCheckAssist(c, mid, assistMid, ip)
if isLiveAss == 1 {
err = s.liveDelAssist(c, mid, assistMid, ck, ip)
}
return
}
// DelAssist delete the assist
func (s *Service) delAssist(c context.Context, mid, assistMid int64, ip, ak, ck string) (err error) {
var (
card *account.Card
)
if card, err = s.acc.Card(c, mid, ip); err != nil {
log.Error("s.assist.AddAssist err(%v) | mid(%d), assistMid(%d), ip(%s)", err, mid, assistMid, ip)
return
}
if err = s.assist.DelAssist(c, mid, assistMid, ip, card.Name); err != nil {
log.Error("s.assist.DelAssist err(%v) | mid(%d), assistMid(%d), ip(%s)", err, mid, assistMid, ip)
return
}
return
}
// prepare for Live revoc log
func (s *Service) preRevocLogForLive(c context.Context, assistLog *assist.AssistLog) (err error) {
if assistLog.Action == 8 && assistLog.Type == 3 {
var (
objID int64
revcLog = &assist.AssistLog{}
)
if objID, err = strconv.ParseInt(assistLog.ObjectID, 10, 64); err != nil {
log.Error("Atoi err(%v) | mid(%d), assistMid(%d), assistLog.ObjectID(%s)", err, assistLog.Mid, assistLog.AssistMid, assistLog.ObjectID)
return
}
revcLog, err = s.assist.AssistLogObj(c, assistLog.Type, 9, assistLog.Mid, objID)
if err == ecode.AssistLogNotExist {
return nil
}
if err != nil {
log.Error("s.assist.AssistLogObj err(%v) | mid(%d), assistMid(%d), logID(%d)", err, assistLog.Mid, assistLog.AssistMid, assistLog.ID)
return
}
if revcLog != nil {
err = ecode.CreativeAssistLogAlreadyRevoc
return
}
return
}
return
}
// RevocAssistLog cancel this asssist action
func (s *Service) RevocAssistLog(c context.Context, mid, assistMid, logID int64, ck, ip string) (err error) {
var assistLog *assist.AssistLog
if assistLog, err = s.assist.AssistLog(c, mid, assistMid, logID, ip); err != nil {
log.Error("s.assist.AssistLog err(%v) | mid(%d), assistMid(%d), logID(%d), ip(%s)", err, mid, assistMid, logID, ip)
return
}
if err = s.preRevocLogForLive(c, assistLog); err != nil {
log.Error("s.preRevocLogForLive err(%v) | mid(%d), assistMid(%d), logID(%d), ip(%s)", err, mid, assistMid, logID, ip)
return
}
if err = s.revoc(c, assistLog, ck, ip); err != nil {
log.Error("s.revoc err(%v) | assistLog(%+v), ip(%s)", err, assistLog, ip)
return
}
if err = s.assist.RevocAssistLog(c, mid, assistMid, logID, ip); err != nil {
log.Error("s.assist.CancelAssistLog err(%v) | mid(%d), assistMid(%d), logID(%d), ip(%s)", err, mid, assistMid, logID, ip)
return
}
return
}
func (s *Service) userBanned(c context.Context, mid int64) (banned int8, err error) {
var card *account.Card
if card, err = s.acc.Card(c, mid, ""); err != nil {
err = nil
return
}
if card.Silence == 1 {
banned = 1
return
}
return
}
// SetAssist get user assist rights about liveRoom
func (s *Service) SetAssist(c context.Context, mid, assistMid int64, main, live int8, ip, ak, ck string) (err error) {
isMainAss, _ := s.assist.Info(c, mid, assistMid, ip)
if isMainAss == 0 && main == 1 {
err = s.addAssist(c, mid, assistMid, ip, ak, ck)
} else if isMainAss == 1 && main == 0 {
err = s.delAssist(c, mid, assistMid, ip, ak, ck)
}
if err != nil {
return
}
isLiveAss, _ := s.LiveCheckAssist(c, mid, assistMid, ip)
if live == 1 && isLiveAss == 0 {
err = s.liveAddAssist(c, mid, assistMid, ak, ck, ip)
} else if live == 0 && isLiveAss == 1 {
err = s.liveDelAssist(c, mid, assistMid, ck, ip)
}
return
}

View File

@@ -0,0 +1,53 @@
package assist
import (
"context"
"go-common/library/log"
)
// LiveStatus get user assist rights about liveRoom
func (s *Service) LiveStatus(c context.Context, mid int64, ip string) (open int8, err error) {
if open, err = s.assist.LiveStatus(c, mid, ip); err != nil {
log.Error("s.assist.HasLiveRight mid(%d), ip(%s)", mid, ip)
return
}
return
}
// liveAddAssist add assist to live
// Notice: 这里是新账号系统的Demo
func (s *Service) liveAddAssist(c context.Context, mid, assistMid int64, ak, ck, ip string) (err error) {
identified, _ := s.acc.IdentifyInfo(c, mid, 1, ip)
if err = s.acc.CheckIdentify(identified); err != nil {
log.Error("s.acc.IdentifyInfo mid(%d),ip(%s)", mid, ip)
return
}
if err = s.assist.LiveAddAssist(c, mid, assistMid, ck, ip); err != nil {
return
}
return
}
// liveDelAssist del assist to live
func (s *Service) liveDelAssist(c context.Context, mid, assistMid int64, ck, ip string) (err error) {
if err = s.assist.LiveDelAssist(c, mid, assistMid, ck, ip); err != nil {
return
}
return
}
// LiveCheckAssist check if is assist in live
func (s *Service) LiveCheckAssist(c context.Context, mid, assistMid int64, ip string) (isAss int8, err error) {
if isAss, err = s.assist.LiveCheckAssist(c, mid, assistMid, ip); err != nil {
return
}
return
}
// LiveRevocBanned revoke banned in live
func (s *Service) LiveRevocBanned(c context.Context, mid int64, banID, ck, ip string) (err error) {
if err = s.assist.LiveBannedRevoc(c, mid, banID, ck, ip); err != nil {
return
}
return
}

View File

@@ -0,0 +1,65 @@
package assist
import (
"context"
"strconv"
"go-common/app/interface/main/creative/model/assist"
"go-common/library/ecode"
"go-common/library/log"
)
func (s *Service) revoc(c context.Context, assistLog *assist.AssistLog, ck, ip string) (err error) {
switch {
case assistLog.Type == 1 && assistLog.Action == 1:
objectID, _ := strconv.ParseInt(assistLog.ObjectID, 10, 64)
if objectID == 0 {
err = ecode.RequestErr
log.Error("strconv.ParseInt(%s) err(%v)", assistLog.ObjectID, err)
return
}
if err = s.reply.ReplyRecover(c, assistLog.Mid, assistLog.SubjectID, objectID, ip); err != nil {
log.Error("s.reply.ReplyRecover(%d,%d,%d,%s) err(%v)", assistLog.Mid, assistLog.SubjectID, assistLog.ObjectID, ip, err)
return
}
case assistLog.Type == 2 && (assistLog.Action == 1 || assistLog.Action == 3):
objectID, _ := strconv.ParseInt(assistLog.ObjectID, 10, 64)
if err = s.dm.Edit(c, assistLog.Mid, assistLog.SubjectID, 0, []int64{objectID}, ip); err != nil {
log.Error("s.dm.ResetDmStat(%d,%d,%d,%s) err(%v)", assistLog.Mid, assistLog.SubjectID, assistLog.ObjectID, ip, err)
return
}
case assistLog.Type == 2 && assistLog.Action == 4:
// 拉黑用户
if err = s.dm.ResetUpBanned(c, assistLog.Mid, 0, assistLog.ObjectID, ip); err != nil {
log.Error("s.dm.ResetUpBanned(%d,%d,%d,%s) err(%v)", assistLog.Mid, assistLog.SubjectID, assistLog.ObjectID, ip, err)
return
}
case assistLog.Type == 2 && assistLog.Action == 5:
// 移动弹幕到字幕池
objectID, _ := strconv.ParseInt(assistLog.ObjectID, 10, 64)
if err = s.dm.UpPool(c, assistLog.Mid, assistLog.SubjectID, []int64{objectID}, 0); err != nil {
log.Error("s.dm.UpPool(%d,%d,%d,%s) err(%v)", assistLog.Mid, assistLog.SubjectID, assistLog.ObjectID, ip, err)
return
}
case assistLog.Type == 2 && assistLog.Action == 6:
// 忽略字幕池的弹幕
objectID, _ := strconv.ParseInt(assistLog.ObjectID, 10, 64)
if err = s.dm.UpPool(c, assistLog.Mid, assistLog.SubjectID, []int64{objectID}, 1); err != nil {
log.Error("s.dm.UpPool(%d,%d,%d,%s) err(%v)", assistLog.Mid, assistLog.SubjectID, assistLog.ObjectID, ip, err)
return
}
case assistLog.Type == 2 && assistLog.Action == 7:
// 取消拉黑用户
if err = s.dm.ResetUpBanned(c, assistLog.Mid, 1, assistLog.ObjectID, ip); err != nil {
log.Error("s.dm.ResetUpBanned(%d,%d,%d,%s) err(%v)", assistLog.Mid, assistLog.SubjectID, assistLog.ObjectID, ip, err)
return
}
case assistLog.Type == 3 && assistLog.Action == 8:
// 取消拉黑用户
if err = s.LiveRevocBanned(c, assistLog.Mid, assistLog.ObjectID, ck, ip); err != nil {
log.Error("s.reply.LiveRevocBanned(%d,%d,%d,%s) err(%v)", assistLog.Mid, assistLog.SubjectID, assistLog.ObjectID, ip, err)
return
}
}
return
}

View File

@@ -0,0 +1,31 @@
package assist
import (
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/dao/account"
"go-common/app/interface/main/creative/dao/assist"
"go-common/app/interface/main/creative/dao/danmu"
"go-common/app/interface/main/creative/dao/reply"
"go-common/app/interface/main/creative/service"
)
// Service assist.
type Service struct {
c *conf.Config
assist *assist.Dao
reply *reply.Dao
dm *danmu.Dao
acc *account.Dao
}
// New get assist service.
func New(c *conf.Config, rpcdaos *service.RPCDaos) *Service {
s := &Service{
c: c,
assist: assist.New(c),
reply: reply.New(c),
dm: danmu.New(c),
acc: rpcdaos.Acc,
}
return s
}

View File

@@ -0,0 +1,87 @@
package assist
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/model/assist"
. "github.com/smartystreets/goconvey/convey"
"go-common/app/interface/main/creative/service"
)
var (
s *Service
)
func init() {
dir, _ := filepath.Abs("../../cmd/creative.toml")
flag.Set("conf", dir)
conf.Init()
rpcdaos := service.NewRPCDaos(conf.Conf)
s = New(conf.Conf, rpcdaos)
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
Reset(func() {})
f(s)
}
}
func ctx() context.Context {
return context.Background()
}
func Test_Revoc(t *testing.T) {
var (
c = ctx()
ck = ""
ip = "127.0.0.1"
assistLog = &assist.AssistLog{}
)
Convey("test_revoc", t, func() {
err := s.revoc(c, assistLog, ck, ip)
So(err, ShouldNotBeNil)
})
}
func Test_Live(t *testing.T) {
var (
c = ctx()
ip = "127.0.0.1"
ck = ""
ak = ""
MID = int64(27515256)
assistMid = int64(27515257)
)
Convey("test_LiveStatus", t, func() {
open, err := s.LiveStatus(c, MID, ip)
So(err, ShouldBeNil)
So(open, ShouldNotBeNil)
})
Convey("test_liveAddAssist", t, func() {
err := s.liveAddAssist(c, MID, assistMid, ak, ck, ip)
So(err, ShouldBeNil)
})
}
func Test_Assist(t *testing.T) {
var (
c = ctx()
err error
ip = "127.0.0.1"
MID = int64(27515256)
ass []*assist.Assist
)
Convey("test_Assists", t, WithService(func(s *Service) {
ass, err = s.Assists(c, MID, ip)
So(err, ShouldBeNil)
So(ass, ShouldNotBeNil)
}))
}

View File

@@ -0,0 +1,63 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"danmu.go",
"service.go",
"subtitle.go",
],
importpath = "go-common/app/interface/main/creative/service/danmu",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/dao/account:go_default_library",
"//app/interface/main/creative/dao/archive:go_default_library",
"//app/interface/main/creative/dao/danmu:go_default_library",
"//app/interface/main/creative/dao/elec:go_default_library",
"//app/interface/main/creative/dao/subtitle:go_default_library",
"//app/interface/main/creative/model/danmu:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//app/interface/main/dm/model:go_default_library",
"//app/interface/main/dm2/model:go_default_library",
"//app/service/main/account/model:go_default_library",
"//app/service/main/archive/api:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/sync/errgroup:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,385 @@
package danmu
import (
"context"
"encoding/json"
"go-common/app/interface/main/creative/model/danmu"
pubSvc "go-common/app/interface/main/creative/service"
dmMdl "go-common/app/interface/main/dm/model"
"go-common/app/service/main/account/model"
account "go-common/app/service/main/account/model"
"go-common/app/service/main/archive/api"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/sync/errgroup"
"strconv"
"time"
)
var (
stateMap = map[int8]int8{
0: 0, // 正常
1: 1, // 删除
2: 2, // 保护
3: 3, // 取消保护
}
poolMap = map[int8]int8{
0: 0, // 普通弹幕池
1: 1, // 字幕弹幕池
2: 2, // 特殊弹幕池
}
)
// AdvDmPurchaseList fn
func (s *Service) AdvDmPurchaseList(c context.Context, mid int64, ip string) (danmus []*danmu.AdvanceDanmu, err error) {
if danmus, err = s.dm.GetAdvDmPurchases(c, mid, ip); err != nil {
log.Error("s.dm.ListAdvDmPurchases err(%v) | mid(%d), ip(%s)", err, mid, ip)
return
}
return
}
// PassDmPurchase fn
func (s *Service) PassDmPurchase(c context.Context, mid, id int64, ip string) (err error) {
if err = s.dm.PassAdvDmPurchase(c, mid, id, ip); err != nil {
log.Error("s.dm.PassDmPurchase err(%v) | mid(%d), id(%d), ip(%s)", err, mid, id, ip)
return
}
return
}
// DenyDmPurchase fn
func (s *Service) DenyDmPurchase(c context.Context, mid, id int64, ip string) (err error) {
if err = s.dm.DenyAdvDmPurchase(c, mid, id, ip); err != nil {
log.Error("s.dm.DenyDmPurchase err(%v) | mid(%d), id(%d), ip(%s)", err, mid, id, ip)
return
}
return
}
// CancelDmPurchase fn
func (s *Service) CancelDmPurchase(c context.Context, mid, id int64, ip string) (err error) {
if err = s.dm.CancelAdvDmPurchase(c, mid, id, ip); err != nil {
log.Error("s.dm.CancelDmPurchase err(%v) | mid(%d), id(%d), ip(%s)", err, mid, id, ip)
return
}
return
}
// Edit fn
func (s *Service) Edit(c context.Context, mid, id int64, state int8, dmids []int64, ip string) (err error) {
if len(dmids) == 0 {
err = ecode.CreativeDanmuFilterParamError
return
}
okState := false
for _, v := range stateMap {
if v == state {
okState = true
}
}
if !okState {
err = ecode.RequestErr
return
}
if err = s.dm.Edit(c, mid, id, state, dmids, ip); err != nil {
log.Error("s.dm.DmList err(%v)|mid(%d),id(%d),state(%d),dmids(%+v),ip(%s)", err, mid, id, state, dmids, ip)
return
}
return
}
// Transfer fn
func (s *Service) Transfer(c context.Context, mid, fromCID, toCID int64, offset float64, ak, ck, ip string) (err error) {
if err = s.dm.Transfer(c, mid, fromCID, toCID, offset, ak, ck, ip); err != nil {
log.Error("s.dm.Transfer err(%v) | mid(%d),fromCID(%d),toCID(%d),offset(%+v),ak(%s),ck(%s),ip(%s)", err, mid, fromCID, toCID, offset, ak, ck, ip)
return
}
return
}
// UpPool fn
func (s *Service) UpPool(c context.Context, cid int64, dmids []int64, pool int8, mid int64, ip string) (err error) {
okPool := false
for _, v := range poolMap {
if v == pool {
okPool = true
}
}
if !okPool {
err = ecode.RequestErr
return
}
if err = s.dm.UpPool(c, mid, cid, dmids, pool); err != nil {
log.Error("s.dm.UpPool err(%v)|cid(%d),dmids(%+v),pool(%+v),mid(%d),ip(%s)", err, cid, dmids, pool, mid, ip)
return
}
return
}
// Distri fn
func (s *Service) Distri(c context.Context, mid, cid int64, ip string) (dmDistri map[int64]int64, err error) {
if dmDistri, err = s.dm.Distri(c, mid, cid, ip); err != nil {
log.Error("s.dm.Distri err(%v) | mid(%d),cid(%d)|ip(%s)", err, mid, cid, ip)
return
}
return
}
// List fn
func (s *Service) List(c context.Context, mid, aid, cid int64, pn, ps int, order, pool, midStr, ip string) (dmList *danmu.DmList, err error) {
var (
v *api.Page
a *api.Arc
mids []int64
elecs map[int64]int
followers map[int64]int
senders map[int64]*account.Info
)
a, _ = s.arc.Archive(c, aid, ip)
v, _ = s.arc.Video(c, aid, cid, ip)
if dmList, err = s.dm.List(c, cid, mid, pn, ps, order, pool, midStr, ip); err != nil {
log.Error("s.dm.List err(%v) | mid(%d), cid(%d),pn(%d),ps(%d),order(%s),midStr(%s),ip(%s)", err, mid, cid, pn, ps, order, midStr, ip)
return
}
for _, l := range dmList.List {
mids = append(mids, l.Mid)
}
if len(mids) > 0 {
var g, ctx = errgroup.WithContext(c)
g.Go(func() error { //获取被充电状态
elecs, _ = s.elec.ElecRelation(ctx, mid, mids, ip)
return nil
})
g.Go(func() error { //获取用户信息
senders, _ = s.acc.Infos(ctx, mids, ip)
return nil
})
g.Go(func() error { //获取被关注状态
followers, _ = s.acc.Followers(ctx, mid, mids, ip)
return nil
})
g.Wait()
for _, l := range dmList.List {
l.VTitle = v.Part
l.ArcTitle = a.Title
l.Aid = aid
l.Cover = pubSvc.CoverURL(a.Pic)
if elec, ok := elecs[l.Mid]; ok { //设置充电状态
l.IsElec = elec
}
if u, ok := senders[l.Mid]; ok { //设置图像和用户名
l.Uname = u.Name
l.Uface = u.Face
}
if relation, ok := followers[l.Mid]; ok { //设置关注状态
l.Relation = relation
}
}
}
return
}
// Recent fn
func (s *Service) Recent(c context.Context, mid, pn, ps int64, ip string) (dmRecent *danmu.DmRecent, err error) {
var (
aids []int64
mids []int64
elecs map[int64]int
followers map[int64]int
senders map[int64]*account.Info
)
if dmRecent, aids, err = s.dm.Recent(c, mid, pn, ps, ip); err != nil {
log.Error("s.dm.Recent err(%v)|(%v),(%v),(%v),(%v),", err, mid, pn, ps, ip)
return
}
if len(dmRecent.List) > 0 && len(aids) > 0 {
var avm map[int64]*api.Arc
if avm, err = s.arc.Archives(c, aids, ip); err != nil {
log.Error("s.arc.Archives mid(%d)|aids(%+v)|ip(%s)|err(%v)", mid, aids, ip, err)
err = nil
}
for _, l := range dmRecent.List {
mids = append(mids, l.Mid)
}
var g, ctx = errgroup.WithContext(c)
g.Go(func() error { //获取被充电状态
elecs, _ = s.elec.ElecRelation(ctx, mid, mids, ip)
return nil
})
g.Go(func() error { //获取用户信息
senders, _ = s.acc.Infos(ctx, mids, ip)
return nil
})
g.Go(func() error { //获取被关注状态
followers, _ = s.acc.Followers(ctx, mid, mids, ip)
return nil
})
g.Wait()
for _, l := range dmRecent.List {
if av, ok := avm[l.Aid]; ok && av != nil {
l.Cover = pubSvc.CoverURL(av.Pic)
}
if elec, ok := elecs[l.Mid]; ok { //设置充电状态
l.IsElec = elec
}
if u, ok := senders[l.Mid]; ok { //设置图像和用户名
l.Uname = u.Name
l.Uface = u.Face
}
if relation, ok := followers[l.Mid]; ok { //设置关注状态
l.Relation = relation
}
}
}
return
}
// DmReportCheck fn
func (s *Service) DmReportCheck(c context.Context, mid, cid, dmid, op int64, ip string) (err error) {
if err = s.dm.ReportUpEdit(c, mid, dmid, cid, op, ip); err != nil {
log.Error("s.dm.ReportUpEdit err(%v) | mid(%d), dmid(%d),cid(%d),op(%d),ip(%s)", err, mid, dmid, cid, op, ip)
return
}
return
}
// DmProtectArchive fn
func (s *Service) DmProtectArchive(c context.Context, mid int64, ip string) (vlist []*dmMdl.Video, err error) {
if vlist, err = s.dm.ProtectApplyVideoList(c, mid, ip); err != nil {
log.Error("s.dm.ProtectApplyVideoList err(%v) | mid(%d),ip(%s)", err, mid, ip)
return
}
return
}
// DmProtectList fn
func (s *Service) DmProtectList(c context.Context, mid int64, page int64, aidStr, sort, ip string) (list *danmu.ApplyList, err error) {
if list, err = s.dm.ProtectApplyList(c, mid, page, aidStr, sort, ip); err != nil {
log.Error("s.dm.ProtectApplyList err(%v) | mid(%d),aidStr(%s),page(%d),sort(%s),ip(%s)", err, mid, aidStr, page, sort, ip)
return
}
return
}
// DmProtectOper fn
func (s *Service) DmProtectOper(c context.Context, mid, status int64, idsStr, ip string) (err error) {
if err = s.dm.ProtectOper(c, mid, status, idsStr, ip); err != nil {
log.Error("s.dm.ProtectOper err(%v) | mid(%d), status(%d),ids(%s),ip(%s)", err, mid, status, idsStr, ip)
return
}
return
}
// UserMid for dm search by name
func (s *Service) UserMid(c context.Context, name, ip string) (mid int64, err error) {
if mid, err = s.acc.MidByName(c, name); err != nil {
log.Error("UserMid err(%v) | name(%s), ip(%s)", err, name, ip)
if err == ecode.AccountInexistence {
err = nil
}
return
}
return
}
// DmReportList fn
func (s *Service) DmReportList(c context.Context, mid, pn, ps int64, aidStr, ip string) (res map[string]interface{}, err error) {
var (
pager = map[string]int64{
"total": 0,
"current": pn,
"size": ps,
}
list = []*danmu.DmReport{}
srchs = []*dmMdl.RptSearch{}
ars = []*danmu.DmArc{}
total = int64(0)
owners = []int64{}
)
res = map[string]interface{}{
"pager": pager,
"list": list,
"archives": ars,
}
if srchs, total, err = s.dm.ReportUpList(c, mid, pn, ps, aidStr, ip); err != nil {
log.Error("s.dm.ReportUpList err(%v) | mid(%d),pn(%d),ps(%d),aidStr(%s),ip(%s)", err, mid, pn, ps, aidStr, ip)
return
}
if len(srchs) > 0 {
for _, v := range srchs {
owners = append(owners, v.Owner)
}
var ownerProfiles map[int64]*model.Info
if ownerProfiles, err = s.acc.Infos(c, owners, ip); err != nil {
log.Error("s.cc.Infos err(%v) | mid(%d),pn(%d),ps(%d),aidStr(%s),ip(%s)", err, mid, pn, ps, aidStr, ip)
return
}
for _, s := range srchs {
t, _ := time.ParseInLocation("2006-01-02 15:04:05", s.RpTime, time.Local)
report := &danmu.DmReport{
RpID: s.ID,
DmInID: s.Cid,
AID: s.Aid,
Pic: pubSvc.CoverURL(s.Cover),
ReportTime: t.Unix(),
Title: s.Title,
Reason: s.Content,
DmID: s.Did,
DmIDStr: strconv.FormatInt(s.Did, 10),
UpUID: s.UPUid,
Content: s.Msg,
UID: s.Owner,
}
if profile, ok := ownerProfiles[s.Owner]; ok {
report.UserName = profile.Name
}
list = append(list, report)
}
if ars, err = s.dm.ReportUpArchives(c, mid, ip); err != nil {
log.Error("s.dm.ReportUpArchives err(%v) | mid(%d),ip(%s)", err, mid, ip)
return
}
}
pager["total"] = total
res["pager"] = pager
res["list"] = list
res["archives"] = ars
return
}
// EditBatch fn
func (s *Service) EditBatch(c context.Context, mid int64, paramsJSON, ip string) (err error) {
type P struct {
CID int64 `json:"cid"`
DmID int64 `json:"dmid"`
State int8 `json:"state"`
}
var filtersJSONData []*P
if err = json.Unmarshal([]byte(paramsJSON), &filtersJSONData); err != nil {
err = ecode.RequestErr
return
}
if len(filtersJSONData) == 0 {
err = ecode.CreativeDanmuFilterParamError
return
}
var (
g errgroup.Group
)
for _, v := range filtersJSONData {
dmids := []int64{}
dmids = append(dmids, v.DmID)
cid := v.CID
state := v.State
g.Go(func() (err error) {
if err = s.dm.Edit(c, mid, cid, state, dmids, ip); err != nil {
log.Error("s.d.Edit v(%+v)|dmids(%+v)|cid(%+v)|state(%+v)|err(%+v)", v, dmids, cid, state, err)
}
log.Info("filtersJSONData v(%+v)|dmids(%+v)|cid(%+v)|state(%+v)|err(%+v)", v, dmids, cid, state, err)
return
})
}
g.Wait()
return
}

View File

@@ -0,0 +1,34 @@
package danmu
import (
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/dao/account"
"go-common/app/interface/main/creative/dao/archive"
"go-common/app/interface/main/creative/dao/danmu"
"go-common/app/interface/main/creative/dao/elec"
"go-common/app/interface/main/creative/dao/subtitle"
"go-common/app/interface/main/creative/service"
)
// Service danmu.
type Service struct {
c *conf.Config
dm *danmu.Dao
arc *archive.Dao
acc *account.Dao
sub *subtitle.Dao
elec *elec.Dao
}
// New get danmu service.
func New(c *conf.Config, rpcdaos *service.RPCDaos) *Service {
s := &Service{
c: c,
dm: danmu.New(c),
acc: rpcdaos.Acc,
arc: rpcdaos.Arc,
sub: rpcdaos.Sub,
elec: elec.New(c),
}
return s
}

View File

@@ -0,0 +1,89 @@
package danmu
import (
"context"
"flag"
"go-common/app/interface/main/creative/conf"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/creative/service"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func init() {
dir, _ := filepath.Abs("../../cmd/creative.toml")
flag.Set("conf", dir)
conf.Init()
rpcdaos := service.NewRPCDaos(conf.Conf)
s = New(conf.Conf, rpcdaos)
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
Reset(func() {})
f(s)
}
}
func Test_AdvDmPurchaseList(t *testing.T) {
var (
c = context.Background()
MID = int64(27515256)
)
Convey("AdvDmPurchaseList", t, WithService(func(s *Service) {
_, err := s.AdvDmPurchaseList(c, MID, "")
So(err, ShouldNotBeNil)
}))
}
func Test_Distri(t *testing.T) {
var (
c = context.Background()
MID = int64(27515256)
)
Convey("Distri", t, WithService(func(s *Service) {
_, err := s.Distri(c, MID, 2333, "")
So(err, ShouldNotBeNil)
}))
}
func Test_DmProtectList(t *testing.T) {
var (
c = context.Background()
MID = int64(27515256)
)
Convey("DmProtectList", t, WithService(func(s *Service) {
_, err := s.DmProtectList(c, MID, 1, "2333", "time", "")
So(err, ShouldNotBeNil)
}))
}
func Test_DmReportList(t *testing.T) {
var (
c = context.Background()
MID = int64(27515256)
)
Convey("DmReportList", t, WithService(func(s *Service) {
_, err := s.DmReportList(c, MID, 1, 10, "2333", "")
So(err, ShouldNotBeNil)
}))
}
func Test_Recent(t *testing.T) {
var (
c = context.Background()
MID = int64(27515256)
)
Convey("Recent", t, WithService(func(s *Service) {
_, err := s.Recent(c, MID, 1, 10, "")
So(err, ShouldNotBeNil)
}))
}

View File

@@ -0,0 +1,26 @@
package danmu
import (
"context"
"go-common/app/interface/main/creative/model/danmu"
"go-common/app/interface/main/dm2/model"
"go-common/library/log"
)
// SubView fn
func (s *Service) SubView(c context.Context, aid int64, ip string) (ret *danmu.SubtitleSubjectReply, err error) {
var sub *model.SubtitleSubjectReply
if sub, err = s.sub.View(c, aid); err != nil {
log.Error("s.sub.View err(%v) | aid(%d), ip(%s)", err, aid, ip)
return
}
if sub != nil {
ret = &danmu.SubtitleSubjectReply{
AllowSubmit: sub.AllowSubmit,
Lan: sub.Lan,
LanDoc: sub.LanDoc,
}
}
return
}

View File

@@ -0,0 +1,72 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"app.go",
"archive.go",
"article.go",
"fan.go",
"overview.go",
"service.go",
],
importpath = "go-common/app/interface/main/creative/service/data",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/dao/account:go_default_library",
"//app/interface/main/creative/dao/activity:go_default_library",
"//app/interface/main/creative/dao/archive:go_default_library",
"//app/interface/main/creative/dao/article:go_default_library",
"//app/interface/main/creative/dao/bfs:go_default_library",
"//app/interface/main/creative/dao/data:go_default_library",
"//app/interface/main/creative/dao/medal:go_default_library",
"//app/interface/main/creative/dao/tag:go_default_library",
"//app/interface/main/creative/model/archive:go_default_library",
"//app/interface/main/creative/model/data:go_default_library",
"//app/interface/main/creative/model/medal:go_default_library",
"//app/interface/main/creative/model/tag:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//app/interface/openplatform/article/model:go_default_library",
"//app/service/main/account/model:go_default_library",
"//app/service/main/archive/api:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/stat/prom:go_default_library",
"//library/sync/errgroup:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,485 @@
package data
import (
"context"
"sort"
"sync"
"time"
"go-common/library/ecode"
"go-common/app/interface/main/creative/model/archive"
"go-common/app/interface/main/creative/model/data"
"go-common/app/service/main/archive/api"
"go-common/library/log"
"go-common/library/sync/errgroup"
"math"
)
var (
zeroSummary = map[string]int64{
"total": 0,
"inc": 0,
"play": 0,
"dm": 0,
"reply": 0,
"coin": 0,
"inter": 0,
"vv": 0,
"da": 0,
"re": 0,
"co": 0,
"fv": 0,
"sh": 0,
"lk": 0,
}
)
// UpFansAnalysisForApp get app fans analysis.
func (s *Service) UpFansAnalysisForApp(c context.Context, mid int64, ty int, ip string) (res *data.AppFan, err error) {
var (
g, ctx = errgroup.WithContext(c)
origin *data.AppFan
typeList map[string]int64
tagList []*data.Rank
viewerArea map[string]int64
viewerBase *data.ViewerBase
)
res = &data.AppFan{}
if origin, err = s.data.UpFansAnalysisForApp(c, mid, ty); err != nil {
log.Error("s.data.UpFansAnalysisForApp mid(%d)|ip(%s)|err(%v)", mid, ip, err)
return
}
if origin == nil {
return
}
if origin.Summary == nil {
origin.Summary = zeroSummary
}
log.Info("s.data.UpFansAnalysisForApp origin mid(%d)|origin(%+v)", mid, origin)
g.Go(func() (err error) {
total, ok := origin.Summary["total"]
inc, oki := origin.Summary["inc"]
if !ok || !oki {
return
}
pfl, err := s.acc.ProfileWithStat(ctx, mid)
if err != nil {
err = nil
log.Error("s.acc.ProfileWithStat mid(%d)|err(%v)", mid, err)
return
}
if pfl == nil {
log.Error("s.acc.ProfileWithStat mid(%d)|Follower(%+v) err(%v)", mid, pfl, err)
return
}
origin.Summary["total"] = pfl.Follower
origin.Summary["inc"] = inc + (pfl.Follower - total)
return
})
g.Go(func() (err error) {
if tys, tgs, err := s.fanTrend(ctx, mid); err == nil {
typeList = tys
tagList = tgs
}
return nil
})
g.Go(func() (err error) {
if va, err := s.fanViewerArea(ctx, mid); err == nil {
viewerArea = va
}
return nil
})
g.Go(func() (err error) {
if vb, err := s.fanViewerBase(ctx, mid); err == nil {
viewerBase = vb
}
return nil
})
g.Wait()
res.Summary = origin.Summary
res.TypeList = typeList
res.TagList = tagList
res.ViewerArea = viewerArea
res.ViewerBase = viewerBase
log.Info("UpFansAnalysisForApp mid(%d)|res(%+v)", mid, res)
return
}
//FanRankApp get app fans rank list.
func (s *Service) FanRankApp(c context.Context, mid int64, ty int, ip string) (res map[string][]*data.RankInfo, err error) {
var (
origin *data.AppFan
rkList map[string][]*data.RankInfo
)
if origin, err = s.data.UpFansAnalysisForApp(c, mid, ty); err != nil {
log.Error("s.data.UpFansAnalysisForApp mid(%d)|ip(%s)|err(%v)", mid, ip, err)
return
}
if origin == nil {
return
}
log.Info("s.UpFansRankApp origin mid(%d)|origin(%+v)", mid, origin)
if rkList, err = s.getTopList(c, mid, origin.RankMap, ip); err != nil {
log.Error("s.getTopList err(%v)", err)
}
if len(rkList) == 0 { //排行列表容错必须返回对应的key
rkList = make(map[string][]*data.RankInfo)
}
for _, key := range rankKeys {
if v, ok := rkList[key]; ok {
rkList[key] = v
} else {
rkList[key] = nil
}
}
res = rkList
log.Info("s.UpFansRankApp mid(%d)|res(%+v)|len[rkList](%d)", mid, res, len(rkList))
return
}
func (s *Service) fanTrend(c context.Context, mid int64) (tys map[string]int64, tags []*data.Rank, err error) {
var (
dt = getDate()
trend map[string]*data.ViewerTrend
)
if trend, err = s.viewerTrend(c, mid, dt); err != nil {
log.Error("fanTrend s.viewerTrend mid(%d)|err(%v)", mid, err)
return
}
if tr, ok := trend["fan"]; ok && tr != nil {
tys = tr.Ty
skeys := []int{2, 1, 4, 3, 6, 5, 8, 7, 10, 9}
for _, k := range skeys {
if v, ok := tr.Tag[k]; ok {
tg := &data.Rank{
Rank: k,
Name: v,
}
tags = append(tags, tg)
}
}
}
return
}
func (s *Service) fanViewerArea(c context.Context, mid int64) (res map[string]int64, err error) {
var (
origin map[string]map[string]int64
)
if origin, err = s.data.ViewerArea(c, mid, getDate()); err != nil {
log.Error("fanViewerBase s.data.ViewerArea mid(%d)|err(%v)", mid, err)
}
if len(origin) == 0 {
return
}
if v, ok := origin["fan"]; ok {
res = v
}
return
}
func (s *Service) fanViewerBase(c context.Context, mid int64) (res *data.ViewerBase, err error) {
var (
origin map[string]*data.ViewerBase
)
if origin, err = s.data.ViewerBase(c, mid, getDate()); err != nil {
log.Error("fanViewerBase s.data.ViewerArea mid(%d)|err(%v)", mid, err)
}
if len(origin) == 0 {
return
}
if v, ok := origin["fan"]; ok {
res = v
}
return
}
//OverView for app data overview.
func (s *Service) OverView(c context.Context, mid int64, ty int8, ip string) (res *data.AppOverView, err error) {
var (
g, ctx = errgroup.WithContext(c)
stat *data.Stat
allIncr []*data.ThirtyDay
singleArcInc []*data.ArcInc
)
g.Go(func() (err error) {
if stat, err = s.NewStat(ctx, mid, ip); err != nil {
err = nil
log.Error("OverView s.ThirtyDayArchive mid(%d)|err(%v)", mid, err)
}
return nil
})
g.Go(func() (err error) {
if allIncr, err = s.ThirtyDayArchive(ctx, mid, ty); err != nil {
err = nil
log.Error("OverView s.ThirtyDayArchive mid(%d)|err(%v)", mid, err)
}
if len(allIncr) >= 7 {
allIncr = allIncr[0:7]
}
return nil
})
g.Go(func() (err error) {
if prop, err := s.AppUpIncr(c, mid, ty, ip); err == nil && len(prop) > 0 {
if prop[len(prop)-1] != nil { //获取最后一天的数据
singleArcInc = prop[len(prop)-1].Arcs
}
}
return nil
})
g.Wait()
res = &data.AppOverView{
Stat: stat,
AllArcIncr: allIncr,
SingleArcInc: singleArcInc,
}
return
}
// ArchiveAnalyze get single archive data.
func (s *Service) ArchiveAnalyze(c context.Context, aid, mid int64, ip string) (stat *data.ArchiveData, err error) {
// check aid valid and owner
isWhite := false
for _, m := range s.c.Whitelist.DataMids {
if m == mid {
isWhite = true
break
}
}
a, re := s.arc.Archive(c, aid, ip)
if re != nil {
err = re
return
}
if a == nil {
err = ecode.AccessDenied
return
}
if !isWhite && a.Author.Mid != mid {
err = ecode.AccessDenied
return
}
stat, err = s.data.ArchiveStat(c, aid)
if err != nil {
log.Error("s.data.ArchiveStat aid(%d)|mid(%d)|error(%v)", aid, mid, err)
return
}
if stat == nil {
return
}
if stat.ArchiveStat.Play >= 100 {
stat.ArchiveAreas, err = s.data.ArchiveArea(c, aid)
}
log.Info("s.ArchiveAnalyze aid(%d)|mid(%d)|stat(%+v)", aid, mid, stat)
return
}
// VideoRetention get video quit data.
func (s *Service) VideoRetention(c context.Context, cid, mid int64, ip string) (res *data.VideoQuit, err error) {
var (
qs []int64
arc *api.Arc
video *archive.Video
isWhite bool
)
for _, m := range s.c.Whitelist.DataMids {
if m == mid {
isWhite = true
break
}
}
if video, err = s.arc.VideoByCid(c, int64(cid), ip); err != nil {
err = ecode.AccessDenied
return
}
if video == nil {
return
}
if arc, err = s.arc.Archive(c, video.Aid, ip); err == nil && !isWhite && arc.Author.Mid != mid {
err = ecode.AccessDenied
return
}
qs, err = s.data.VideoQuitPoints(c, cid)
res = &data.VideoQuit{
Point: appVideoQuit(qs),
Duration: sliceDuration(qs),
}
log.Info("s.VideoRetention cid(%d)|mid(%d)|quitPoints(%+v)|video(%+v)|res(%+v)", cid, mid, qs, video, res)
return
}
// >7 interval=(n/7四舍五入)
func appVideoQuit(qps []int64) []int64 {
cnt := len(qps) + 1
if cnt <= 7 {
return qps
}
nqps := make([]int64, 0)
interval := int64(math.Floor(float64(cnt)/7.0 + 0.5))
for i := 1; i < 8; i++ {
k := interval * int64(i)
if k > int64(cnt)-1 {
break
}
nqps = append(nqps, qps[k-1])
}
return nqps
}
func sliceDuration(qps []int64) (ds []int64) {
cnt := len(qps) + 1
if cnt <= 7 {
for i := 1; i < cnt; i++ {
ds = append(ds, int64(i)*30)
}
return
}
interval := int64(math.Floor(float64(cnt)/7.0 + 0.5))
for i := 1; i < 8; i++ {
k := interval * int64(i)
if k > int64(cnt)-1 {
break
}
ds = append(ds, (k)*30)
}
return
}
// AppVideoQuitPoints get app video quit data.
func (s *Service) AppVideoQuitPoints(c context.Context, cid, mid int64, ip string) (res []int64, err error) {
if res, err = s.VideoQuitPoints(c, cid, mid, ip); err != nil {
return
}
res = appVideoQuit(res)
return
}
// AppUpIncr for Play/Dm/Reply/Fav/Share/Elec/Coin incr.
func (s *Service) AppUpIncr(c context.Context, mid int64, ty int8, ip string) (res []*data.AppViewerIncr, err error) {
incr, err := s.UpIncr(c, mid, ty, ip)
if err != nil {
return
}
if len(incr) == 0 {
return
}
res = make([]*data.AppViewerIncr, 0, len(incr))
sortK := make([]string, 0, len(incr))
for k := range incr {
sortK = append(sortK, k)
}
sort.Strings(sortK)
for _, k := range sortK {
v, ok := incr[k]
if !ok {
continue
}
if v != nil {
av := &data.AppViewerIncr{}
tm, _ := time.Parse("20060102", k)
av.DateKey = tm.Unix()
av.Arcs = v.Arcs
av.TotalIncr = v.TotalIncr
trs := make([]*data.Rank, 0, len(v.TyRank))
for rk, rv := range v.TyRank {
tr := &data.Rank{}
tr.Name = rk
tr.Rank = rv
trs = append(trs, tr)
}
av.TyRank = trs
res = append(res, av)
}
}
return
}
// AppStat get app archive static data.
func (s *Service) AppStat(c context.Context, mid int64) (sts *data.AppStatList, err error) {
sts = &data.AppStatList{}
sts.Show = 1
if sts.Show == 0 {
return
}
var (
wg sync.WaitGroup
viewChan = make(chan *data.AppStat, 6)
fanChan = make(chan *data.AppStat, 6)
comChan = make(chan *data.AppStat, 6)
dmChan = make(chan *data.AppStat, 6)
)
for i := 0; i < 6; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
datekey := time.Now().AddDate(0, 0, -1-i).Add(-12 * time.Hour).Format("2006-01-02")
dt := time.Now().AddDate(0, 0, -1-i).Add(-12 * time.Hour).Format("20060102")
res, err := s.data.UpStat(c, mid, dt)
if err != nil {
log.Error("s.data.UpStat mid(%d)|err(%v)", mid, err)
return
}
if res == nil {
return
}
viewChan <- &data.AppStat{Date: datekey, Num: res.View}
fanChan <- &data.AppStat{Date: datekey, Num: res.Fans}
comChan <- &data.AppStat{Date: datekey, Num: res.Reply}
dmChan <- &data.AppStat{Date: datekey, Num: res.Dm}
}(i)
}
wg.Wait()
close(viewChan)
close(fanChan)
close(comChan)
close(dmChan)
for v := range viewChan {
sts.View = append(sts.View, v)
}
for v := range fanChan {
sts.Fans = append(sts.Fans, v)
}
for v := range comChan {
sts.Comment = append(sts.Comment, v)
}
for v := range dmChan {
sts.Danmu = append(sts.Danmu, v)
}
sort.Slice(sts.View, func(i, j int) bool {
return sts.View[i].Date > sts.View[j].Date
})
sort.Slice(sts.Fans, func(i, j int) bool {
return sts.Fans[i].Date > sts.Fans[j].Date
})
sort.Slice(sts.Comment, func(i, j int) bool {
return sts.Comment[i].Date > sts.Comment[j].Date
})
sort.Slice(sts.Danmu, func(i, j int) bool {
return sts.Danmu[i].Date > sts.Danmu[j].Date
})
// set increment num
for i := 0; i < len(sts.View)-1; i++ {
if sts.View[i].Num = sts.View[i].Num - sts.View[i+1].Num; sts.View[i].Num < 0 {
sts.View[i].Num = 0
}
if sts.Fans[i].Num = sts.Fans[i].Num - sts.Fans[i+1].Num; sts.Fans[i].Num < 0 {
sts.Fans[i].Num = 0
}
if sts.Comment[i].Num = sts.Comment[i].Num - sts.Comment[i+1].Num; sts.Comment[i].Num < 0 {
sts.Comment[i].Num = 0
}
if sts.Danmu[i].Num = sts.Danmu[i].Num - sts.Danmu[i+1].Num; sts.Danmu[i].Num < 0 {
sts.Danmu[i].Num = 0
}
}
// rm last element
if len(sts.View) > 0 {
sts.View = sts.View[:len(sts.View)-1]
sts.Fans = sts.Fans[:len(sts.Fans)-1]
sts.Comment = sts.Comment[:len(sts.Comment)-1]
sts.Danmu = sts.Danmu[:len(sts.Danmu)-1]
}
return
}

View File

@@ -0,0 +1,186 @@
package data
import (
"context"
"sort"
"sync"
"time"
"go-common/app/interface/main/creative/model/data"
"go-common/app/service/main/archive/api"
"go-common/library/log"
)
// UpPlaySourceAnalysis get play analysis.
func (s *Service) UpPlaySourceAnalysis(c context.Context, mid int64) (res *data.PlaySource, err error) {
if res, err = s.data.UpPlaySourceAnalysis(c, mid); err != nil {
log.Error("s.data.UpPlaySourceAnalysis err(%v)", err)
}
return
}
// reverse reverses a slice of ints in place.
func reverse(s []int64) {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
}
// UpArcPlayAnalysis get play list.
func (s *Service) UpArcPlayAnalysis(c context.Context, mid int64, cp int, ip string) (res *data.ArchivePlayList, err error) {
var (
originAIDs []int64
)
res = &data.ArchivePlayList{} //初始化返回值
dt := "0030" //最近30个稿件
originAIDs, err = s.data.UpArcQuery(c, mid, dt, cp)
if err != nil {
log.Error("s.data.UpArcQuery mid(%d)|err(%v)", err, mid)
return
}
log.Info("s.data.UpArcQuery originAIDs(%+v)|len(%d)|mid(%d)", originAIDs, len(originAIDs), mid)
reverse(originAIDs) //反转获取最近aid list.
aids := make([]int64, 0, 30)
aidsMap := make(map[int]int64)
sortK := make([]int, 0, 30)
for k, aid := range originAIDs { //取最近30个aid
aidsMap[k] = aid
sortK = append(sortK, k)
if len(sortK) == 30 {
break
}
}
sort.Slice(sortK, func(i, j int) bool { //30个aid索引从小到大排列
return sortK[i] < sortK[j]
})
for _, ak := range sortK {
if aid, ok := aidsMap[ak]; ok {
aids = append(aids, aid)
}
}
count := len(aids)
log.Info("s.data.UpArcQuery aids(%+v)|len(%d)|mid(%d)", aids, count, mid)
if count == 0 {
return
}
aps := make([]*data.ArchivePlay, 0, count)
apsMap := make(map[int64]*data.ArchivePlay, count)
var (
wg sync.WaitGroup
l sync.RWMutex
avm map[int64]*api.Arc
)
start := time.Now()
for _, aid := range aids { //并发获取aid对应的播放信息
wg.Add(1)
go func(aid int64) {
defer wg.Done()
start = time.Now()
var ap *data.ArchivePlay
if ap, err = s.data.UpArcPlayAnalysis(context.Background(), aid); err != nil {
log.Error("s.data.UpArcPlayAnalysis err(%v)", err)
}
elapsed := time.Since(start)
log.Info("s.data.UpArcPlayAnalysis ap(%+v) elapsed(%v)", ap, elapsed)
if ap != nil {
l.Lock()
apsMap[aid] = ap
l.Unlock()
}
}(aid)
}
wg.Add(1)
go func() {
defer wg.Done()
if avm, err = s.arc.Archives(c, aids, ip); err != nil {
log.Error("s.arc.Archives mid(%d)|aids(%+v)|ip(%s)|err(%v)", mid, aids, ip, err)
err = nil
}
}()
wg.Wait()
elapsed := time.Since(start)
log.Info("s.data.UpArcPlayAnalysis aids(%+v)|apsMap(%+v)|len(apsMap|%d)|len(avm|%d)|elapsed(%v)", apsMap, aids, len(avm), len(apsMap), elapsed)
for _, aid := range aids {
if ap, ok := apsMap[aid]; ok {
if av, ok := avm[aid]; ok && av != nil && ap != nil {
ap.Title = av.Title
}
aps = append(aps, ap)
}
}
sort.Slice(aps, func(i, j int) bool { //30个aid按创建时间从小到大排列
return aps[i].CTime < aps[j].CTime
})
res.ArcPlayList = aps
return
}
// ThirtyDayArchive for Play/Dm/Reply/Fav/Share/Elec/Coin for 30 days.
func (s *Service) ThirtyDayArchive(c context.Context, mid int64, ty int8) (res []*data.ThirtyDay, err error) {
tyStr, _ := data.IncrTy(ty)
if res, err = s.data.ThirtyDayArchiveCache(c, mid, tyStr); err != nil && len(res) != 0 {
log.Info("creatorDataArchive mid(%d) type(%d) cache hit", mid, ty)
return
}
if res, err = s.data.ThirtyDayArchive(c, mid, ty); len(res) != 0 {
timeSlice := make([]int64, 0, 30)
resMap := make(map[int64]int64)
for i := 30; i > 0; i-- { //从昨天往前推算30天生成30天对应的时间戳
var tm time.Time
dt := time.Now().AddDate(0, 0, -1-i).Add(-12 * time.Hour).Format("20060102")
tm, err = time.Parse("20060102", dt)
if err != nil {
log.Error("time.Parse error(%v)", err)
return
}
t := tm.Unix()
timeSlice = append(timeSlice, t)
}
for _, v := range res { //映射原始时间戳集合
resMap[v.DateKey] = v.DateKey
}
if len(res) < 30 { //如果当前的数据不够30条则补齐30条
for _, v := range timeSlice {
if _, ok := resMap[v]; !ok { //当前时间戳不在原始时间戳集合存在则使用生成的时间戳
td := &data.ThirtyDay{
DateKey: v,
}
res = append(res, td)
}
if len(res) == 30 { //添加到30条为止
break
}
}
log.Info("s.data.ThirtyDayArchive append mid(%d) type(%d) return data(%+v)", mid, ty, res)
}
tds := make([]*data.ThirtyDay, 0, 30)
skeys := make([]int64, 0, 30)
tdMap := make(map[int64]int64)
for _, v := range res {
if v != nil {
tdMap[v.DateKey] = v.TotalIncr //设置时间戳和动态数据的键值对
skeys = append(skeys, v.DateKey) //获取时间戳集合
}
}
sort.Slice(skeys, func(i, j int) bool { //对时间戳做降序排列
return skeys[i] > skeys[j]
})
for _, k := range skeys { //按照排序好的时间戳组装最终的返回数据
if v, ok := tdMap[k]; ok {
td := &data.ThirtyDay{}
td.DateKey = k
td.TotalIncr = v
tds = append(tds, td)
if len(tds) == 30 { //只取30条
break
}
}
}
log.Info("s.data.ThirtyDayArchive mid(%d) type(%d) cache miss res(%+v)", mid, ty, tds)
res = tds
s.data.AddCache(func() {
s.data.AddThirtyDayArchiveCache(context.Background(), mid, tyStr, tds)
})
}
return
}

View File

@@ -0,0 +1,87 @@
package data
import (
"context"
"sort"
"time"
"go-common/app/interface/main/creative/model/data"
artmdl "go-common/app/interface/openplatform/article/model"
"go-common/library/log"
)
// ThirtyDayArticle for 30 days.
func (s *Service) ThirtyDayArticle(c context.Context, mid int64, ip string) (res []*artmdl.ThirtyDayArticle, err error) {
if res, err = s.data.ThirtyDayArticleCache(c, mid); err != nil && len(res) != 0 {
return
}
if res, err = s.art.ThirtyDayArticle(c, mid, ip); err != nil && res != nil {
s.data.AddCache(func() {
s.data.AddThirtyDayArticleCache(context.Background(), mid, res)
})
}
return
}
//ArtThirtyDay for article.
func (s *Service) ArtThirtyDay(c context.Context, mid int64, ty byte) (res []*data.ArtTrend, err error) {
if res, err = s.data.ArtThirtyDay(c, mid, ty); err != nil {
log.Error("s.data.ArtThirtyDay mid(%d)|err(%v)", mid, err)
}
return
}
//ArtRank for article rank.
func (s *Service) ArtRank(c context.Context, mid int64, ty byte) (res *data.ArtRankList, err error) {
daytime := time.Now().AddDate(0, 0, -1).Add(-12 * time.Hour)
dt := daytime.Format("20060102")
var ar *data.ArtRankMap
if ar, err = s.data.ArtRank(c, mid, ty, dt); err != nil {
log.Error("s.data.ArtRank mid(%d)|err(%v)", mid, err)
return
}
if ar == nil {
log.Info("s.data.ArtRank mid(%d) article rank(%+v)", mid, ar)
return
}
sortK := make([]int, 0, len(ar.AIDs))
aids := make([]int64, 0, len(ar.AIDs))
for k, v := range ar.AIDs {
aids = append(aids, v)
sortK = append(sortK, k)
}
artMap, _ := s.art.ArticleMetas(c, aids, "")
if len(artMap) == 0 {
return
}
arts := make([]*data.ArtMeta, 0, len(artMap))
sort.Ints(sortK)
for _, k := range sortK {
if aid, ok := ar.AIDs[k]; ok {
if a, ok := artMap[aid]; ok {
art := &data.ArtMeta{}
art.AID = a.ID
art.Title = a.Title
art.PTime = a.PublishTime
if v, ok := ar.Incrs[k]; ok {
art.Incr = v
}
arts = append(arts, art)
}
}
}
res = &data.ArtRankList{Arts: arts}
return
}
//ArtReadAnalysis for article.
func (s *Service) ArtReadAnalysis(c context.Context, mid int64) (res *data.ArtRead, err error) {
if res, err = s.data.ReadAnalysis(c, mid); err != nil {
log.Error("s.data.ReadAnalysis mid(%d)|err(%v)", mid, err)
}
return
}

View File

@@ -0,0 +1,143 @@
package data
import (
"context"
"sort"
"go-common/app/interface/main/creative/model/data"
"go-common/app/interface/main/creative/model/medal"
account "go-common/app/service/main/account/model"
"go-common/library/log"
"go-common/library/sync/errgroup"
)
var (
rankKeys = []string{data.PlayDuration, data.VideoAct, data.DynamicAct}
)
// UpFansAnalysisForWeb get web fans data.
func (s *Service) UpFansAnalysisForWeb(c context.Context, mid int64, ip string) (res *data.WebFan, err error) {
var (
origin *data.WebFan
rkList map[string][]*data.RankInfo
mdlRank []*medal.FansRank
)
if origin, err = s.data.UpFansAnalysisForWeb(c, mid, data.Thirty); err != nil {
log.Error("s.data.UpFansAnalysisForWeb err(%v)", err)
return
}
if origin == nil {
return
}
group, ctx := errgroup.WithContext(c)
group.Go(func() (err error) {
if rkList, err = s.getTopList(ctx, mid, origin.RankMap, ip); err != nil {
log.Error("s.getTopList mid(%d)|err(%v)", mid, err)
err = nil
}
return
})
group.Go(func() (err error) {
if mdlRank, err = s.medal.Rank(ctx, mid); err != nil {
log.Error("s.medal.Rank mid(%d)|err(%v)", mid, err)
err = nil
}
return
})
group.Wait()
if len(rkList) == 0 {
log.Info("s.getTopList is empty rkList(%+v) ", rkList)
rkList = make(map[string][]*data.RankInfo)
}
for _, key := range rankKeys {
if v, ok := rkList[key]; ok {
rkList[key] = v
} else {
rkList[key] = nil
}
}
log.Info("s.getTopList rkList(%+v)|len(%d)", rkList, len(rkList))
res = &data.WebFan{
Summary: origin.Summary,
Source: origin.Source,
RankList: rkList,
RankMedal: map[string][]*medal.FansRank{
"medal": mdlRank,
},
}
return
}
// sort mid list and get uname/avatar info
func (s *Service) getTopList(c context.Context, mid int64, RankMap map[string]map[string]int32, ip string) (rkList map[string][]*data.RankInfo, err error) {
rkList = make(map[string][]*data.RankInfo)
for _, key := range rankKeys {
vd, ok := RankMap[key] //map playduration videoact dynamicact top10 mids.
if !ok {
continue
}
sortK := make([]string, 0, 10)
for key := range vd { //sort top mids by key, for example (dr2,dr1,dr3...)
sortK = append(sortK, key)
}
sort.Slice(sortK, func(i, j int) bool { //for example (dr1,dr2,dr3...)
return sortK[i] < sortK[j]
})
mids := make([]int64, 0, 10)
for _, k := range sortK { //get sort mids slice.
if mid, ok := vd[k]; ok {
mids = append(mids, int64(mid))
}
}
if len(mids) == 0 {
continue
}
var (
g, ctx = errgroup.WithContext(c)
users map[int64]*account.Info
followers map[int64]int
)
g.Go(func() error { //获取用户信息
if users, err = s.acc.Infos(ctx, mids, ip); err != nil {
log.Error("s.acc.Infos mid(%d)|mids(%v)|ip(%s)|err(%v)", mid, mids, ip, err)
}
return err
})
g.Go(func() error { //获取关注状态
if followers, err = s.acc.Relations2(ctx, mid, mids, ip); err != nil {
log.Error("s.acc.Relations mid(%d)|ip(%s)|err(%v)", mid, ip, err)
}
return err
})
if g.Wait() != nil {
return
}
rkInfos := make([]*data.RankInfo, 0, 10)
for _, m := range mids {
ri := &data.RankInfo{}
if v, ok := users[m]; ok { //get userinfo by sorted mids.
ri.MID = v.Mid
ri.Uname = v.Name
ri.Photo = v.Face
}
if fl, ok := followers[m]; ok { //get relation by sorted mids.
ri.Relation = fl
}
rkInfos = append(rkInfos, ri) //append top10 useinfo.
if len(rkInfos) == 10 {
break
}
}
rkList[key] = rkInfos //map playduration videoact dynamicact top10 userinfo.
}
log.Info("getTopList mid(%d)|rkList(%+v) ", mid, rkList)
return
}
//UpFansMedal for get fan medel count.
func (s *Service) UpFansMedal(c context.Context, mid int64) (fansMdl *data.UpFansMedal, err error) {
if fansMdl, err = s.data.UpFansMedal(c, mid); err != nil {
log.Error("s.data.UpFansMedal mid(%d)|err(%v)", mid, err)
}
return
}

View File

@@ -0,0 +1,354 @@
package data
import (
"context"
"sort"
"time"
"go-common/app/interface/main/creative/model/data"
"go-common/app/interface/main/creative/model/tag"
"go-common/library/ecode"
"go-common/library/log"
)
func beginningOfDay(t time.Time) time.Time {
d := time.Duration(-t.Hour()) * time.Hour
return t.Truncate(time.Hour).Add(d)
}
func getTuesday(now time.Time) time.Time {
t := beginningOfDay(now)
weekday := int(t.Weekday())
if weekday == 0 {
weekday = 7
}
d := time.Duration(-weekday+2) * 24 * time.Hour
return t.Truncate(time.Hour).Add(d)
}
func getSunday(now time.Time) time.Time {
t := beginningOfDay(now)
weekday := int(t.Weekday())
if weekday == 0 {
return t
}
d := time.Duration(7-weekday) * 24 * time.Hour
return t.Truncate(time.Hour).Add(d)
}
func getDate() (sd string) {
t := time.Now()
td := getTuesday(t).Add(12 * time.Hour)
if t.Before(td) { //当前时间在本周二12点之前则取上上周日的数据否则取上周日的数据
sd = getSunday(t.AddDate(0, 0, -14)).Format("20060102")
} else {
sd = getSunday(t.AddDate(0, 0, -7)).Format("20060102")
}
log.Info("current time (%s) tuesday (%s) sunday (%s)", t.Format("2006-01-02 15:04:05"), td, sd)
return
}
// NewStat get stat from hbase.
func (s *Service) NewStat(c context.Context, mid int64, ip string) (r *data.Stat, err error) {
hbaseDate1 := time.Now().AddDate(0, 0, -1).Add(-12 * time.Hour).Format("20060102")
hbaseDate2 := time.Now().AddDate(0, 0, -2).Add(-12 * time.Hour).Format("20060102")
var r1, r2 *data.UpBaseStat
if r1, err = s.data.UpStat(c, mid, hbaseDate1); err != nil || r1 == nil {
log.Error("s.data.NewStat error(%v) mid(%d) r1(%v) ip(%s)", err, mid, r1, ip)
err = ecode.CreativeDataErr
return
}
if r2, err = s.data.UpStat(c, mid, hbaseDate2); err != nil || r2 == nil {
log.Error("s.data.NewStat error(%v) mid(%d) r2(%v) ip(%s)", err, mid, r2, ip)
err = ecode.CreativeDataErr
return
}
r = &data.Stat{}
if r1 != nil {
r.Play = r1.View
r.Dm = r1.Dm
r.Comment = r1.Reply
r.Fan = r1.Fans
r.Fav = r1.Fav
r.Like = r1.Like
r.Share = r1.Share
r.Coin = r1.Coin
r.Elec = r1.Elec
}
log.Info("s.data.UpStat hbaseDate1(%+v) mid(%d)", r1, mid)
if r2 != nil {
r.PlayLast = r2.View
r.DmLast = r2.Dm
r.CommentLast = r2.Reply
r.FanLast = r2.Fans
r.FavLast = r2.Fav
r.LikeLast = r2.Like
r.ShareLast = r2.Share
r.CoinLast = r2.Coin
r.ElecLast = r2.Elec
}
log.Info("s.data.UpStat hbaseDate2 (%+v) mid(%d)", r2, mid)
pfl, err := s.acc.ProfileWithStat(c, mid)
if err != nil {
return
}
r.Fan = int64(pfl.Follower)
return
}
// ViewerBase get up viewer base data.
func (s *Service) ViewerBase(c context.Context, mid int64) (res map[string]*data.ViewerBase, err error) {
dt := getDate()
// try cache
if res, _ = s.data.ViewerBaseCache(c, mid, dt); res != nil {
s.pCacheHit.Incr("viewer_base_cache")
return
}
// from data source
if res, err = s.data.ViewerBase(c, mid, dt); len(res) != 0 {
s.pCacheMiss.Incr("viewer_base_cache")
s.data.AddCache(func() {
s.data.AddViewerBaseCache(context.Background(), mid, dt, res)
})
}
return
}
// ViewerArea get up viewer area data.
func (s *Service) ViewerArea(c context.Context, mid int64) (res map[string]map[string]int64, err error) {
dt := getDate()
// try cache
if res, _ = s.data.ViewerAreaCache(c, mid, dt); res != nil {
s.pCacheHit.Incr("viewer_area_cache")
return
}
// from data source
if res, err = s.data.ViewerArea(c, mid, dt); len(res) != 0 {
s.pCacheMiss.Incr("viewer_area_cache")
s.data.AddCache(func() {
s.data.AddViewerAreaCache(context.Background(), mid, dt, res)
})
}
return
}
// CacheTrend get trend from mc.
func (s *Service) CacheTrend(c context.Context, mid int64) (res map[string]*data.ViewerTrend, err error) {
dt := getDate()
// try cache
if res, err = s.data.TrendCache(c, mid, dt); err != nil {
log.Error("trend s.data.TrendCache err(%v)", err)
return
}
if len(res) != 0 {
s.pCacheHit.Incr("trend_cache")
return
}
// from data source
if res, err = s.viewerTrend(c, mid, dt); err != nil {
return
}
s.pCacheMiss.Incr("trend_cache")
if len(res) != 0 {
s.data.AddCache(func() {
s.data.AddTrendCache(context.Background(), mid, dt, res)
})
}
return
}
// ViewerTrend get up viewer trend data.
func (s *Service) viewerTrend(c context.Context, mid int64, dt string) (res map[string]*data.ViewerTrend, err error) {
ut, err := s.data.ViewerTrend(c, mid, dt)
if err != nil || ut == nil {
log.Error("trend s.data.ViewerTrend err(%v)", err)
return
}
f := []string{"fan", "not_fan"}
skeys := make([]int, 0) //for tag sort.
tgs := make([]int64, 0) // for request tag name.
res = make(map[string]*data.ViewerTrend)
for _, fk := range f {
td := ut[fk]
vt := &data.ViewerTrend{}
if td == nil {
vt.Ty = nil
vt.Tag = nil
res[fk] = vt
continue
}
tg := make(map[int]string) //return tag map to user.
ty := make(map[string]int64) //return type map to user.
//deal type for type name.
if td.Ty != nil {
for k, v := range td.Ty {
ke := int16(k)
if t, ok := s.p.TypeMapCache[ke]; ok {
ty[t.Name] = v
}
}
} else {
ty = nil
}
// deal tag for tag name.
if td.Tag != nil {
for k, v := range td.Tag {
tgs = append(tgs, v)
skeys = append(skeys, k)
}
var tlist []*tag.Meta
if tlist, err = s.dtag.TagList(c, tgs); err != nil {
log.Error("trend s.dtag.TagList err(%v)", err)
}
tNameMap := make(map[int64]string)
for _, v := range tlist {
tNameMap[v.TagID] = v.TagName
}
for _, k := range skeys {
if _, ok := tNameMap[td.Tag[k]]; ok {
tg[k] = tNameMap[td.Tag[k]]
}
}
} else {
tg = nil
}
vt.Ty = ty
vt.Tag = tg
res[fk] = vt
}
return
}
// RelationFansDay get up viewer trend data.
func (s *Service) RelationFansDay(c context.Context, mid int64) (res map[string]map[string]int, err error) {
dt := time.Now().AddDate(0, 0, -1).Add(-12 * time.Hour).Format("20060102")
// try cache
if res, _ = s.data.RelationFansDayCache(c, mid, dt); res != nil {
s.pCacheHit.Incr("relation_fans_day_cache")
return
}
// from data source
if res, err = s.data.RelationFansDay(c, mid); len(res) != 0 {
s.pCacheMiss.Incr("relation_fans_day_cache")
s.data.AddCache(func() {
s.data.AddRelationFansDayCache(context.Background(), mid, dt, res)
})
}
return
}
// RelationFansHistory get relation history data by month.
func (s *Service) RelationFansHistory(c context.Context, mid int64, month string) (res map[string]map[string]int, err error) {
if res, err = s.data.RelationFansHistory(c, mid, month); err != nil {
log.Error("s.data.RelationFansHistory err(%v)", err)
}
return
}
// RelationFansMonth get up viewer trend data.
func (s *Service) RelationFansMonth(c context.Context, mid int64) (res map[string]map[string]int, err error) {
dt := time.Now().AddDate(0, 0, -1).Add(-12 * time.Hour).Format("20060102")
// try cache
if res, _ = s.data.RelationFansMonthCache(c, mid, dt); res != nil {
s.pCacheHit.Incr("relation_fans_month_cache")
return
}
// from data source
if res, err = s.data.RelationFansMonth(c, mid); len(res) != 0 {
s.pCacheMiss.Incr("relation_fans_month_cache")
s.data.AddCache(func() {
s.data.AddRelationFansMonthCache(context.Background(), mid, dt, res)
})
}
return
}
// ViewerActionHour get up viewer action hour data.
func (s *Service) ViewerActionHour(c context.Context, mid int64) (res map[string]*data.ViewerActionHour, err error) {
dt := getDate()
// try cache
if res, _ = s.data.ViewerActionHourCache(c, mid, dt); res != nil {
s.pCacheHit.Incr("viewer_action_hour_cache")
return
}
// from data source
if res, err = s.data.ViewerActionHour(c, mid, dt); len(res) != 0 {
s.data.AddCache(func() {
s.pCacheMiss.Incr("viewer_action_hour_cache")
s.data.AddViewerActionHourCache(context.Background(), mid, dt, res)
})
}
return
}
// UpIncr for Play/Dm/Reply/Fav/Share/Elec/Coin incr.
func (s *Service) UpIncr(c context.Context, mid int64, ty int8, ip string) (res map[string]*data.ViewerIncr, err error) {
tyStr, _ := data.IncrTy(ty)
res = make(map[string]*data.ViewerIncr)
daytime := time.Now().AddDate(0, 0, -1).Add(-12 * time.Hour)
datekey := daytime.Format("20060102")
dt := daytime.Format("20060102")
vic, _ := s.data.ViewerIncrCache(c, mid, tyStr, dt)
if vic != nil {
s.pCacheHit.Incr("viewer_incr_cache")
res[datekey] = vic
log.Info("s.data.ViewerIncrCache mid(%d) cache(%v) err(%v)", mid, vic, err)
return
}
incr, _ := s.data.UpIncr(c, mid, ty, dt)
if incr == nil {
res[datekey] = nil
log.Info("s.data.UpIncr mid(%d) incr(%v) err(%v)", incr, err)
return
}
tyRank := make(map[string]int) //return type map to user.
for k, v := range incr.Rank {
ke := int16(k)
if t, ok := s.p.TypeMapCache[ke]; ok {
tyRank[t.Name] = v
}
}
sortK := make([]int, 0, len(incr.TopAIDList))
aids := make([]int64, 0, len(incr.TopAIDList))
for k, v := range incr.TopAIDList {
aids = append(aids, v)
sortK = append(sortK, k)
}
avm, _ := s.p.BatchArchives(c, mid, aids, ip)
if len(avm) == 0 {
return
}
sort.Ints(sortK)
arcs := make([]*data.ArcInc, 0, len(avm))
for _, k := range sortK {
if aid, ok := incr.TopAIDList[k]; ok {
if av, ok := avm[aid]; ok {
al := &data.ArcInc{}
al.AID = av.Archive.Aid
al.PTime = av.Archive.PTime
al.Title = av.Archive.Title
al.DayTime = daytime.Unix()
if _, ok := incr.TopIncrList[k]; ok {
al.Incr = incr.TopIncrList[k]
}
arcs = append(arcs, al)
}
}
}
vi := &data.ViewerIncr{}
vi.Arcs = arcs
vi.TotalIncr = incr.Incr
if len(tyRank) == 0 {
vi.TyRank = nil
} else {
vi.TyRank = tyRank
}
res[datekey] = vi
// insert cache. NOTE: sync reason?
s.data.AddCache(func() {
s.pCacheMiss.Incr("viewer_incr_cache")
s.data.AddViewerIncrCache(context.Background(), mid, tyStr, dt, vi)
})
return
}

View File

@@ -0,0 +1,240 @@
package data
import (
"context"
"strings"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/dao/account"
"go-common/app/interface/main/creative/dao/activity"
"go-common/app/interface/main/creative/dao/archive"
"go-common/app/interface/main/creative/dao/article"
"go-common/app/interface/main/creative/dao/bfs"
"go-common/app/interface/main/creative/dao/data"
"go-common/app/interface/main/creative/dao/medal"
"go-common/app/interface/main/creative/dao/tag"
arcMdl "go-common/app/interface/main/creative/model/archive"
dataMdl "go-common/app/interface/main/creative/model/data"
"go-common/app/interface/main/creative/service"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/stat/prom"
)
//Service struct
type Service struct {
c *conf.Config
data *data.Dao
acc *account.Dao
arc *archive.Dao
art *article.Dao
dtag *tag.Dao
dbfs *bfs.Dao
medal *medal.Dao
act *activity.Dao
p *service.Public
pCacheHit *prom.Prom
pCacheMiss *prom.Prom
}
//New get service
func New(c *conf.Config, rpcdaos *service.RPCDaos, p *service.Public) *Service {
s := &Service{
c: c,
data: data.New(c),
acc: rpcdaos.Acc,
arc: rpcdaos.Arc,
art: rpcdaos.Art,
dtag: tag.New(c),
dbfs: bfs.New(c),
medal: medal.New(c),
act: activity.New(c),
p: p,
pCacheHit: prom.CacheHit,
pCacheMiss: prom.CacheMiss,
}
return s
}
// Stat get stat.
func (s *Service) Stat(c context.Context, mid int64, ip string) (r *dataMdl.Stat, err error) {
if r, err = s.data.Stat(c, ip, mid); err != nil {
return
}
pfl, err := s.acc.ProfileWithStat(c, mid)
if err != nil {
return
}
r.Fan = int64(pfl.Follower)
return
}
// Tags get predict tag.
func (s *Service) Tags(c context.Context, mid int64, tid uint16, title, filename, desc, cover string, tagFrom int8) (res *dataMdl.Tags, err error) {
res = &dataMdl.Tags{
Tags: make([]string, 0),
}
var ctags []*dataMdl.CheckedTag
ctags, err = s.TagsWithChecked(c, mid, tid, title, filename, desc, cover, tagFrom)
if len(ctags) > 0 {
for _, t := range ctags {
res.Tags = append(res.Tags, t.Tag)
}
}
return
}
// TagsWithChecked get predict tag with checked mark.
func (s *Service) TagsWithChecked(c context.Context, mid int64, tid uint16, title, filename, desc, cover string, tagFrom int8) (retTags []*dataMdl.CheckedTag, err error) {
retTags = make([]*dataMdl.CheckedTag, 0)
var checkedTags []*dataMdl.CheckedTag
if checkedTags, err = s.data.TagsWithChecked(c, mid, tid, title, filename, desc, cover, tagFrom); err != nil {
log.Error("s.data.TagsWithChecked error(%v)", err)
err = nil
}
// no recommend tag, return
if len(checkedTags) == 0 {
return
}
actTagsMap := make(map[string]int64)
acts, _ := s.act.Activities(c)
// no acts, no filter and return
if len(acts) == 0 {
retTags = checkedTags
return
}
// filter act tags
for _, act := range acts {
tagsSlice := strings.Split(act.Tags, ",")
if len(tagsSlice) > 0 {
for _, tag := range tagsSlice {
actTagsMap[tag] = act.ID
}
}
actTagsMap[act.Name] = act.ID
}
for _, checkedTag := range checkedTags {
if _, ok := actTagsMap[checkedTag.Tag]; !ok {
retTags = append(retTags, checkedTag)
}
}
return
}
// VideoQuitPoints get video quit data.
func (s *Service) VideoQuitPoints(c context.Context, cid, mid int64, ip string) (res []int64, err error) {
// check cid owner
isWhite := false
for _, m := range s.c.Whitelist.DataMids {
if m == mid {
isWhite = true
break
}
}
if !isWhite {
var video *arcMdl.Video
if video, err = s.arc.VideoByCid(c, int64(cid), ip); err != nil {
err = ecode.AccessDenied
return
}
if arc, errr := s.arc.Archive(c, video.Aid, ip); errr == nil {
if arc.Author.Mid != mid {
err = ecode.AccessDenied
return
}
}
}
res, err = s.data.VideoQuitPoints(c, cid)
return
}
// ArchiveStat get video quit data.
func (s *Service) ArchiveStat(c context.Context, aid, mid int64, ip string) (stat *dataMdl.ArchiveData, err error) {
// check aid valid and owner
isWhite := false
for _, m := range s.c.Whitelist.DataMids {
if m == mid {
isWhite = true
break
}
}
if !isWhite {
a, re := s.arc.Archive(c, aid, ip)
if re != nil {
err = re
return
}
if a == nil {
log.Warn("arc not exist")
err = ecode.AccessDenied
return
}
if a.Author.Mid != mid {
log.Warn("owner mid(%d) and viewer mid(%d) are different ", a.Author.Mid, mid)
err = ecode.AccessDenied
return
}
}
if stat, err = s.data.ArchiveStat(c, aid); err != nil {
return
}
if stat == nil {
return
}
if stat.ArchiveStat != nil && stat.ArchiveStat.Play >= 100 {
if stat.ArchiveAreas, err = s.data.ArchiveArea(c, aid); err != nil {
log.Error(" s.data.ArchiveArea aid(%d)|mid(%d), err(%+v)", aid, mid, err)
return
}
}
//获取播放数据
if stat.ArchivePlay, err = s.data.UpArcPlayAnalysis(c, aid); err != nil {
log.Error(" s.data.UpArcPlayAnalysis aid(%d)|mid(%d), err(%+v)", aid, mid, err)
return
}
return
}
// Covers get covers from ai
func (s *Service) Covers(c context.Context, mid int64, fns []string, ip string) (cvs []string, err error) {
if cvs, err = s.data.RecommendCovers(c, mid, fns); err != nil {
log.Error("s.data.RecommendCovers err(%v)", mid, err)
return
}
return
}
// Ping service
func (s *Service) Ping(c context.Context) (err error) {
if err = s.data.Ping(c); err != nil {
log.Error("s.data.Dao.PingDb err(%v)", err)
}
return
}
// Close dao
func (s *Service) Close() {
s.data.Close()
}
// IsWhite check white.
func (s *Service) IsWhite(mid int64) (isWhite bool) {
for _, m := range s.c.Whitelist.DataMids {
if m == mid {
isWhite = true
break
}
}
return
}
// IsForbidVideoup fn.
func (s *Service) IsForbidVideoup(mid int64) (isForbid bool) {
for _, m := range s.c.Whitelist.ForbidVideoupMids {
if m == mid {
isForbid = true
break
}
}
return
}

View File

@@ -0,0 +1,154 @@
package data
import (
"context"
"flag"
"go-common/app/interface/main/creative/conf"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/creative/service"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
p *service.Public
)
func init() {
dir, _ := filepath.Abs("../../cmd/creative.toml")
flag.Set("conf", dir)
conf.Init()
rpcdaos := service.NewRPCDaos(conf.Conf)
p = service.New(conf.Conf, rpcdaos)
s = New(conf.Conf, rpcdaos, p)
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
Reset(func() {})
f(s)
}
}
var (
c = context.TODO()
MID = int64(27515256)
ty = int8(1)
ip = "127.0.0.1"
dt = "20180301"
)
func Test_AppStat(t *testing.T) {
Convey("AppStat", t, WithService(func(s *Service) {
Convey("AppStat", func() {
res, err := s.AppStat(c, MID)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}))
}
func Test_ViewerBase(t *testing.T) {
Convey("ViewerBase", t, WithService(func(s *Service) {
Convey("ViewerBase", func() {
res, err := s.ViewerBase(c, MID)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}))
}
func Test_ViewerArea(t *testing.T) {
Convey("ViewerArea", t, WithService(func(s *Service) {
Convey("ViewerArea", func() {
res, err := s.ViewerArea(c, MID)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}))
}
func Test_CacheTrend(t *testing.T) {
Convey("CacheTrend", t, WithService(func(s *Service) {
Convey("CacheTrend", func() {
res, err := s.CacheTrend(c, MID)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}))
}
func Test_RelationFansHistory(t *testing.T) {
Convey("RelationFansHistory", t, WithService(func(s *Service) {
Convey("RelationFansHistory", func() {
res, err := s.RelationFansHistory(c, MID, dt)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}))
}
func Test_RelationFansMonth(t *testing.T) {
Convey("RelationFansMonth", t, WithService(func(s *Service) {
Convey("RelationFansMonth", func() {
res, err := s.RelationFansMonth(c, MID)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}))
}
func Test_ViewerActionHour(t *testing.T) {
Convey("ViewerActionHour", t, WithService(func(s *Service) {
Convey("ViewerActionHour", func() {
res, err := s.ViewerActionHour(c, MID)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}))
}
func Test_UpIncr(t *testing.T) {
Convey("UpIncr", t, WithService(func(s *Service) {
Convey("UpIncr", func() {
res, err := s.UpIncr(c, MID, ty, ip)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}))
}
func Test_AppUpIncr(t *testing.T) {
Convey("AppUpIncr", t, WithService(func(s *Service) {
Convey("AppUpIncr", func() {
res, err := s.AppUpIncr(c, MID, ty, ip)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}))
}
func Test_ThirtyDayArchive(t *testing.T) {
Convey("ThirtyDayArchive", t, WithService(func(s *Service) {
Convey("ThirtyDayArchive", func() {
res, err := s.ThirtyDayArchive(c, MID, ty)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}))
}
func Test_ThirtyDayArticle(t *testing.T) {
Convey("ThirtyDayArticle", t, WithService(func(s *Service) {
Convey("ThirtyDayArticle", func() {
res, err := s.ThirtyDayArticle(c, MID, ip)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}))
}

View File

@@ -0,0 +1,36 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["service.go"],
importpath = "go-common/app/interface/main/creative/service/dynamic",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/dao/lottery:go_default_library",
"//app/interface/main/creative/model/lottery:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//library/log:go_default_library",
"//library/net/metadata:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,55 @@
package dynamic
import (
"context"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/dao/lottery"
lMdl "go-common/app/interface/main/creative/model/lottery"
"go-common/app/interface/main/creative/service"
"go-common/library/log"
"go-common/library/net/metadata"
)
//Service struct
type Service struct {
c *conf.Config
lottery *lottery.Dao
}
//New get service
func New(c *conf.Config, rpcdaos *service.RPCDaos) *Service {
s := &Service{
c: c,
lottery: lottery.New(c),
}
return s
}
// LotteryUserCheck fn
func (s *Service) LotteryUserCheck(c context.Context, mid int64) (check bool, err error) {
var (
ret int
ip = metadata.String(c, metadata.RemoteIP)
)
if ret, err = s.lottery.UserCheck(c, mid, ip); err != nil {
log.Error("s.lottery.UserCheck err(%v) | mid(%d), ip(%s)", err, mid, ip)
return
}
if ret == 1 {
check = true
}
return
}
// LotteryNotice fn
func (s *Service) LotteryNotice(c context.Context, aid, mid int64) (bind bool, err error) {
var ret *lMdl.Notice
if ret, err = s.lottery.Notice(c, aid, mid, metadata.String(c, metadata.RemoteIP)); err != nil {
log.Error("s.lottery.Notice err(%v) |aid(%d)|mid(%d)", err, aid, mid)
return
}
if ret != nil && ret.BizID > 0 {
bind = true
}
return
}

View File

@@ -0,0 +1,56 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"elec.go",
"service.go",
],
importpath = "go-common/app/interface/main/creative/service/elec",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/dao/account:go_default_library",
"//app/interface/main/creative/dao/archive:go_default_library",
"//app/interface/main/creative/dao/elec:go_default_library",
"//app/interface/main/creative/model/elec:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//app/service/main/account/model:go_default_library",
"//app/service/main/archive/api:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,242 @@
package elec
import (
"context"
"time"
model "go-common/app/interface/main/creative/model/elec"
account "go-common/app/service/main/account/model"
"go-common/app/service/main/archive/api"
"go-common/library/log"
)
const (
ftime = "2006-01-02"
)
// UserInfo get user elec info.
func (s *Service) UserInfo(c context.Context, mid int64, ip string) (data *model.UserInfo, err error) {
if data, err = s.elec.UserInfo(c, mid, ip); err != nil {
log.Error("s.elec.UserInfo(%d) error(%v)", mid, err)
}
return
}
// UserUpdate user join or exit elec.
func (s *Service) UserUpdate(c context.Context, mid int64, st int8, ip string) (data *model.UserInfo, err error) {
if data, err = s.elec.UserUpdate(c, mid, st, ip); err != nil {
log.Error("s.elec.UserUpdate(%d) error(%v)", mid, err)
}
return
}
// ArcUpdate arc open or close elec.
func (s *Service) ArcUpdate(c context.Context, mid, aid int64, st int8, ip string) (err error) {
if err = s.elec.ArcUpdate(c, mid, aid, st, ip); err != nil {
log.Error("s.elec.ArcInfo(%d,%d) error(%v)", mid, aid, err)
}
return
}
// Notify get up-to-date notice.
func (s *Service) Notify(c context.Context, ip string) (data *model.Notify, err error) {
if data, err = s.elec.Notify(c, ip); err != nil {
log.Error("s.elec.Notify error(%v)", err)
}
return
}
// Status get elec setting status.
func (s *Service) Status(c context.Context, mid int64, ip string) (data *model.Status, err error) {
if data, err = s.elec.Status(c, mid, ip); err != nil {
log.Error("s.elec.Status error(%d, %v)", mid, err)
}
return
}
// UpStatus update elec setting status.
func (s *Service) UpStatus(c context.Context, mid int64, spday int, ip string) (err error) {
if err = s.elec.UpStatus(c, mid, spday, ip); err != nil {
log.Error("s.elec.UpStatus(%d) error(%v)", mid, err)
}
return
}
// RecentRank recent rank.
func (s *Service) RecentRank(c context.Context, mid, size int64, ip string) (data []*model.Rank, err error) {
if data, err = s.elec.RecentRank(c, mid, size, ip); err != nil {
log.Error("s.elec.RecentRank error(%d, %v)", mid, err)
}
if len(data) == 0 {
log.Error("s.elec.TotalRank (%d, %v)", mid, data)
return
}
//data, _ = s.CheckIsFriend(c, data, mid, ip)
return
}
// CurrentRank current rank.
func (s *Service) CurrentRank(c context.Context, mid int64, ip string) (data []*model.Rank, err error) {
if data, err = s.elec.CurrentRank(c, mid, ip); err != nil {
log.Error("s.elec.CurrentRank error(%d, %v)", mid, err)
}
if len(data) == 0 {
log.Error("s.elec.TotalRank (%d, %v)", mid, data)
return
}
//data, _ = s.CheckIsFriend(c, data, mid, ip)
return
}
// TotalRank total rank.
func (s *Service) TotalRank(c context.Context, mid int64, ip string) (data []*model.Rank, err error) {
if data, err = s.elec.TotalRank(c, mid, ip); err != nil {
log.Error("s.elec.TotalRank error(%d, %v)", mid, err)
return
}
if len(data) == 0 {
log.Error("s.elec.TotalRank (%d, %v)", mid, data)
return
}
//data, _ = s.CheckIsFriend(c, data, mid, ip)
return
}
// DailyBill daily settlement.
func (s *Service) DailyBill(c context.Context, mid int64, pn, ps int, bg, end, ip string) (data *model.BillList, err error) {
if bg == "" {
bg = time.Now().Add(-7 * 24 * time.Hour).Format(ftime)
}
if end == "" {
end = time.Now().Format(ftime)
}
if data, err = s.elec.DailyBill(c, mid, pn, ps, bg, end, ip); err != nil {
log.Error("s.elec.DailyBill error(%d, %v)", mid, err)
}
return
}
// Balance get battery balance.
func (s *Service) Balance(c context.Context, mid int64, ip string) (data *model.Balance, err error) {
if data, err = s.elec.Balance(c, mid, ip); err != nil {
log.Error("s.elec.Balance error(%d, %v)", mid, err)
}
return
}
// AppDailyBill daily settlement.
func (s *Service) AppDailyBill(c context.Context, mid int64, pn, ps int, ip string) (cb *model.ChargeBill, err error) {
var data *model.BillList
bg := time.Now().Add(-24 * 30 * 12 * time.Hour).Format(ftime)
end := time.Now().Format(ftime)
if data, err = s.elec.DailyBill(c, mid, pn, ps, bg, end, ip); err != nil {
log.Error("s.elec.DailyBill error(%d, %v)", mid, err)
return
}
cb = &model.ChargeBill{}
if data == nil {
log.Error("s.elec.DailyBill mid(%d) data(%v)", mid, data)
return
}
bls := make([]*model.Bill, 0, len(data.List))
for _, v := range data.List {
bl := &model.Bill{}
bl.ID = v.ID
bl.MID = v.MID
bl.ChannelType = v.ChannelType
bl.ChannelTyName = v.ChannelTyName
bl.AddNum = v.AddNum
bl.ReduceNum = v.ReduceNum
bl.WalletBalance = v.WalletBalance
bl.DateVersion = v.DateVersion
bl.Remark = v.Remark
bl.MonthBillResp = v.MonthBillResp
t, _ := time.Parse(ftime, bl.DateVersion)
bl.Weekday = model.Weekday(t)
bls = append(bls, bl)
}
cb.List = bls
cb.Pager.Current = data.Pn
cb.Pager.Size = data.Ps
cb.Pager.Total = data.TotalCount
return
}
// RecentElec get recent charge info.
func (s *Service) RecentElec(c context.Context, mid int64, pn, ps int, ip string) (l *model.RecentElecList, err error) {
if l, err = s.elec.RecentElec(c, mid, pn, ps, ip); err != nil {
log.Error("s.elec.RecentElec error(%d, %v)", mid, err)
return
}
if l == nil || len(l.List) == 0 {
return
}
var (
mids, aids []int64
a map[int64]*api.Arc
u map[int64]*account.Info
)
for _, v := range l.List {
mids = append(mids, v.MID)
if v.AID > 0 {
aids = append(aids, v.AID)
}
}
if len(aids) > 0 {
if a, err = s.arc.Archives(c, aids, ip); err != nil {
log.Error("s.arc.Archives aids(%v), ip(%s) err(%v)", aids, ip, err)
return
}
}
if len(mids) > 0 {
if u, err = s.acc.Infos(c, mids, ip); err != nil {
log.Error("s.acc.Infos mids(%v), ip(%s) err(%v)", mids, ip, err)
return
}
}
els := make([]*model.RecentElec, 0, len(l.List))
for _, v := range l.List {
el := &model.RecentElec{}
el.AID = v.AID
el.MID = v.MID
el.ElecNum = v.ElecNum
el.Avatar = v.Avatar
el.CTime = v.CTime
if ui, ok := u[el.MID]; ok && ui != nil {
el.Avatar = ui.Face
el.Uname = ui.Name
}
if el.AID > 0 {
if av, ok := a[el.AID]; ok && av != nil {
el.Title = av.Title
}
}
els = append(els, el)
}
l.List = els
return
}
// RemarkList get remark list.
func (s *Service) RemarkList(c context.Context, mid int64, pn, ps int, bg, end, ip string) (rms *model.RemarkList, err error) {
if rms, err = s.elec.RemarkList(c, mid, pn, ps, bg, end, ip); err != nil {
log.Error("s.elec.RemarkList error(%d, %v)", mid, err)
}
return
}
// RemarkDetail get remark detail.
func (s *Service) RemarkDetail(c context.Context, mid, id int64, ip string) (rm *model.Remark, err error) {
if rm, err = s.elec.RemarkDetail(c, mid, id, ip); err != nil {
log.Error("s.elec.RemarkDetail error(%d, %d,%v)", mid, id, err)
}
return
}
// Remark reply a msg.
func (s *Service) Remark(c context.Context, mid, id int64, msg, ak, ck, ip string) (status int, err error) {
if status, err = s.elec.Remark(c, mid, id, msg, ak, ck, ip); err != nil {
log.Error("s.elec.Remark error(%d, %d, %v)", mid, id, err)
}
return
}

View File

@@ -0,0 +1,68 @@
package elec
import (
"context"
"go-common/library/log"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/dao/account"
"go-common/app/interface/main/creative/dao/archive"
"go-common/app/interface/main/creative/dao/elec"
elecMdl "go-common/app/interface/main/creative/model/elec"
"go-common/app/interface/main/creative/service"
)
//Service struct.
type Service struct {
c *conf.Config
elec *elec.Dao
acc *account.Dao
arc *archive.Dao
}
//New get service.
func New(c *conf.Config, rpcdaos *service.RPCDaos) *Service {
s := &Service{
c: c,
elec: elec.New(c),
acc: rpcdaos.Acc,
arc: rpcdaos.Arc,
}
return s
}
// UserState get user elec state.
func (s *Service) UserState(c context.Context, mid int64, ip, ak, ck string) (data *elecMdl.UserState, err error) {
data, err = s.elec.UserState(c, mid, ip)
return
}
// ArchiveState get arc elec state.
func (s *Service) ArchiveState(c context.Context, aid, mid int64, ip string) (data *elecMdl.ArcState, err error) {
data, err = s.elec.ArchiveState(c, aid, mid, ip)
return
}
// CheckIsFriend check paymid state.
func (s *Service) CheckIsFriend(c context.Context, data []*elecMdl.Rank, mid int64, ip string) (res []*elecMdl.Rank, err error) {
var mids []int64
for _, v := range data {
mids = append(mids, v.PayMID)
}
richRel, err := s.acc.RichRelation(c, mid, mids, ip)
if err != nil {
log.Error("s.acc.RichRelation error(%d, %v)", mid, err)
return
}
if len(richRel) > 0 {
for _, v := range data {
if richRel[v.PayMID] == 3 || richRel[v.PayMID] == 4 {
v.IsFriend = true
} else {
v.IsFriend = false
}
}
}
res = data
return
}

View File

@@ -0,0 +1,84 @@
package elec
import (
"context"
"flag"
"go-common/app/interface/main/creative/conf"
"path/filepath"
"testing"
"time"
. "github.com/smartystreets/goconvey/convey"
"go-common/app/interface/main/creative/service"
)
var (
s *Service
)
func init() {
dir, _ := filepath.Abs("../../cmd/creative.toml")
flag.Set("conf", dir)
conf.Init()
rpcdaos := service.NewRPCDaos(conf.Conf)
s = New(conf.Conf, rpcdaos)
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
Reset(func() {})
f(s)
}
}
func Test_State(t *testing.T) {
var (
c = context.TODO()
mid = int64(2089809)
)
Convey("ArchiveState", t, WithService(func(s *Service) {
_, err := s.ArchiveState(c, 2333, mid, "")
So(err, ShouldBeNil)
}))
Convey("UserState", t, WithService(func(s *Service) {
_, err := s.UserState(c, mid, "", "", "")
So(err, ShouldBeNil)
}))
Convey("UserInfo", t, WithService(func(s *Service) {
_, err := s.UserInfo(c, mid, "")
So(err, ShouldBeNil)
}))
Convey("Notify", t, WithService(func(s *Service) {
_, err := s.Notify(c, "")
So(err, ShouldBeNil)
}))
Convey("Status", t, WithService(func(s *Service) {
_, err := s.Status(c, mid, "")
So(err, ShouldBeNil)
}))
Convey("UpStatus", t, WithService(func(s *Service) {
err := s.UpStatus(c, mid, 1, "")
So(err, ShouldBeNil)
}))
Convey("RecentRank", t, WithService(func(s *Service) {
_, err := s.RecentRank(c, mid, 10, "")
So(err, ShouldBeNil)
}))
Convey("CurrentRank", t, WithService(func(s *Service) {
_, err := s.CurrentRank(c, mid, "")
So(err, ShouldBeNil)
}))
Convey("TotalRank", t, WithService(func(s *Service) {
_, err := s.TotalRank(c, mid, "")
So(err, ShouldBeNil)
}))
Convey("Balance", t, WithService(func(s *Service) {
_, err := s.Balance(c, mid, "")
So(err, ShouldBeNil)
}))
Convey("RemarkDetail", t, WithService(func(s *Service) {
_, err := s.RemarkDetail(c, mid, 233, "")
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,51 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/faq:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["service.go"],
importpath = "go-common/app/interface/main/creative/service/faq",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/dao/faq:go_default_library",
"//app/interface/main/creative/model/faq:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//library/log:go_default_library",
"//library/sync/pipeline/fanout:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,68 @@
package faq
import (
"context"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/dao/faq"
faqMdl "go-common/app/interface/main/creative/model/faq"
"go-common/app/interface/main/creative/service"
"go-common/library/log"
"go-common/library/sync/pipeline/fanout"
)
//Service struct
type Service struct {
c *conf.Config
faq *faq.Dao
cache *fanout.Fanout
}
//New get service
func New(c *conf.Config, rpcdaos *service.RPCDaos) *Service {
s := &Service{
c: c,
faq: faq.New(c),
cache: fanout.New("faq-service"),
}
return s
}
// Pre fn
func (s *Service) Pre(c context.Context) (res map[string]*faqMdl.Faq) {
res = make(map[string]*faqMdl.Faq)
var (
total int
err error
resD []*faqMdl.Detail
)
res["app_edit_faq"] = &faqMdl.Faq{
State: false,
QuestionTypeID: faqMdl.PhoneFaqQuesTypeID,
QuestionTypeName: faqMdl.PhoneFaqName,
URL: s.c.H5Page.FAQVideoEditor,
}
if resD, total, err = s.faq.DetailCache(c, faqMdl.PhoneFaqQuesTypeID, 1, 1, 2); err != nil || len(resD) == 0 {
if _, total, err = s.faq.Detail(context.Background(), faqMdl.PhoneFaqQuesTypeID, 1, 1, 2); err != nil {
log.Error("s.faq.Detail(%s,%d,%d,%d) error(%v)", faqMdl.PhoneFaqQuesTypeID, 1, 1, 2, err)
}
}
if total > 0 {
res["app_edit_faq"].State = true
}
return
}
// Detail fn
func (s *Service) Detail(c context.Context, qTypeID string, keyFlag, pn, ps int) (resD []*faqMdl.Detail, total int, err error) {
if resD, total, err = s.faq.DetailCache(c, qTypeID, keyFlag, pn, ps); err != nil || len(resD) == 0 {
if resD, total, err = s.faq.Detail(context.Background(), qTypeID, keyFlag, pn, ps); err != nil {
log.Error("s.faq.Detail(%s,%d,%d,%d) error(%v)", qTypeID, keyFlag, pn, ps, err)
}
if len(resD) > 0 {
s.cache.Do(c, func(c context.Context) {
s.faq.SetDetailCache(context.Background(), qTypeID, keyFlag, pn, ps, total, resD)
})
}
}
return
}

View File

@@ -0,0 +1,45 @@
package faq
import (
"context"
"flag"
"go-common/app/interface/main/creative/conf"
faqMdl "go-common/app/interface/main/creative/model/faq"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/creative/service"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func init() {
dir, _ := filepath.Abs("../../cmd/creative.toml")
flag.Set("conf", dir)
conf.Init()
rpcdaos := service.NewRPCDaos(conf.Conf)
s = New(conf.Conf, rpcdaos)
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
Reset(func() {})
f(s)
}
}
func Test_Pre(t *testing.T) {
var (
c = context.TODO()
res map[string]*faqMdl.Faq
)
Convey("Pre", t, WithService(func(s *Service) {
res = s.Pre(c)
So(res, ShouldNotBeNil)
}))
}

View File

@@ -0,0 +1,48 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["service.go"],
importpath = "go-common/app/interface/main/creative/service/feedback",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/dao/feedback:go_default_library",
"//app/interface/main/creative/model/feedback:go_default_library",
"//app/interface/main/creative/service:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,73 @@
package feedback
import (
"context"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/dao/feedback"
fdMdl "go-common/app/interface/main/creative/model/feedback"
"go-common/app/interface/main/creative/service"
)
//Service struct.
type Service struct {
c *conf.Config
feedback *feedback.Dao
}
//New get service.
func New(c *conf.Config, rpcdaos *service.RPCDaos) *Service {
s := &Service{
c: c,
feedback: feedback.New(c),
}
return s
}
// Feedbacks get user feedback list.
func (s *Service) Feedbacks(c context.Context, mid, ps, pn, tagID int64, state, start, end, platform, ip string) (data []*fdMdl.Feedback, count int64, err error) {
data, count, err = s.feedback.Feedbacks(c, mid, ps, pn, tagID, state, start, end, platform, ip)
return
}
// AddFeedback add feedback
func (s *Service) AddFeedback(c context.Context, mid, tagID, sessionID int64, qq, content, aid, imgURL, browser, platform, ip string) (err error) {
err = s.feedback.AddFeedback(c, mid, tagID, sessionID, qq, content, aid, browser, imgURL, platform, ip)
return
}
// Tags get tags.
func (s *Service) Tags(c context.Context, mid int64, ip string) (tags []*fdMdl.Tag, err error) {
var tls *fdMdl.TagList
if tls, err = s.feedback.Tags(c, mid, ip); err != nil {
return
}
if tls == nil || len(tls.Platforms) == 0 {
return
}
for _, v := range tls.Platforms {
if v.EN == "ugc" {
tags = v.Tags
}
}
return
}
// NewTags get new tags.
func (s *Service) NewTags(c context.Context, mid int64, ip string) (tags *fdMdl.TagList, err error) {
tags, err = s.feedback.Tags(c, mid, ip)
return
}
// Detail get feedback detail
func (s *Service) Detail(c context.Context, mid, sessionID int64, ip string) (data []*fdMdl.Reply, err error) {
data, err = s.feedback.Detail(c, mid, sessionID, ip)
return
}
// CloseSession get feedback detail
func (s *Service) CloseSession(c context.Context, sessionID int64, ip string) (err error) {
err = s.feedback.CloseSession(c, sessionID, ip)
return
}

View File

@@ -0,0 +1,53 @@
package feedback
import (
"context"
"flag"
"go-common/app/interface/main/creative/conf"
"path/filepath"
"testing"
"time"
. "github.com/smartystreets/goconvey/convey"
"go-common/app/interface/main/creative/service"
)
var (
s *Service
)
func init() {
dir, _ := filepath.Abs("../../cmd/creative.toml")
flag.Set("conf", dir)
conf.Init()
rpcdaos := service.NewRPCDaos(conf.Conf)
s = New(conf.Conf, rpcdaos)
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
Reset(func() {})
f(s)
}
}
func Test_State(t *testing.T) {
var (
c = context.TODO()
mid = int64(2089809)
)
Convey("AppealList", t, WithService(func(s *Service) {
_, err := s.Tags(c, mid, "")
So(err, ShouldNotBeNil)
}))
Convey("Detail", t, WithService(func(s *Service) {
_, err := s.Detail(c, mid, 23333, "")
So(err, ShouldNotBeNil)
}))
Convey("Feedbacks", t, WithService(func(s *Service) {
_, count, err := s.Feedbacks(c, mid, 10, 10, int64(2), "1", "2", "3", "pc", "")
So(err, ShouldNotBeNil)
So(count, ShouldBeZeroValue)
}))
}

View File

@@ -0,0 +1,52 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/geetest:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["service.go"],
importpath = "go-common/app/interface/main/creative/service/geetest",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/dao/account:go_default_library",
"//app/interface/main/creative/dao/geetest:go_default_library",
"//app/interface/main/creative/model/geetest:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//library/log:go_default_library",
"//library/stat/prom:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,127 @@
package geetest
import (
"context"
"crypto/md5"
"encoding/hex"
"math/rand"
"strconv"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/dao/account"
d "go-common/app/interface/main/creative/dao/geetest"
m "go-common/app/interface/main/creative/model/geetest"
"go-common/app/interface/main/creative/service"
"go-common/library/log"
"go-common/library/stat/prom"
)
//Service struct.
type Service struct {
c *conf.Config
gt *d.Dao
acc *account.Dao
pErr *prom.Prom
}
//New get service.
func New(c *conf.Config, rpcdaos *service.RPCDaos) *Service {
s := &Service{
c: c,
gt: d.New(c),
acc: rpcdaos.Acc,
pErr: prom.BusinessErrCount,
}
return s
}
// PreProcessAdd fn
func (s *Service) PreProcessAdd(c context.Context, mid int64, ip, clientType string, newCaptcha int) (res *m.ProcessRes, err error) {
var pre string
res = &m.ProcessRes{
Limit: map[string]bool{
"add": false,
},
}
if exist, _, _ := s.acc.HalfMin(c, mid); exist {
log.Info("halfMin exist | mid(%d)", mid)
res.Limit["add"] = true
}
if res.Limit["add"] {
res.CaptchaID = s.c.Geetest.CaptchaID
res.NewCaptcha = newCaptcha
if pre, err = s.gt.PreProcess(c, mid, ip, clientType, newCaptcha); err != nil || pre == "" {
randOne := md5.Sum([]byte(strconv.Itoa(rand.Intn(100))))
randTwo := md5.Sum([]byte(strconv.Itoa(rand.Intn(100))))
challenge := hex.EncodeToString(randOne[:]) + hex.EncodeToString(randTwo[:])[0:2]
res.Challenge = challenge
log.Info("s.gt.PreProcess err != nil (%s,%d,%d) ", clientType, newCaptcha, mid)
s.pErr.Incr("geetest_preprocess")
res.Success = 0
err = nil
return
}
res.Success = 1
slice := md5.Sum([]byte(pre + s.c.Geetest.PrivateKEY))
res.Challenge = hex.EncodeToString(slice[:])
}
return
}
// PreProcess getGeetestChal
func (s *Service) PreProcess(c context.Context, mid int64, ip, clientType string, newCaptcha int) (res *m.ProcessRes, err error) {
var pre string
res = &m.ProcessRes{
Limit: map[string]bool{
"add": false,
},
}
if exist, _, _ := s.acc.HalfMin(c, mid); exist {
log.Info("halfMin exist | mid(%d)", mid)
res.Limit["add"] = true
}
res.CaptchaID = s.c.Geetest.CaptchaID
res.NewCaptcha = newCaptcha
if pre, err = s.gt.PreProcess(c, mid, ip, clientType, newCaptcha); err != nil || pre == "" {
randOne := md5.Sum([]byte(strconv.Itoa(rand.Intn(100))))
randTwo := md5.Sum([]byte(strconv.Itoa(rand.Intn(100))))
challenge := hex.EncodeToString(randOne[:]) + hex.EncodeToString(randTwo[:])[0:2]
res.Challenge = challenge
log.Info("s.gt.PreProcess err != nil (%s,%d,%d) ", clientType, newCaptcha, mid)
s.pErr.Incr("geetest_preprocess")
res.Success = 0
err = nil
return
}
res.Success = 1
slice := md5.Sum([]byte(pre + s.c.Geetest.PrivateKEY))
res.Challenge = hex.EncodeToString(slice[:])
return
}
// Validate recheck the seccode
func (s *Service) Validate(c context.Context, challenge, validate, seccode, clientType, ip string, success int, mid int64) (stat bool) {
if len(validate) != 32 {
log.Error("s.Validate(%s,%s,%s,%d) err(validate not eq 32byte)", challenge, validate, seccode, mid)
return
}
if success != 1 {
slice := md5.Sum([]byte(challenge))
stat = hex.EncodeToString(slice[:]) == validate
return
}
slice := md5.Sum([]byte(s.c.Geetest.PrivateKEY + "geetest" + challenge))
if hex.EncodeToString(slice[:]) != validate {
log.Error("s.Validate(%s,%s,%s,%d) err(challenge not found)", challenge)
return
}
res, err := s.gt.Validate(c, challenge, seccode, clientType, ip, s.c.Geetest.CaptchaID, mid)
if err != nil {
s.pErr.Incr("geetest_validate")
log.Error("s.Validate(%s,%s,%s,%d) err(gtServer validate failed.)", challenge, validate, seccode, mid)
return
}
slice = md5.Sum([]byte(seccode))
stat = hex.EncodeToString(slice[:]) == res.Seccode
return
}

View File

@@ -0,0 +1,51 @@
package geetest
import (
"context"
"flag"
"go-common/app/interface/main/creative/conf"
m "go-common/app/interface/main/creative/model/geetest"
"path/filepath"
"testing"
"time"
. "github.com/smartystreets/goconvey/convey"
"go-common/app/interface/main/creative/service"
)
var (
s *Service
)
func init() {
dir, _ := filepath.Abs("../../cmd/creative.toml")
flag.Set("conf", dir)
conf.Init()
rpcdaos := service.NewRPCDaos(conf.Conf)
s = New(conf.Conf, rpcdaos)
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
Reset(func() {})
f(s)
}
}
func Test_PreProcess(t *testing.T) {
var (
c = context.TODO()
err error
res *m.ProcessRes
mid = int64(2089809)
ip = "127.0.0.1"
clientType = "clientType"
newCaptcha = 1
)
Convey("PreProcess", t, WithService(func(s *Service) {
res, err = s.PreProcess(c, mid, ip, clientType, newCaptcha)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
}))
}

View File

@@ -0,0 +1,53 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/growup:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"growup.go",
"service.go",
],
importpath = "go-common/app/interface/main/creative/service/growup",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/dao/archive:go_default_library",
"//app/interface/main/creative/dao/growup:go_default_library",
"//app/interface/main/creative/model/growup:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,128 @@
package growup
import (
"context"
"go-common/app/interface/main/creative/model/growup"
"go-common/library/log"
"time"
)
// UpStatus get up status. 前提:必须当前用户线上有可以观看的视频(0/-6) TODO deprecated
func (s *Service) UpStatus(c context.Context, mid int64, ip string) (us *growup.UpStatus, err error) {
if us, err = s.growup.UpStatus(c, mid, ip); err != nil {
log.Error("s.growup.UpStatus(%d) error(%v)", mid, err)
return
}
return
}
// UpInfo get up info.
func (s *Service) UpInfo(c context.Context, mid int64, ip string) (ui *growup.UpInfo, err error) {
if ui, err = s.growup.UpInfo(c, mid, ip); err != nil {
log.Error("s.growup.UpInfo(%d) error(%v)", mid, err)
}
return
}
// Join join growup.
func (s *Service) Join(c context.Context, mid int64, accTy, signTy int, ip string) (err error) {
if err = s.growup.Join(c, mid, accTy, signTy, ip); err != nil {
log.Error("s.growup.Join(%d) error(%v)", mid, err)
}
return
}
// Quit quit growup.
func (s *Service) Quit(c context.Context, mid int64, ip string) (err error) {
if err = s.growup.Quit(c, mid, ip); err != nil {
log.Error("s.growup.Quit(%d) error(%v)", mid, err)
}
return
}
// Summary get up status.
func (s *Service) Summary(c context.Context, mid int64, ip string) (us *growup.Summary, err error) {
if us, err = s.growup.Summary(c, mid, ip); err != nil {
log.Error("s.growup.Summary(%d) error(%v)", mid, err)
}
return
}
// Stat get up info.
func (s *Service) Stat(c context.Context, mid int64, ip string) (ui *growup.Stat, err error) {
if ui, err = s.growup.Stat(c, mid, ip); err != nil {
log.Error("s.growup.Stat(%d) error(%v)", mid, err)
}
if ui == nil || len(ui.Tops) == 0 {
log.Error("s.growup.Stat mid(%d) data(%v)", mid, ui)
return
}
dt := time.Now().AddDate(0, 0, -2)
year := dt.Format("2006")
month := dt.Format("01")
ui.Desc = "收入数据统计日期:" + year + "年" + month + "月"
aids := make([]int64, 0, len(ui.Tops))
for _, v := range ui.Tops {
if v != nil {
aids = append(aids, v.AID)
}
}
avm, err := s.p.BatchArchives(c, mid, aids, ip)
if err != nil {
log.Error("s.p.BatchArchives aids (%v), ip(%s) err(%v)", aids, ip, err)
return
}
if len(avm) == 0 {
return
}
for _, v := range ui.Tops {
if v != nil {
if av, ok := avm[v.AID]; ok {
v.Title = av.Archive.Title
}
}
}
return
}
// IncomeList get up status.
func (s *Service) IncomeList(c context.Context, mid int64, ty, pn, ps int, ip string) (l *growup.IncomeList, err error) {
if l, err = s.growup.IncomeList(c, mid, ty, pn, ps, ip); err != nil {
log.Error("s.growup.IncomeList(%d) error(%v)", mid, err)
return
}
if l == nil || len(l.Data) == 0 {
log.Error("s.growup.IncomeList mid(%d) type(%d) data(%v)", mid, ty, l)
return
}
aids := make([]int64, 0, len(l.Data))
for _, v := range l.Data {
if v != nil {
aids = append(aids, v.AID)
}
}
avm, err := s.p.BatchArchives(c, mid, aids, ip)
if err != nil {
log.Error("s.p.BatchArchives aids (%v), ip(%s) err(%v)", aids, ip, err)
return
}
if len(avm) == 0 {
return
}
for _, v := range l.Data {
if v != nil {
if av, ok := avm[v.AID]; ok {
v.Title = av.Archive.Title
}
}
}
return
}
// BreachList get up info.
func (s *Service) BreachList(c context.Context, mid int64, pn, ps int, ip string) (ui *growup.BreachList, err error) {
if ui, err = s.growup.BreachList(c, mid, pn, ps, ip); err != nil {
log.Error("s.growup.BreachList(%d) error(%v)", mid, err)
}
return
}

View File

@@ -0,0 +1,27 @@
package growup
import (
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/dao/archive"
"go-common/app/interface/main/creative/dao/growup"
"go-common/app/interface/main/creative/service"
)
//Service struct.
type Service struct {
c *conf.Config
arc *archive.Dao
growup *growup.Dao
p *service.Public
}
//New get service.
func New(c *conf.Config, rpcdaos *service.RPCDaos, p *service.Public) *Service {
s := &Service{
c: c,
arc: rpcdaos.Arc,
growup: growup.New(c),
p: p,
}
return s
}

View File

@@ -0,0 +1,52 @@
package growup
import (
"context"
"flag"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/model/growup"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/creative/service"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
p *service.Public
)
func init() {
dir, _ := filepath.Abs("../../cmd/creative.toml")
flag.Set("conf", dir)
conf.Init()
rpcdaos := service.NewRPCDaos(conf.Conf)
p = service.New(conf.Conf, rpcdaos)
s = New(conf.Conf, rpcdaos, p)
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
Reset(func() {})
f(s)
}
}
func Test_UpInfo(t *testing.T) {
var (
c = context.TODO()
err error
res *growup.UpInfo
MID = int64(27515256)
localHost = "127.0.0.1"
)
Convey("UpInfo", t, WithService(func(s *Service) {
res, err = s.UpInfo(c, MID, localHost)
So(err, ShouldNotBeNil)
So(res, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,51 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/medal:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["service.go"],
importpath = "go-common/app/interface/main/creative/service/medal",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/dao/medal:go_default_library",
"//app/interface/main/creative/model/medal:go_default_library",
"//app/interface/main/creative/model/newcomer:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,70 @@
package medal
import (
"context"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/dao/medal"
mdMdl "go-common/app/interface/main/creative/model/medal"
"go-common/app/interface/main/creative/model/newcomer"
"go-common/app/interface/main/creative/service"
"go-common/library/log"
)
//Service struct
type Service struct {
c *conf.Config
medal *medal.Dao
//task
p *service.Public
}
//New get service
func New(c *conf.Config, rpcdaos *service.RPCDaos, p *service.Public) *Service {
s := &Service{
c: c,
medal: medal.New(c),
p: p,
}
return s
}
// Medal get medal.
func (s *Service) Medal(c context.Context, mid int64) (t *mdMdl.Medal, err error) {
t, err = s.medal.Medal(c, mid)
return
}
// OpenMedal open medal.
func (s *Service) OpenMedal(c context.Context, mid int64, name string) (err error) {
if err = s.medal.OpenMedal(c, mid, name); err != nil {
log.Error("s.medal.OpenMedal mid(%d) error(%v)", mid, err)
return
}
s.p.TaskPub(mid, newcomer.MsgForOpenFansMedal, newcomer.MsgFinishedCount)
return
}
// RecentFans get recent fans.
func (s *Service) RecentFans(c context.Context, mid int64) (res []*mdMdl.RecentFans, err error) {
res, err = s.medal.RecentFans(c, mid)
return
}
// CheckMedal check medal name valid
func (s *Service) CheckMedal(c context.Context, mid int64, name string) (valid int, err error) {
valid, err = s.medal.CheckMedal(c, mid, name)
return
}
// Rank get fans rank list
func (s *Service) Rank(c context.Context, mid int64) (rank []*mdMdl.FansRank, err error) {
rank, err = s.medal.Rank(c, mid)
return
}
// Rename rename medal name
func (s *Service) Rename(c context.Context, mid int64, name, ak, ck string) (err error) {
err = s.medal.Rename(c, mid, name, ak, ck)
return
}

View File

@@ -0,0 +1,56 @@
package medal
import (
"context"
"flag"
"go-common/app/interface/main/creative/conf"
mdMdl "go-common/app/interface/main/creative/model/medal"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/creative/service"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
p *service.Public
)
func init() {
dir, _ := filepath.Abs("../../cmd/creative.toml")
flag.Set("conf", dir)
conf.Init()
rpcdaos := service.NewRPCDaos(conf.Conf)
p = service.New(conf.Conf, rpcdaos)
s = New(conf.Conf, rpcdaos, p)
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
Reset(func() {})
f(s)
}
}
func Test_Medal(t *testing.T) {
var (
mid int64 = 1
name = "name"
c = context.TODO()
err error
res *mdMdl.Medal
)
Convey("Medal", t, WithService(func(s *Service) {
res, err = s.Medal(c, mid)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
}))
Convey("OpenMedal", t, WithService(func(s *Service) {
err = s.OpenMedal(c, mid, name)
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,61 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["service.go"],
importpath = "go-common/app/interface/main/creative/service/music",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/dao/account:go_default_library",
"//app/interface/main/creative/dao/archive:go_default_library",
"//app/interface/main/creative/dao/material:go_default_library",
"//app/interface/main/creative/dao/music:go_default_library",
"//app/interface/main/creative/dao/up:go_default_library",
"//app/interface/main/creative/model/app:go_default_library",
"//app/interface/main/creative/model/music:go_default_library",
"//app/interface/main/creative/model/search:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//app/service/main/account/model:go_default_library",
"//app/service/main/archive/api:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/metadata:go_default_library",
"//library/queue/databus/report:go_default_library",
"//library/sync/errgroup:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,44 @@
package music
import (
"context"
"flag"
"go-common/app/interface/main/creative/conf"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/creative/service"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
p *service.Public
)
func init() {
dir, _ := filepath.Abs("../../cmd/creative.toml")
flag.Set("conf", dir)
conf.Init()
rpcdaos := service.NewRPCDaos(conf.Conf)
p = service.New(conf.Conf, rpcdaos)
s = New(conf.Conf, rpcdaos, p)
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
Reset(func() {})
f(s)
}
}
func Test_loadPreValues(t *testing.T) {
Convey("loadPreValues", t, WithService(func(s *Service) {
s.loadPreValues()
vals := s.BgmList(context.Background(), 1)
So(vals, ShouldNotBeNil)
}))
}

View File

@@ -0,0 +1,67 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/service:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"h5.go",
"service.go",
"state.go",
"task.go",
],
importpath = "go-common/app/interface/main/creative/service/newcomer",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/dao/academy:go_default_library",
"//app/interface/main/creative/dao/account:go_default_library",
"//app/interface/main/creative/dao/archive:go_default_library",
"//app/interface/main/creative/dao/article:go_default_library",
"//app/interface/main/creative/dao/data:go_default_library",
"//app/interface/main/creative/dao/medal:go_default_library",
"//app/interface/main/creative/dao/newcomer:go_default_library",
"//app/interface/main/creative/dao/order:go_default_library",
"//app/interface/main/creative/dao/watermark:go_default_library",
"//app/interface/main/creative/model/newcomer:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//app/service/main/account/api:go_default_library",
"//library/conf/env:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/metadata:go_default_library",
"//library/queue/databus/report:go_default_library",
"//library/sync/errgroup.v2:go_default_library",
"//library/time:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,152 @@
package newcomer
import (
"context"
"fmt"
"go-common/app/interface/main/creative/model/newcomer"
"go-common/library/ecode"
"go-common/library/log"
)
// H5TaskList for H5 detail task list
func (s *Service) H5TaskList(c context.Context, mid int64, from string) (res *newcomer.H5TaskRewardList, err error) {
var (
u *UserTaskInfo
tasks []*newcomer.Task
taskTypeMap = make(map[int8][]*newcomer.Task) // taskType-task
taskGroupMap = make(map[int64][]*newcomer.Task) // groupID-task
)
// get user tasks
userTasks, err := s.newc.UserTasks(c, mid)
if err != nil {
log.Error("TaskList s.newc.UserTasks mid(%d)|error(%v)", mid, err)
return
}
if len(userTasks) == 0 {
// returnUser did not receive the task
res = &newcomer.H5TaskRewardList{
TaskReceived: newcomer.NoBindTask,
}
return
}
// get user info
u, err = s.getUserTaskInfo(c, mid, userTasks)
if err != nil {
return
}
// get tasks
tasks = s.getTasksInfoByType(userTasks, newcomer.DefualtTaskType)
if len(tasks) == 0 {
err = ecode.CreativeNewcomerNoTask
log.Error("TaskList s.GetTaskByType len(tasks) == 0")
return
}
// group by groupID & taskType
taskGroupMap, taskTypeMap = s.groupByTasks(tasks)
// add task label & redirect
s.addLabelRedirect(tasks, from)
// task_gift
taskGift, err := s.getTaskGiftData(c, mid, taskTypeMap, newcomer.FromH5)
if err != nil {
return
}
// task_groups
tgs, err := s.getTaskGroupData(c, mid, taskGroupMap)
if err != nil {
return
}
// if userLevel == UserTaskLevel01 , set unlock state
if u.UserTaskLevel == newcomer.UserTaskLevel01 {
for _, v := range tgs {
if v.TaskType == newcomer.AdvancedTaskType {
v.RewardState = newcomer.RewardUnlock
}
}
}
// add tips
s.addTaskGroupTip(tgs)
s.addGiftTip(taskGift, taskTypeMap)
res = &newcomer.H5TaskRewardList{
TaskReceived: newcomer.BindTask,
TaskGroups: tgs,
TaskGift: taskGift,
}
return
}
// addLabelRedirect add label & redirect
func (s *Service) addLabelRedirect(tasks []*newcomer.Task, from string) {
if len(tasks) == 0 {
return
}
for _, v := range tasks {
if v == nil {
continue
}
t, ok := s.TaskMapCache[v.ID]
if !ok {
continue
}
m, ook := newcomer.H5RedirectMap[from][t.TargetType]
if !ook || len(m) == 0 {
continue
}
v.Label = m[0]
v.Redirect = m[1]
}
}
// addGiftTip get gift tip
func (s *Service) addGiftTip(tg []*newcomer.TaskGift, kindMap map[int8][]*newcomer.Task) {
for _, v := range tg {
if v == nil {
continue
}
if v.State != newcomer.RewardUnlock {
if tip, ok := newcomer.GiftTipMap[v.State][v.Type]; ok {
v.Tip = tip
} else {
v.Tip = ""
}
continue
}
// 判断还需要完成奖几个任务
if len(kindMap[v.Type]) == 0 {
v.Tip = ""
continue
}
unfinished := 0
for _, v := range kindMap[v.Type] {
if v == nil {
continue
}
if v.CompleteSate == newcomer.TaskIncomplete {
unfinished++
}
}
v.Tip = fmt.Sprintf("再完成%d个任务就能领取了呢", unfinished)
}
}
// addTaskGroupTip get taskGroup tip
func (s *Service) addTaskGroupTip(tr []*newcomer.TaskRewardGroup) {
for _, v := range tr {
if v == nil {
continue
}
if tip, ok := newcomer.TaskGroupTipMap[v.RewardState][v.GroupID]; ok {
v.Tip = tip
} else {
v.Tip = ""
}
}
}

View File

@@ -0,0 +1,440 @@
package newcomer
import (
"context"
"time"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/dao/academy"
"go-common/app/interface/main/creative/dao/account"
"go-common/app/interface/main/creative/dao/archive"
"go-common/app/interface/main/creative/dao/article"
"go-common/app/interface/main/creative/dao/data"
"go-common/app/interface/main/creative/dao/medal"
"go-common/app/interface/main/creative/dao/newcomer"
"go-common/app/interface/main/creative/dao/order"
"go-common/app/interface/main/creative/dao/watermark"
ncMDL "go-common/app/interface/main/creative/model/newcomer"
"go-common/app/interface/main/creative/service"
"go-common/library/conf/env"
"go-common/library/log"
"go-common/library/net/metadata"
"go-common/library/queue/databus/report"
"sync"
)
//Service struct
type Service struct {
c *conf.Config
newc *newcomer.Dao
arc *archive.Dao
art *article.Dao
acc *account.Dao
data *data.Dao
aca *academy.Dao
wm *watermark.Dao
medal *medal.Dao
order *order.Dao
//reward
RewardCache []*ncMDL.Reward
RewardMapCache map[int64]*ncMDL.Reward
RewardTyPIDMapCache map[int8]int64 //存储奖励 类型-分类id对应关系
RewardPIDTyMapCache map[int64]int8 //存储奖励 分类id-类型对应关系
//task
TaskCache []*ncMDL.Task
TaskMapCache map[int64]*ncMDL.Task
TaskTypeMapCache map[int8][]*ncMDL.Task
TaskRewardMapCache map[int64][]*ncMDL.TaskRewardEntity
//taskgroup-reward
TaskGroupRewardMapCache map[int64][]*ncMDL.TaskGroupReward
//gift-reward
GiftRewardMapCache map[int8][]*ncMDL.GiftReward
//initiative check task
checkTaskChan chan int64
checkTaskQueue []int64
checkTaskDone chan struct{}
// task-group
TaskGroupCache []*ncMDL.TaskGroupEntity
TaskGroupMapCache map[int64]*ncMDL.TaskGroupEntity
}
//New get service
func New(c *conf.Config, rpcdaos *service.RPCDaos) *Service {
s := &Service{
c: c,
newc: newcomer.New(c),
arc: rpcdaos.Arc,
art: rpcdaos.Art,
acc: rpcdaos.Acc,
data: data.New(c),
aca: academy.New(c),
wm: watermark.New(c),
medal: medal.New(c),
order: order.New(c),
checkTaskChan: make(chan int64, 1000),
checkTaskQueue: make([]int64, 0, 1000),
checkTaskDone: make(chan struct{}),
}
s.loadRewards()
s.loadTasks()
s.loadTaskGroupRewards()
s.loadGiftRewards()
s.loadTaskRewards()
s.loadTaskGroups()
go s.loadProc()
go s.checkTaskStateByMid()
return s
}
// Ping service
func (s *Service) Ping(c context.Context) (err error) {
if err = s.newc.Ping(c); err != nil {
log.Error("s.newc.Ping err(%v)", err)
}
return
}
// Close dao
func (s *Service) Close() {
s.newc.Close()
s.checkTaskDone <- struct{}{}
}
// loadproc
func (s *Service) loadProc() {
for {
time.Sleep(3 * time.Minute)
s.loadRewards()
s.loadTasks()
s.loadTaskGroupRewards()
s.loadGiftRewards()
s.loadTaskRewards()
s.loadTaskGroups()
}
}
//load tags
func (s *Service) loadRewards() {
res, err := s.newc.Rewards(context.Background())
if err != nil {
log.Error("s.newc.Rewards error(%v)", err)
return
}
if len(res) == 0 {
return
}
s.RewardCache = res
tempRewardMapCache := make(map[int64]*ncMDL.Reward)
tempRewardTyPIDMapCache := make(map[int8]int64)
tempRewardPIDTyMapCache := make(map[int64]int8)
for _, v := range res {
tempRewardMapCache[v.ID] = v
if v.ParentID == 0 {
tempRewardTyPIDMapCache[v.Type] = v.ID
tempRewardPIDTyMapCache[v.ID] = v.Type
}
}
s.RewardMapCache = tempRewardMapCache
s.RewardTyPIDMapCache = tempRewardTyPIDMapCache
s.RewardPIDTyMapCache = tempRewardPIDTyMapCache
}
//load tags
func (s *Service) loadTasks() {
res, err := s.newc.Tasks(context.Background())
if err != nil {
log.Error("s.newc.Tasks error(%v)", err)
return
}
if len(res) == 0 {
return
}
s.TaskCache = res
temp := make(map[int64]*ncMDL.Task)
tempMap := make(map[int8][]*ncMDL.Task)
for _, v := range res {
temp[v.ID] = v
switch v.Type {
case ncMDL.NewcomerTaskType:
tempMap[ncMDL.NewcomerTaskType] = append(tempMap[ncMDL.NewcomerTaskType], v)
case ncMDL.AdvancedTaskType:
tempMap[ncMDL.AdvancedTaskType] = append(tempMap[ncMDL.AdvancedTaskType], v)
case ncMDL.MonthTaskType:
tempMap[ncMDL.MonthTaskType] = append(tempMap[ncMDL.MonthTaskType], v)
}
}
s.TaskMapCache = temp
// 默认分类包含:新手与进阶任务
tempMap[ncMDL.DefualtTaskType] = append(tempMap[ncMDL.DefualtTaskType], tempMap[ncMDL.NewcomerTaskType]...)
tempMap[ncMDL.DefualtTaskType] = append(tempMap[ncMDL.DefualtTaskType], tempMap[ncMDL.AdvancedTaskType]...)
s.TaskTypeMapCache = tempMap
}
// SendRewardReceiveLog for reward receive.
func (s *Service) SendRewardReceiveLog(c context.Context, mid int64) (err error) {
if env.DeployEnv == env.DeployEnvDev {
return
}
uInfo := &report.UserInfo{
Business: 141, //创作中心奖励领取行为日志业务ID
Mid: mid,
Type: 0, //0-激励计划奖品领取
Oid: mid,
Platform: "激励计划",
Ctime: time.Now(),
Action: "incentive_plan_reward_receive", //激励计划奖品领取
Index: []interface{}{mid},
IP: metadata.String(c, metadata.RemoteIP),
}
report.User(uInfo)
log.Info("s.SendRewardReceiveLog mid(%d)|uInfo(%+v)", mid, uInfo)
return
}
// SendPendantReceiveLog for reward receive.
func (s *Service) SendPendantReceiveLog(c context.Context, mid int64) (err error) {
if env.DeployEnv == env.DeployEnvDev {
return
}
uInfo := &report.UserInfo{
Business: 141, //创作中心奖励领取行为日志业务ID
Mid: mid,
Type: 1, //1-头像挂件奖品领取
Oid: mid,
Platform: "头像挂件",
Ctime: time.Now(),
Action: "pendant_reward_receive", //头像挂件奖品领取
Index: []interface{}{mid},
IP: metadata.String(c, metadata.RemoteIP),
}
report.User(uInfo)
log.Info("s.SendPendantReceiveLog mid(%d)|uInfo(%+v)", mid, uInfo)
return
}
//load gift-reward
func (s *Service) loadGiftRewards() {
res, err := s.newc.AllGiftRewards(context.Background())
if err != nil {
log.Error("s.newc.AllGiftRewards error(%v)", err)
return
}
if len(res) == 0 {
return
}
s.GiftRewardMapCache = res
}
//load taskgroup-reward
func (s *Service) loadTaskGroupRewards() {
res, err := s.newc.AllTaskGroupRewards(context.Background())
if err != nil {
log.Error("s.newc.AllTaskGroupRewards error(%v)", err)
return
}
if len(res) == 0 {
return
}
s.TaskGroupRewardMapCache = res
}
// checkTaskStateByMid read bindMid to check task state
func (s *Service) checkTaskStateByMid() {
ticker := time.NewTicker(time.Millisecond * 100)
defer ticker.Stop()
for {
select {
case id := <-s.checkTaskChan:
s.checkTaskQueue = append(s.checkTaskQueue, id)
case <-ticker.C:
if len(s.checkTaskQueue) > 0 {
mid := s.checkTaskQueue[0]
s.checkTaskQueue = s.checkTaskQueue[1:]
s.DriveStateByUser(context.Background(), mid)
}
case <-s.checkTaskDone:
log.Info("checkTaskStateByMid close")
return
}
}
}
// putCheckTask put mid to checkTaskQueue
func (s *Service) putCheckTaskState(mid int64) {
var wg sync.WaitGroup
wg.Add(1)
go func() {
s.checkTaskChan <- mid
wg.Done()
}()
wg.Wait()
}
//load task-group
func (s *Service) loadTaskGroups() {
res, err := s.newc.TaskGroups(context.Background())
if err != nil {
log.Error("s.newc.TaskGroups error(%v)", err)
return
}
if len(res) == 0 {
return
}
s.TaskGroupCache = res
temp := make(map[int64]*ncMDL.TaskGroupEntity)
for _, v := range res {
temp[v.ID] = v
}
s.TaskGroupMapCache = temp
}
//load task-group
func (s *Service) loadTaskRewards() {
res, err := s.newc.TaskRewards(context.Background())
if err != nil {
log.Error("s.newc.TaskRewards error(%v)", err)
return
}
if len(res) == 0 {
return
}
s.TaskRewardMapCache = res
}
// getRewardsByTaskType get rewards by taskType
func (s *Service) getRewardsByTaskType(taskType int8) (res []*ncMDL.Reward) {
res = make([]*ncMDL.Reward, 0)
gifts, ok := s.GiftRewardMapCache[taskType]
if !ok || len(gifts) == 0 {
return
}
for _, v := range gifts {
if v == nil {
continue
}
r, ok := s.RewardMapCache[v.RewardID]
if !ok {
continue
}
res = append(res, r)
}
return
}
// getRewardsByGroupID get reward by groupID
func (s *Service) getRewardsByGroupID(groupID int64) []*ncMDL.Reward {
rewards := make([]*ncMDL.Reward, 0)
rs, ok := s.TaskGroupRewardMapCache[groupID]
if !ok || len(rs) == 0 {
log.Error("getRewardsByGroupID reward not exist groupID(%d)", groupID)
return rewards
}
for _, r := range rs {
if r == nil {
continue
}
if rr, ok := s.RewardMapCache[r.RewardID]; ok {
rewards = append(rewards, rr)
}
}
return rewards
}
// getTaskByGroupID get tasks by groupID
func (s *Service) getTasksByGroupID(groupID int64) (res []*ncMDL.Task) {
res = make([]*ncMDL.Task, 0)
for _, task := range s.TaskCache {
if task == nil {
continue
}
if _, ok := s.TaskGroupMapCache[task.GroupID]; !ok {
continue
}
if task.GroupID == groupID && task.State == ncMDL.NormalState {
res = append(res, task)
}
}
return
}
// getTaskByType get tasks by type
func (s *Service) getTasksByType(ty int8) (res []*ncMDL.Task) {
res = make([]*ncMDL.Task, 0)
for _, task := range s.TaskCache {
if task == nil {
continue
}
if _, ok := s.TaskGroupMapCache[task.GroupID]; !ok {
continue
}
if task.Type == ty && task.State == ncMDL.NormalState {
res = append(res, task)
}
}
return
}
// getTasksInfo get tasks info by type
func (s *Service) getTasksInfoByType(ts []*ncMDL.Task, ty int8) (res []*ncMDL.Task) {
tsMap := make(map[int64]*ncMDL.Task)
for _, t := range ts {
if t == nil {
continue
}
tsMap[t.ID] = t
}
tasks, ok := s.TaskTypeMapCache[ty]
if !ok || len(tasks) == 0 {
return
}
res = make([]*ncMDL.Task, 0, len(tasks))
for _, v := range tasks {
if v == nil || v.State != 0 { //-1-删除0-正常1-隐藏
continue
}
if _, ok := s.TaskGroupMapCache[v.GroupID]; !ok { // check taskGroup
continue
}
task := *v
t, ok := tsMap[v.ID]
if !ok {
task.CompleteSate = ncMDL.TaskIncomplete
} else {
task.CompleteSate = t.CompleteSate
}
res = append(res, &task)
}
return
}
// isHiddenTaskType check taskType is hidden
func (s *Service) isHiddenTaskType(ty int8) bool {
tasks, ok := s.TaskTypeMapCache[ty]
if !ok || len(tasks) == 0 {
return true
}
for _, t := range tasks {
if t == nil {
continue
}
_, ok := s.TaskGroupMapCache[t.GroupID]
if !ok {
continue
}
if t.State == 0 {
return false
}
}
return true
}

View File

@@ -0,0 +1,26 @@
package newcomer
import (
"flag"
"os"
"testing"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/service"
)
var (
s *Service
)
func TestMain(m *testing.M) {
flag.Set("conf", "../../cmd/creative.toml")
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
rpcdaos := service.NewRPCDaos(conf.Conf)
s = New(conf.Conf, rpcdaos)
m.Run()
os.Exit(m.Run())
}

View File

@@ -0,0 +1,626 @@
package newcomer
import (
"context"
"strconv"
"time"
"go-common/app/interface/main/creative/model/newcomer"
"go-common/library/log"
"go-common/library/sync/errgroup.v2"
)
//DriveStateByUser drive new hand & advanced task state
func (s *Service) DriveStateByUser(c context.Context, mid int64) {
res, err := s.newc.UserTasksByMID(c, mid)
if err != nil {
log.Error("DriveStateByUser s.newc.UserTasksByMID mid(%d)|err(%v)", mid, err)
return
}
if len(res) == 0 {
return
}
for _, v := range res {
if s.CheckTaskState(context.Background(), &newcomer.CheckTaskStateReq{MID: v.MID, TaskID: v.TaskID}) {
_, err := s.newc.UpUserTask(c, v.MID, v.TaskID)
if err != nil {
log.Error("DriveStateByUser s.newc.UpUserTask mid(%d)|task id(%d)|err(%v)", v.MID, v.TaskID, err)
}
}
}
}
//CheckTaskState check task state by mid & task id
func (s *Service) CheckTaskState(c context.Context, req *newcomer.CheckTaskStateReq) (state bool) {
if req == nil {
return
}
mid, tid := req.MID, req.TaskID
if _, ok := s.TaskMapCache[tid]; !ok {
return
}
task := s.TaskMapCache[tid]
//log.Info("CheckTaskState req(%+v)|task(%+v)", req, task)
switch task.TargetType {
case newcomer.TargetType001, newcomer.TargetType014: //新手任务-1 该UID下开放浏览的稿件≥1 / 进阶任务- 14 该UID下开放浏览的稿件≥5
cnt, err := s.arc.UpCount(c, mid)
if err != nil {
log.Error("CheckTaskState s.arc.UpCount mid(%d)|error(%v)", mid, err)
return
}
if cnt >= task.TargetValue {
switch task.TargetType {
case newcomer.TargetType001:
log.Info("CheckTaskState TargetType001 mid(%d)|count(%d)|指标:新手任务-1 该UID下开放浏览的稿件≥1", mid, cnt)
case newcomer.TargetType014:
log.Info("CheckTaskState TargetType014 mid(%d)|count(%d)|指标:进阶任务- 14 该UID下开放浏览的稿件≥5", mid, cnt)
}
state = true
}
case newcomer.TargetType002: //该UID分享自己视频的次数≥1
case newcomer.TargetType003: //该UID在创作学院的观看记录≥1
cnt, err := s.aca.PlayCount(c, mid)
if err != nil {
log.Error("s.aca.PlayCount error(%v)", err)
return
}
if cnt >= task.TargetValue {
log.Info("CheckTaskState TargetType003 mid(%d)|count(%d)|指标:新手任务-1 该UID在创作学院的观看记录≥1", mid, cnt)
state = true
}
case newcomer.TargetType004, newcomer.TargetType005, newcomer.TargetType006, newcomer.TargetType007, newcomer.TargetType008, newcomer.TargetType009: //该UID下所有avid的获得评论数/...≥3/5
state = s.totalStat(c, mid, int64(task.TargetValue), task.TargetType)
case newcomer.TargetType010, newcomer.TargetType022: //新手任务- 10 获得10个粉丝 / 进阶任务- 22 该UID的粉丝数≥1000
pl, err := s.acc.ProfileWithStat(c, mid)
if err != nil {
log.Error("CheckTaskState s.acc.ProfileWithStat error(%v)", err)
return
}
if pl == nil {
return
}
if pl.Follower >= int64(task.TargetValue) {
switch task.TargetType {
case newcomer.TargetType010:
log.Info("CheckTaskState TargetType010 mid(%d)|follower(%d)|指标:新手任务-10 该UID的粉丝数≥10", mid, pl.Follower)
case newcomer.TargetType022:
log.Info("CheckTaskState TargetType022 mid(%d)|follower(%d)|指标:进阶任务-22 该UID的粉丝数≥1000", mid, pl.Follower)
}
state = true
}
case newcomer.TargetType011: //任务完成期间该UID的水印开关为打开状态
wm, err := s.wm.WaterMark(c, mid)
if err != nil {
log.Error("CheckTaskState s.wm.WaterMark mid(%d) error(%v)", mid, err)
return
}
if wm != nil && wm.State == 1 && wm.URL != "" {
log.Info("CheckTaskState TargetType011 mid(%d)已开启水印|指标:新手任务-11 任务完成期间该UID的水印开关为打开状态", mid)
state = true
}
case newcomer.TargetType012: //该UID的关注列表含有“哔哩哔哩创作中心”
fid := creatorMID //用户哔哩哔哩创作中心 mid
fl, err := s.acc.Relations(c, mid, []int64{fid}, "")
if err != nil {
log.Error("CheckTaskState s.acc.Relations mid(%d)|ip(%s)|error(%v)", mid, "", err)
return
}
if fl == nil {
return
}
if st, ok := fl[fid]; ok && (st == 6 || st == 2) {
log.Info("CheckTaskState TargetType012 mid(%d)已关注创作中心|指标:新手任务-12 该UID的关注列表含有“哔哩哔哩创作中心”", mid)
state = true
}
case newcomer.TargetType013, newcomer.TargetType015, newcomer.TargetType016, newcomer.TargetType017, newcomer.TargetType018, newcomer.TargetType019, newcomer.TargetType020, newcomer.TargetType021: //13-该UID通过手机投稿的稿件≥1 / 15-21单稿件获得1000播放...
state = s.singleStat(c, mid, int64(task.TargetValue), task.TargetType)
case newcomer.TargetType023: //该UID的激励计划状态为已开通
ac, err := s.order.GrowAccountState(c, mid, 0) //类型 0 视频 2 专栏 3 素材
if err != nil {
log.Error("CheckTaskState s.order.GrowUpPlan mid(%d) error(%v)", mid, err)
return
}
if ac == nil {
return
}
if ac.State == 3 { //账号状态; 1: 未申请; 2: 待审核; 3: 已签约; 4.已驳回; 5.主动退出; 6:被动退出; 7:封禁
log.Info("CheckTaskState TargetType023 mid(%d)已签约激励计划|指标:进阶任务-23 该UID的激励计划状态为已开通", mid)
state = true
}
case newcomer.TargetType024: //该UID粉丝勋章为开启状态
medal, err := s.medal.Medal(c, mid)
if err != nil {
log.Error("CheckTaskState s.medal.Medal mid(%d) error(%v)", mid, err)
return
}
if medal == nil {
return
}
status, err := strconv.Atoi(medal.Status)
if err != nil {
log.Error("CheckTaskState strconv.Atoi medal.Status(%s) error(%v)", medal.Status, err)
return
}
if status == 2 { //勋章审核状态 -1已拒绝 0未申请 1已申请 2已开通
log.Info("CheckTaskState TargetType024 mid(%d)已开通粉丝勋章|指标:进阶任务-24 该UID粉丝勋章为开启状态", mid)
state = true
}
}
return
}
func (s *Service) totalStat(c context.Context, mid, val int64, ty int8) (state bool) {
st, err := s.data.UpStat(c, mid, time.Now().AddDate(0, 0, -1).Add(-12*time.Hour).Format("20060102"))
if err != nil || st == nil {
log.Error("totalStat s.data.NewStat mid(%d) st(%+v) error(%v) ", mid, st, err)
return
}
switch ty {
case newcomer.TargetType004:
if st.Reply >= val {
log.Info("CheckTaskState TargetType004 mid(%d)|v(%+v)|指标:新手任务-4 该UID下所有avid的获得评论数≥3", mid, st.Reply)
state = true
}
case newcomer.TargetType005:
if st.Share >= val {
log.Info("CheckTaskState TargetType005 mid(%d)|v(%+v)|指标:新手任务-5 该UID下所有avid获得分享数≥3", mid, st.Share)
state = true
}
case newcomer.TargetType006:
if st.Fav >= val {
log.Info("CheckTaskState TargetType006 mid(%d)|v(%+v)|指标:新手任务-6 该UID的所有avid的获得收藏数≥5", mid, st.Fav)
state = true
}
case newcomer.TargetType007:
if st.Coin >= val {
log.Info("CheckTaskState TargetType007 mid(%d)|v(%+v)|指标:新手任务-7 该UID下所有avid的获得硬币数≥5", mid, st.Coin)
state = true
}
case newcomer.TargetType008:
if st.Like >= val {
log.Info("CheckTaskState TargetType008 mid(%d)|v(%+v)|指标:新手任务-8 该UID下所有avid获得点赞数≥5", mid, st.Like)
state = true
}
case newcomer.TargetType009:
if st.Dm >= val {
log.Info("CheckTaskState TargetType009 mid(%d)|v(%+v)|指标:新手任务-9 该UID下所有avid的获得弹幕数≥5", mid, st.Dm)
state = true
}
}
return
}
func (s *Service) singleStat(c context.Context, mid, val int64, ty int8) (state bool) {
st, err := s.data.UpArchiveStatQuery(c, mid, time.Now().AddDate(0, 0, -1).Add(-12*time.Hour).Format("20060102"))
if err != nil || st == nil {
log.Error("singleStat s.data.UpArchiveStatQuery mid(%d)|err(%v)", mid, err)
return
}
switch ty {
case newcomer.TargetType013:
if st.FromPhoneNum >= val {
log.Info("CheckTaskState TargetType013 mid(%d)|v(%+v)|指标:进阶任务-13 用手机投稿上传视频", mid, st.FromPhoneNum)
state = true
}
case newcomer.TargetType015:
if st.PlayV >= val {
log.Info("CheckTaskState TargetType015 mid(%d)|v(%+v)|指标:进阶任务-15 该UID下任意avid的获得点击量≥1000", mid, st.PlayV)
state = true
}
case newcomer.TargetType016:
if st.ReplyV >= val {
log.Info("CheckTaskState TargetType016 mid(%d)|v(%+v)|指标:进阶任务-16 该UID下任意avid的评论≥30", mid, st.ReplyV)
state = true
}
case newcomer.TargetType017:
if st.ShareV >= val {
log.Info("CheckTaskState TargetType017 mid(%d)|v(%+v)|指标:进阶任务-17 该UID下任意avid的获得分享数≥10", mid, st.ShareV)
state = true
}
case newcomer.TargetType018:
if st.FavV >= val {
log.Info("CheckTaskState TargetType018 mid(%d)|v(%+v)|指标:进阶任务-18 该UID下任意avid的获得收藏数≥30", mid, st.FavV)
state = true
}
case newcomer.TargetType019:
if st.CoinV >= val {
log.Info("CheckTaskState TargetType019 mid(%d)|v(%+v)|指标:进阶任务-19 该UID下任意avid的获得硬币数≥50", mid, st.CoinV)
state = true
}
case newcomer.TargetType020:
if st.LikeV >= val {
log.Info("CheckTaskState TargetType020 mid(%d)|v(%+v)|指标:进阶任务-20 该UID下任意avid的获得点赞数≥50", mid, st.LikeV)
state = true
}
case newcomer.TargetType021:
if st.DmV >= val {
log.Info("CheckTaskState TargetType021 mid(%d)|v(%+v)|指标:进阶任务-21 该UID下任意avid的获得弹幕数≥50", mid, st.DmV)
state = true
}
}
return
}
//syncCheckTaskStatus check task status
func (s *Service) syncCheckTaskStatus(c context.Context, mid int64, tasks []*newcomer.Task) {
log.Info("syncCheckTaskStatus mid(%d) | tasks count(%d)", mid, len(tasks))
tsm := getTaskSortMap(tasks)
if len(tsm) == 0 {
return
}
g := &errgroup.Group{}
for k := range tsm {
switch k {
case newcomer.ArcUpCount: //该UID下开放浏览的稿件数量
g.Go(func(context.Context) error {
s.arcUpCount(c, mid, tsm[newcomer.ArcUpCount])
return nil
})
case newcomer.AcaPlayCount: //该UID在创作学院的观看记录
g.Go(func(context.Context) error {
s.acaPlayCount(c, mid, tsm[newcomer.AcaPlayCount])
return nil
})
case newcomer.DataUpStat: //该UID下所有avid的最高计数
g.Go(func(context.Context) error {
s.dataUpStat(c, mid, tsm[newcomer.DataUpStat])
return nil
})
case newcomer.AccProfileWithStat: //粉丝数量
g.Go(func(context.Context) error {
s.accProfileWithStat(c, mid, tsm[newcomer.AccProfileWithStat])
return nil
})
case newcomer.WmWaterMark: //水印状态
g.Go(func(context.Context) error {
s.wmWaterMark(c, mid, tsm[newcomer.WmWaterMark])
return nil
})
case newcomer.AccRelation: //该UID的关注列表含有“哔哩哔哩创作中心”
g.Go(func(context.Context) error {
s.accRelation(c, mid, tsm[newcomer.AccRelation])
return nil
})
case newcomer.DataUpArchiveStat: //该UID下任意avid的计数
g.Go(func(context.Context) error {
s.dataUpArchiveStatQuery(c, mid, tsm[newcomer.DataUpArchiveStat])
return nil
})
case newcomer.OrderGrowAccountState: //激励计划状态
g.Go(func(context.Context) error {
s.orderGrowAccountState(c, mid, tsm[newcomer.OrderGrowAccountState])
return nil
})
case newcomer.MedalCheckMedal: //该UID粉丝勋章
g.Go(func(context.Context) error {
s.medalCheckMedal(c, mid, tsm[newcomer.MedalCheckMedal])
return nil
})
}
}
g.Wait()
}
func (s *Service) arcUpCount(c context.Context, mid int64, tasks []*newcomer.Task) {
if len(tasks) == 0 {
return
}
cnt, err := s.arc.UpCount(c, mid)
if err != nil {
log.Error("arcUpCount s.arc.UpCount mid(%d)|error(%v)", mid, err)
return
}
for _, v := range tasks {
if cnt >= v.TargetValue {
_, err := s.newc.UpUserTask(c, mid, v.ID)
if err != nil {
log.Error("arcUpCount s.newc.UpUserTask mid(%d)|task id(%d)|err(%v)", mid, v.ID, err)
}
log.Info("arcUpCount finish task mid(%d)|count(%d)|", mid, cnt)
}
}
}
func (s *Service) acaPlayCount(c context.Context, mid int64, tasks []*newcomer.Task) {
if len(tasks) == 0 {
return
}
cnt, err := s.aca.PlayCount(c, mid)
if err != nil {
log.Error("acaPlayCount s.aca.PlayCount error(%v)", err)
return
}
for _, v := range tasks {
if cnt >= v.TargetValue {
_, err := s.newc.UpUserTask(c, mid, v.ID)
if err != nil {
log.Error("acaPlayCount s.newc.UpUserTask mid(%d)|task id(%d)|err(%v)", mid, v.ID, err)
continue
}
log.Info("acaPlayCount finish task mid(%d)|count(%d)|", mid, cnt)
}
}
}
func (s *Service) dataUpStat(c context.Context, mid int64, tasks []*newcomer.Task) {
if len(tasks) == 0 {
return
}
st, err := s.data.UpStat(c, mid, time.Now().AddDate(0, 0, -1).Add(-12*time.Hour).Format("20060102"))
if err != nil || st == nil {
log.Error("dataUpStat s.data.NewStat mid(%d) st(%+v) error(%v) ", mid, st, err)
return
}
for _, v := range tasks {
val := int64(v.TargetValue)
state := false
switch v.TargetType {
case newcomer.TargetType004:
if st.Reply >= val {
state = true
}
log.Info("dataUpStat TargetType004 mid(%d)|v(%+v)|", mid, st.Reply)
case newcomer.TargetType005:
if st.Share >= val {
state = true
}
log.Info("dataUpStat TargetType005 mid(%d)|v(%+v)|", mid, st.Share)
case newcomer.TargetType006:
if st.Fav >= val {
state = true
}
log.Info("dataUpStat TargetType006 mid(%d)|v(%+v)|", mid, st.Fav)
case newcomer.TargetType007:
if st.Coin >= val {
state = true
}
log.Info("dataUpStat TargetType007 mid(%d)|v(%+v)|", mid, st.Coin)
case newcomer.TargetType008:
if st.Like >= val {
state = true
}
log.Info("dataUpStat TargetType008 mid(%d)|v(%+v)|", mid, st.Like)
case newcomer.TargetType009:
if st.Dm >= val {
state = true
}
log.Info("dataUpStat TargetType009 mid(%d)|v(%+v)|", mid, st.Dm)
}
if state {
_, err := s.newc.UpUserTask(c, mid, v.ID)
if err != nil {
log.Error("dataUpStat s.newc.UpUserTask mid(%d)|task id(%d)|err(%v)", mid, v.ID, err)
}
}
}
}
func (s *Service) accProfileWithStat(c context.Context, mid int64, tasks []*newcomer.Task) {
if len(tasks) == 0 {
return
}
pl, err := s.acc.ProfileWithStat(c, mid)
if err != nil {
log.Error("accProfileWithStat s.acc.ProfileWithStat error(%v)", err)
return
}
if pl == nil {
return
}
for _, v := range tasks {
if pl.Follower >= int64(v.TargetValue) {
_, err := s.newc.UpUserTask(c, mid, v.ID)
if err != nil {
log.Error("accProfileWithStat s.newc.UpUserTask mid(%d)|task id(%d)|err(%v)", mid, v.ID, err)
continue
}
log.Info("accProfileWithStat finish task mid(%d)|follower(%d)|", mid, pl.Follower)
}
}
}
func (s *Service) wmWaterMark(c context.Context, mid int64, tasks []*newcomer.Task) {
if len(tasks) == 0 {
return
}
wm, err := s.wm.WaterMark(c, mid)
if err != nil {
log.Error("wmWaterMark s.wm.WaterMark mid(%d) error(%v)", mid, err)
return
}
for _, v := range tasks {
if wm != nil && wm.State == 1 && wm.URL != "" {
_, err := s.newc.UpUserTask(c, mid, v.ID)
if err != nil {
log.Error("wmWaterMark s.newc.UpUserTask mid(%d)|task id(%d)|err(%v)", mid, v.ID, err)
continue
}
log.Info("wmWaterMark finish task mid(%d)|state(%d)|", mid, wm.State)
}
}
}
func (s *Service) accRelation(c context.Context, mid int64, tasks []*newcomer.Task) {
if len(tasks) == 0 {
return
}
fid := creatorMID //用户哔哩哔哩创作中心 mid
fl, err := s.acc.Relations(c, mid, []int64{fid}, "")
if err != nil {
log.Error("accRelation s.acc.Relations mid(%d)|ip(%s)|error(%v)", mid, "", err)
return
}
if fl == nil {
return
}
for _, v := range tasks {
if st, ok := fl[fid]; ok && (st == 6 || st == 2) {
_, err := s.newc.UpUserTask(c, mid, v.ID)
if err != nil {
log.Error("accRelation s.newc.UpUserTask mid(%d)|task id(%d)|err(%v)", mid, v.ID, err)
continue
}
log.Info("accRelation finish task mid(%d)|state(%d)|", mid, st)
}
}
}
func (s *Service) dataUpArchiveStatQuery(c context.Context, mid int64, tasks []*newcomer.Task) {
if len(tasks) == 0 {
return
}
st, err := s.data.UpArchiveStatQuery(c, mid, time.Now().AddDate(0, 0, -1).Add(-12*time.Hour).Format("20060102"))
if err != nil || st == nil {
log.Error("dataUpArchiveStatQuery s.data.UpArchiveStatQuery mid(%d)|err(%v)", mid, err)
return
}
for _, v := range tasks {
val := int64(v.TargetValue)
state := false
switch v.TargetType {
case newcomer.TargetType013:
if st.FromPhoneNum >= val {
log.Info("dataUpArchiveStatQuery TargetType013 mid(%d)|v(%+v)|", mid, st.FromPhoneNum)
state = true
}
case newcomer.TargetType015:
if st.PlayV >= val {
log.Info("dataUpArchiveStatQuery TargetType015 mid(%d)|v(%+v)|", mid, st.PlayV)
state = true
}
case newcomer.TargetType016:
if st.ReplyV >= val {
log.Info("dataUpArchiveStatQuery TargetType016 mid(%d)|v(%+v)|", mid, st.ReplyV)
state = true
}
case newcomer.TargetType017:
if st.ShareV >= val {
log.Info("dataUpArchiveStatQuery TargetType017 mid(%d)|v(%+v)|", mid, st.ShareV)
state = true
}
case newcomer.TargetType018:
if st.FavV >= val {
log.Info("dataUpArchiveStatQuery TargetType018 mid(%d)|v(%+v)|", mid, st.FavV)
state = true
}
case newcomer.TargetType019:
if st.CoinV >= val {
log.Info("dataUpArchiveStatQuery TargetType019 mid(%d)|v(%+v)|", mid, st.CoinV)
state = true
}
case newcomer.TargetType020:
if st.LikeV >= val {
log.Info("dataUpArchiveStatQuery TargetType020 mid(%d)|v(%+v)|", mid, st.LikeV)
state = true
}
case newcomer.TargetType021:
if st.DmV >= val {
log.Info("dataUpArchiveStatQuery TargetType021 mid(%d)|v(%+v)|", mid, st.DmV)
state = true
}
}
if state {
_, err := s.newc.UpUserTask(c, mid, v.ID)
if err != nil {
log.Error("dataUpArchiveStatQuery s.newc.UpUserTask mid(%d)|task id(%d)|err(%v)", mid, v.ID, err)
}
}
}
}
func (s *Service) orderGrowAccountState(c context.Context, mid int64, tasks []*newcomer.Task) {
if len(tasks) == 0 {
return
}
ac, err := s.order.GrowAccountState(c, mid, 0)
if err != nil {
log.Error("orderGrowAccountState s.order.GrowUpPlan mid(%d) error(%v)", mid, err)
return
}
if ac == nil {
return
}
for _, v := range tasks {
if ac.State == 3 { //账号状态; 1: 未申请; 2: 待审核; 3: 已签约; 4.已驳回; 5.主动退出; 6:被动退出; 7:封禁
_, err := s.newc.UpUserTask(c, mid, v.ID)
if err != nil {
log.Error("orderGrowAccountState s.newc.UpUserTask mid(%d)|task id(%d)|err(%v)", mid, v.ID, err)
continue
}
log.Info("orderGrowAccountState finish task mid(%d)|state(%d)|", mid, ac.State)
}
}
}
func (s *Service) medalCheckMedal(c context.Context, mid int64, tasks []*newcomer.Task) {
if len(tasks) == 0 {
return
}
medal, err := s.medal.Medal(c, mid)
if err != nil {
log.Error("medalCheckMedal s.medal.Medal mid(%d) error(%v)", mid, err)
return
}
if medal == nil {
return
}
for _, v := range tasks {
status, err := strconv.Atoi(medal.Status)
if err != nil {
log.Error("medalCheckMedal strconv.Atoi medal.Status(%s) error(%v)", medal.Status, err)
continue
}
if status == 2 { //勋章审核状态 -1已拒绝 0未申请 1已申请 2已开通
_, err := s.newc.UpUserTask(c, mid, v.ID)
if err != nil {
log.Error("medalCheckMedal s.newc.UpUserTask mid(%d)|task id(%d)|err(%v)", mid, v.ID, err)
continue
}
log.Info("medalCheckMedal finish task mid(%d)|state(%d)|", mid, status)
}
}
}
func getTaskSortMap(tasks []*newcomer.Task) map[int8][]*newcomer.Task {
taskSortMap := make(map[int8][]*newcomer.Task)
for _, v := range tasks {
switch v.TargetType {
case newcomer.TargetType001, newcomer.TargetType014:
taskSortMap[newcomer.ArcUpCount] = append(taskSortMap[newcomer.ArcUpCount], v)
case newcomer.TargetType002: //分享
case newcomer.TargetType003:
taskSortMap[newcomer.AcaPlayCount] = append(taskSortMap[newcomer.AcaPlayCount], v)
case newcomer.TargetType004, newcomer.TargetType005, newcomer.TargetType006, newcomer.TargetType007, newcomer.TargetType008, newcomer.TargetType009:
taskSortMap[newcomer.DataUpStat] = append(taskSortMap[newcomer.DataUpStat], v)
case newcomer.TargetType010, newcomer.TargetType022:
taskSortMap[newcomer.AccProfileWithStat] = append(taskSortMap[newcomer.AccProfileWithStat], v)
case newcomer.TargetType011:
taskSortMap[newcomer.WmWaterMark] = append(taskSortMap[newcomer.WmWaterMark], v)
case newcomer.TargetType012:
taskSortMap[newcomer.AccRelation] = append(taskSortMap[newcomer.AccRelation], v)
case newcomer.TargetType013, newcomer.TargetType015, newcomer.TargetType016, newcomer.TargetType017, newcomer.TargetType018, newcomer.TargetType019, newcomer.TargetType020, newcomer.TargetType021:
taskSortMap[newcomer.DataUpArchiveStat] = append(taskSortMap[newcomer.DataUpArchiveStat], v)
case newcomer.TargetType023:
taskSortMap[newcomer.OrderGrowAccountState] = append(taskSortMap[newcomer.OrderGrowAccountState], v)
case newcomer.TargetType024:
taskSortMap[newcomer.MedalCheckMedal] = append(taskSortMap[newcomer.MedalCheckMedal], v)
}
}
return taskSortMap
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,57 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"operation_test.go",
"service_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//library/ecode:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"operation.go",
"service.go",
],
importpath = "go-common/app/interface/main/creative/service/operation",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/dao/creative:go_default_library",
"//app/interface/main/creative/model/operation:go_default_library",
"//app/interface/main/creative/service:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,213 @@
package operation
import (
"context"
"encoding/json"
operMdl "go-common/app/interface/main/creative/model/operation"
"go-common/library/ecode"
"go-common/library/log"
"strconv"
"strings"
"time"
)
// 0 => web+app; 1=> app; 2=> web; 100=>全平台
const (
remarkShowBanner = "show_banner"
)
// Tool get a tool down.
func (s *Service) Tool(c context.Context, ty int8) (ops []*operMdl.Operation, err error) {
var tyStr string
if ty == 0 || ty == 1 { //创作中心页的tool下载
tyStr = "icon"
} else if ty == 2 { //投稿页的tool下载
tyStr = "submit_icon"
}
if op, ok := s.toolCache[tyStr]; ok {
ops = op
}
return
}
// WebOperations get full operations.
func (s *Service) WebOperations(c context.Context) (ops map[string][]*operMdl.Operation, err error) {
if s.operCache == nil {
err = ecode.NothingFound
return
}
ops = make(map[string][]*operMdl.Operation)
for _, v := range s.operCache {
if v.Platform == 0 || v.Platform == 2 {
o := &operMdl.Operation{}
o.ID = v.ID
o.Ty = v.Ty
o.Rank = v.Rank
o.Pic = v.Pic
o.Link = v.Link
o.Content = v.Content
o.Remark = v.Remark
o.Note = v.Note
o.Stime = v.Stime
o.Etime = v.Etime
if o.Ty == "play" || o.Ty == "collect_arc" {
o.Ty = "board"
}
ops[o.Ty] = append(ops[o.Ty], o)
}
}
for _, ty := range operMdl.FullTypes() {
trimTy := strings.Trim(ty, "'")
if _, ok := ops[trimTy]; !ok {
ops[trimTy] = []*operMdl.Operation{}
}
}
return
}
// AppBanner get app index flexslider; filter by platform + business + remark
func (s *Service) AppBanner(c context.Context) (bns []*operMdl.Banner, cbns []*operMdl.BannerCreator, err error) {
bns = make([]*operMdl.Banner, 0, len(s.operCache))
cbns = make([]*operMdl.BannerCreator, 0, len(s.operCache))
for _, v := range s.operCache {
// 平台切除web平台;
// 允许征稿启示也显示在所有APP的Banner上;
// 必须开启remark=="show_banner"的业务校验;
if (v.Ty != "play" && v.Ty != "collect_arc") ||
v.Platform == 2 ||
v.Remark != remarkShowBanner {
continue
}
bn := &operMdl.Banner{}
cbn := &operMdl.BannerCreator{}
bn.Ty = v.Ty
bn.Rank = v.Rank
cbn.Ty = v.Ty
cbn.Rank, _ = strconv.Atoi(v.Rank)
if v.AppPic == "" {
pics := []string{}
if err = json.Unmarshal([]byte(v.Pic), &pics); err != nil {
log.Error("json.Unmarshal(%v) error(%v)", string(v.Pic), err)
}
bn.Pic = pics[len(pics)-1]
cbn.Pic = pics[len(pics)-1]
} else {
bn.Pic = v.AppPic
cbn.Pic = v.AppPic
}
bn.Link = v.Link
bn.Content = v.Content
cbn.Link = v.Link
cbn.Content = v.Content
bns = append(bns, bn)
cbns = append(cbns, cbn)
}
return
}
// CreatorOperationList get operations list.
func (s *Service) CreatorOperationList(c context.Context, pn, ps int) (list *operMdl.BannerList, err error) {
if s.operCache == nil {
err = ecode.NothingFound
return
}
list = &operMdl.BannerList{Pn: pn, Ps: ps}
// notice: s.CreatorRelOperCache["play"] 已经进行合并
play, ok := s.CreatorRelOperCache["play"]
if !ok {
return
}
bcs := make([]*operMdl.BannerCreator, 0)
for _, v := range play {
bc := &operMdl.BannerCreator{}
bc.Ty = v.Ty
bc.Rank, _ = strconv.Atoi(v.Rank)
if v.AppPic == "" {
pics := []string{}
if err = json.Unmarshal([]byte(v.Pic), &pics); err != nil {
log.Error("json.Unmarshal(%v) error(%v)", string(v.Pic), err)
}
bc.Pic = pics[len(pics)-1]
} else {
bc.Pic = v.AppPic
}
bc.Link = v.Link
bc.Content = v.Content
st, _ := time.Parse("2006-01-02 15:04:05", v.Stime)
bc.Stime = st.Unix()
et, _ := time.Parse("2006-01-02 15:04:05", v.Etime)
bc.Etime = et.Unix()
bcs = append(bcs, bc)
}
total := len(bcs)
list.Total = total
start := (pn - 1) * ps
end := pn * ps
if total <= start {
list.BannerCreator = make([]*operMdl.BannerCreator, 0)
} else if total <= end {
list.BannerCreator = bcs[start:total]
} else {
list.BannerCreator = bcs[start:end]
}
return
}
// AppOperationList get operations list.
func (s *Service) AppOperationList(c context.Context, pn, ps int, tp string) (list *operMdl.BannerList, err error) {
tpOK := false
for _, fullTp := range operMdl.FullTypes() {
trimTy := strings.Trim(fullTp, "'")
if trimTy == tp {
tpOK = true
break
}
}
if s.allRelOperCache == nil || !tpOK {
return
}
list = &operMdl.BannerList{Pn: pn, Ps: ps}
vals := make([]*operMdl.Operation, 0)
for _, v := range s.allRelOperCache {
if v.Ty == tp && (v.Platform == 0 || v.Platform == 1) {
vals = append(vals, v)
}
}
if len(vals) == 0 {
return
}
bcs := make([]*operMdl.BannerCreator, 0)
for _, v := range vals {
bc := &operMdl.BannerCreator{}
bc.Ty = v.Ty
bc.Rank, _ = strconv.Atoi(v.Rank)
if v.AppPic == "" {
pics := []string{}
if err = json.Unmarshal([]byte(v.Pic), &pics); err != nil {
log.Error("json.Unmarshal(%v) error(%v)", string(v.Pic), err)
}
bc.Pic = pics[len(pics)-1]
} else {
bc.Pic = v.AppPic
}
bc.Link = v.Link
bc.Content = v.Content
st, _ := time.Parse("2006-01-02 15:04:05", v.Stime)
bc.Stime = st.Unix()
et, _ := time.Parse("2006-01-02 15:04:05", v.Etime)
bc.Etime = et.Unix()
bcs = append(bcs, bc)
}
total := len(bcs)
list.Total = total
start := (pn - 1) * ps
end := pn * ps
if total <= start {
list.BannerCreator = make([]*operMdl.BannerCreator, 0)
} else if total <= end {
list.BannerCreator = bcs[start:total]
} else {
list.BannerCreator = bcs[start:end]
}
return
}

View File

@@ -0,0 +1,38 @@
package operation
import (
"context"
"go-common/library/ecode"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func Test_WebOperations(t *testing.T) {
Convey("WebOperations", t, WithService(func(s *Service) {
res, err := s.WebOperations(context.TODO())
So(err, ShouldEqual, ecode.NothingFound)
So(res, ShouldBeNil)
}))
Convey("Ping", t, WithService(func(s *Service) {
err := s.Ping(context.TODO())
So(err, ShouldEqual, ecode.NothingFound)
}))
}
func Test_AppBanner(t *testing.T) {
Convey("AppBanner", t, WithService(func(s *Service) {
bns, cbns, err := s.AppBanner(context.TODO())
So(bns, ShouldBeNil)
So(cbns, ShouldBeNil)
So(err, ShouldNotBeNil)
}))
}
func Test_CreatorOperationList(t *testing.T) {
Convey("CreatorOperationList", t, WithService(func(s *Service) {
bns, err := s.CreatorOperationList(context.TODO(), 1, 10)
So(bns, ShouldBeNil)
So(err, ShouldNotBeNil)
}))
}

View File

@@ -0,0 +1,168 @@
package operation
import (
"context"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/dao/creative"
operMdl "go-common/app/interface/main/creative/model/operation"
"go-common/app/interface/main/creative/service"
"go-common/library/log"
"time"
)
//Service struct
type Service struct {
c *conf.Config
creative *creative.Dao
NoticeStr string
CreativeStr string
// cache
operCache []*operMdl.Operation
allRelOperCache []*operMdl.Operation
toolCache map[string][]*operMdl.Operation
WebRelOperCache map[string][]*operMdl.Operation
CreatorRelOperCache map[string][]*operMdl.Operation
}
//New get service
func New(c *conf.Config, rpcdaos *service.RPCDaos) *Service {
s := &Service{
c: c,
creative: creative.New(c),
}
s.loadOper()
s.loadTool()
s.loadRelOper()
go s.loadproc()
return s
}
func (s *Service) loadOper() {
var (
op []*operMdl.Operation
creative *operMdl.Operation
notice *operMdl.Operation
err error
)
op, err = s.creative.Operations(context.TODO(), operMdl.FullTypes())
if err != nil {
log.Error("s.oper.Operations error(%v)", err)
return
}
log.Warn("loadOper fulltypes (%+v)", op)
s.operCache = op
// generate rank 最小的 creative and notice str
for _, v := range op {
if v.Ty == "creative" && (v.Platform == 0 || v.Platform == 1) {
if creative == nil || (v.Rank < creative.Rank) {
creative = v
}
}
if v.Ty == "notice" && (v.Platform == 0 || v.Platform == 1) {
if notice == nil || (v.Rank < notice.Rank) {
notice = v
}
}
}
log.Warn("loadOper CreativeStr(%+v) | NoticeStr(%+v)", creative, notice)
if creative != nil {
s.CreativeStr = creative.Content
} else {
s.CreativeStr = ""
}
if notice != nil {
s.NoticeStr = notice.Content
} else {
s.NoticeStr = ""
}
}
func (s *Service) loadRelOper() {
var (
op []*operMdl.Operation
err error
)
op, err = s.creative.AllOperByTypeSQL(context.TODO(), []string{"'play'", "'notice'", "'collect_arc'"})
if err != nil {
log.Error("s.oper.AllOperByTypeSQL error(%v)", err)
return
}
s.allRelOperCache = op
tmpWebRelOperCache := make(map[string][]*operMdl.Operation)
tmpCreatorRelOperCache := make(map[string][]*operMdl.Operation)
for _, v := range op {
vs := &operMdl.Operation{
ID: v.ID,
Ty: v.Ty,
Rank: v.Rank,
Pic: v.Pic,
Link: v.Link,
Content: v.Content,
Remark: v.Remark,
Note: v.Note,
Stime: v.Stime,
Etime: v.Etime,
AppPic: v.AppPic,
Platform: v.Platform,
}
// 合并 collect_arc + play => play, for Web + Creator
if vs.Ty == "collect_arc" {
vs.Ty = "play"
}
if v.Platform == 0 { //all platform
tmpWebRelOperCache[vs.Ty] = append(tmpWebRelOperCache[vs.Ty], vs)
tmpCreatorRelOperCache[vs.Ty] = append(tmpCreatorRelOperCache[vs.Ty], vs)
} else if v.Platform == 1 { //app
tmpCreatorRelOperCache[vs.Ty] = append(tmpCreatorRelOperCache[vs.Ty], vs)
} else if v.Platform == 2 { //web
tmpWebRelOperCache[vs.Ty] = append(tmpWebRelOperCache[vs.Ty], vs)
}
}
s.WebRelOperCache = tmpWebRelOperCache
s.CreatorRelOperCache = tmpCreatorRelOperCache
}
func (s *Service) loadTool() {
var (
icon []*operMdl.Operation
sicon []*operMdl.Operation
err error
)
icon, err = s.creative.Tool(context.TODO(), "icon")
if err != nil {
log.Error("s.oper.Tool(%s) error(%v)", "icon", err)
return
}
sicon, err = s.creative.Tool(context.TODO(), "submit_icon")
if err != nil {
log.Error("s.oper.Tool(%s) error(%v)", "submit_icon", err)
return
}
var tmp = map[string][]*operMdl.Operation{}
tmp["icon"] = icon
tmp["submit_icon"] = sicon
s.toolCache = tmp
}
// loadproc
func (s *Service) loadproc() {
for {
time.Sleep(1 * time.Minute)
s.loadOper()
s.loadTool()
s.loadRelOper()
}
}
// Ping service
func (s *Service) Ping(c context.Context) (err error) {
if err = s.creative.Ping(c); err != nil {
log.Error("s.operationDao.PingDb err(%v)", err)
}
return
}
// Close dao
func (s *Service) Close() {
s.creative.Close()
}

View File

@@ -0,0 +1,33 @@
package operation
import (
"flag"
"path/filepath"
"time"
"go-common/app/interface/main/creative/conf"
. "github.com/smartystreets/goconvey/convey"
"go-common/app/interface/main/creative/service"
)
var (
s *Service
)
func init() {
dir, _ := filepath.Abs("../../cmd/creative.toml")
flag.Set("conf", dir)
conf.Init()
rpcdaos := service.NewRPCDaos(conf.Conf)
s = New(conf.Conf, rpcdaos)
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
Reset(func() {
})
f(s)
}
}

Some files were not shown because too many files have changed in this diff Show More