Initial commit

This commit is contained in:
Donny
2019-04-22 20:46:32 +08:00
commit 49ab8aadd1
25441 changed files with 4055000 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/interface/main/mcn/cmd:all-srcs",
"//app/interface/main/mcn/conf:all-srcs",
"//app/interface/main/mcn/dao:all-srcs",
"//app/interface/main/mcn/model:all-srcs",
"//app/interface/main/mcn/server:all-srcs",
"//app/interface/main/mcn/service:all-srcs",
"//app/interface/main/mcn/tool/cache:all-srcs",
"//app/interface/main/mcn/tool/datacenter:all-srcs",
"//app/interface/main/mcn/tool/validate:all-srcs",
"//app/interface/main/mcn/tool/worker:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,29 @@
# v1.3.0
1. mcn四期功能
# v1.2.1
1. 修复mcn_data_up表中没有数据时up主列表不存在的问题
# v1.2.0
1. mcn三期功能
# v1.1.2
1. 修复数据显示问题
# v1.1.1
1. 修复待开启状态下的签约周期值
# v1.1.0
1. mcn二期功能
# v1.0.3
1. 修改data summary逻辑现在直接取数据库中的数据
# v1.0.2
1. mcn上传接口加防刷
# v1.0.1
1. mcn一期功能上线
# v1.0.0
1. mcn-interface init

View File

@@ -0,0 +1,11 @@
# Owner
wangzhe01
shencen
# Author
hejianbing
wangyuzhe
yanjinbin
# Reviewer
wangzhe01

View File

@@ -0,0 +1,20 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- hejianbing
- shencen
- wangzhe01
labels:
- interface
- interface/main/mcn
- main
options:
no_parent_owners: true
reviewers:
- hejianbing
- limengqing
- liyixin
- shencen
- wangyuzhe
- wangzhe01
- yanjinbin

View File

@@ -0,0 +1,12 @@
# mcn-interface
# 项目简介
1.
# 编译环境
# 依赖包
# 编译执行

View File

@@ -0,0 +1 @@
# HTTP API文档

View File

@@ -0,0 +1,43 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
)
go_binary(
name = "cmd",
embed = [":go_default_library"],
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = ["main.go"],
data = ["mcn-interface.toml"],
importpath = "go-common/app/interface/main/mcn/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/mcn/conf:go_default_library",
"//app/interface/main/mcn/server/http:go_default_library",
"//library/ecode/tip:go_default_library",
"//library/log:go_default_library",
"//library/net/trace: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,43 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"go-common/app/interface/main/mcn/conf"
"go-common/app/interface/main/mcn/server/http"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
"go-common/library/net/trace"
)
func main() {
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
log.Init(conf.Conf.Log)
defer log.Close()
log.SetFormat("[%D %T] [%L] [%S] %M")
log.Info("start")
trace.Init(conf.Conf.Tracer)
defer trace.Close()
ecode.Init(conf.Conf.Ecode)
http.Init(conf.Conf)
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
log.Info("exit")
return
case syscall.SIGHUP:
default:
return
}
}
}

View File

@@ -0,0 +1,235 @@
[log]
stdout = true
[memcache]
name = "mcn-interface"
proto = "tcp"
addr = "172.16.63.98:11211"
active = 50
idle = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "24h"
McnSignCacheExpire = "10s"
McnDataCacheExpire = "30s"
[uploadantispam]
on=true
second=60
n=10
hour=1
m=100
[uploadantispam.redis]
name = "mcn/mcn-interface"
proto = "tcp"
addr = "172.18.33.60:6893"
idle = 10
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
expire = "10m"
[MCNorm]
dsn = "upcrm:DdL6c5JaWCYKMAQ10PURbfeImow9HXlx@tcp(172.16.33.205:3306)/bilibili_upcrm?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 1
idleTimeout = "4h"
[bfs]
bucket = "mcn"
key = "0i4zga2vht5cnrw6"
secret = "i3sryb7gdfwvtqmkne49x2ojp8l065"
# 上传文件大小限制为10M
maxFileSize = 10485760
[host]
bfs = "http://uat-bfs.bilibili.co"
msg = "http://message.bilibili.co"
Videoup = "http://uat-archive.api.bilibili.co"
Api = "http://api.bilibili.co"
[httpClient]
key = "b8f239ca38a53308"
secret = "5460ef72fe13c10dfb53442b9111427e"
dial = "1s"
timeout = "5s"
keepAlive = "60s"
[httpClient.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[Other]
debug = true
PublicationPriceChangeLimit = "1m"
WhiteListMid = [370894821, 15555180]
[grpcclient]
[grpcclient.tag]
timeout = "1s"
[grpcclient.account]
timeout = "1s"
[grpcclient.member]
timeout = "1s"
[grpcclient.archive]
timeout = "1s"
[RankCache]
Size = 1024
ExpireTime = "15s"
RecommendPoolExpireTime = "15s"
[DataClientConf]
Key = "b9739fc84d087c4b3c1aa297d01999e6"
Secret = "5018928e83a23c0cc9773f2571de01e5"
[property]
# MCN申请MCN管理入口申请成功
[[property.msg]]
msgType = 1
code = "116_1_1"
title = "MCN管理后台申请已通过"
content = '您申请的mcn管理后台已通过个人页点击mcn管理中心即可查看快快去关联旗下up主吧记得关联上自己的账号哦点击去#{关联up主}{"https://member.bilibili.com/studio/mcn/m/home"}——”'
# MCN申请MCN管理入口申请未通过
[[property.msg]]
msgType = 2
code = "116_1_2"
title = "MCN管理后台申请未通过"
content = '非常抱歉您的申请由于%s的原因暂未通过点击#{再次申请}{"https://member.bilibili.com/studio/mcn/m/welcome"}'
# MCN申请和up主绑定申请授权
[[property.msg]]
msgType = 3
code = "116_2_1"
title = "MCN账号绑定申请"
content = '现有用户昵称%suid%d属于公司%s申请与您的账号绑定授权。授权后您的账号数据将与对方共享点击#{查看授权详情}{"https://member.bilibili.com/studio/mcn/authorization/%d?type=bind"}'
# MCN申请和up主绑定up主同意等待运营审核中
[[property.msg]]
msgType = 4
code = "116_2_2"
title = "MCN账号绑定申请"
content = "您已成功确认与“%s公司”用户名“%s”UID%d的合作关系我们会在3个工作日内审核并以站内信告知是否绑定。"
# MCN申请和up主绑定up主同意且运营通过
[[property.msg]]
msgType = 5
code = "116_2_3"
title = "您已成功与up主账号绑定"
content = "您已经成功绑定用户昵称%suid%d您将可以在MCN后台系统中查看该UP主的相关数据"
# MCN申请和up主绑定up主同意且运营通过
[[property.msg]]
msgType = 6
code = "116_2_4"
title = "您已成功与MCN账号绑定"
content = "您已经成功绑定公司:%s公司用户名“%s”UID%d您的账号数据将与MCN共享"
# MCN申请和up主绑定up主同意但运营未通过
[[property.msg]]
msgType = 7
code = "116_2_5"
title = "您与UP账号绑定审核未通过"
content = "您与用户昵称%suid%d的绑定申请因%s的原因被驳回绑定失败"
# MCN申请和up主绑定up主同意但运营未通过
[[property.msg]]
msgType = 8
code = "116_2_6"
title = "您与MCN账号绑定审核未通过"
content = "您与%s公司用户名“%s”UID%d的绑定申请因%s的原因被驳回绑定失败"
# MCN申请和up主绑定被up主拒绝
[[property.msg]]
msgType = 9
code = "116_2_7"
title = "您与UP账号绑定申请未通过"
content = "用户昵称%suid%d拒绝与您的主账号进行绑定请确认邀请UP主的昵称与UID无误后再次申请"
# MCN和up主纠纷处理 - Up主和MCN关系冻结
[[property.msg]]
msgType = 10
code = "116_3_1"
title = "您与MCN的绑定关系已暂时冻结"
content = "已暂时冻结您与%s公司用户名“%s”UID%d的合约关系冻结期内您的所有数据将不再对该账号进行展示"
# MCN和up主纠纷处理 - Up主和MCN关系冻结
[[property.msg]]
msgType = 11
code = "116_3_2"
title = "您与up主的绑定关系已暂时冻结"
content = "已暂时冻结用户昵称%suid%d与您的合约关系冻结期内该UP主的所有数据将不再对您进行展示此期间该UP的增长数据将不计入您的数据表现中"
# MCN和up主纠纷处理 - Up主和MCN提前解约
[[property.msg]]
msgType = 12
code = "116_3_3"
title = "您与MCN的绑定关系已解除"
content = "已解除您与%s公司用户名“%s”UID%d的合约关系您的所有数据将不再对该账号进行展示"
# MCN和up主纠纷处理 - Up主和MCN提前解约
[[property.msg]]
msgType = 13
code = "116_3_4"
title = "您与up主的绑定关系已解除"
content = "已解除用户昵称%suid%d与您的合约关系该UP主的所有数据将不再对您进行展示该UP的数据增长将停止在冻结日/解约日"
# MCN违规账号封禁
[[property.msg]]
msgType = 14
code = "116_4_1"
title = "MCN后台被暂时封禁"
content = "非常抱歉您的MCN后台被暂时封禁冻结期间将无法使用"
# MCN违规账号清退
[[property.msg]]
msgType = 15
code = "116_4_2"
title = "MCN后台被关闭"
content = "非常抱歉您的MCN后台被关闭关闭后您的MCN后台将无法登录"
# MCN和B站续约
[[property.msg]]
msgType = 16
code = "116_1_3"
title = "MCN管理后台成功续约"
content = '恭喜您成功续约创作合伙人计划,成为我们新一期的合作伙伴,与我们共同打造良好的站内生态'
# MCN违规账号冻结期结束账号恢复
[[property.msg]]
msgType = 17
code = "116_4_3"
title = "MCN后台已恢复"
content = '您的MCN管理后台功能已恢复点击进入MCN管理后台'
# MCN新开权限
[[property.msg]]
msgType = 18
code = "116_5_1"
title = "你的%s开通"
content = '你的%s已开通快去看看吧——'
# MCN权限关闭
[[property.msg]]
msgType = 19
code = "116_5_2"
title = "你的%s关闭"
content = '你的%s被关闭了哦'
# UP主不同意授权变更
[[property.msg]]
msgType = 20
code = "116_6_1"
title = "与%sUP主的权限变更失败"
content = '与%sUP主的合作权限变更因up主不同意授权未通过'
# 运营不同意授权变更
[[property.msg]]
msgType = 21
code = "116_6_2"
title = "与%sUP主的权限变更失败"
content = '与%sUP主的合作权限变更因%s原因审核未通过'
# 运营同意授权变更
[[property.msg]]
msgType = 22
code = "116_6_3"
title = "与%sUP主的权限变更成功"
content = '与%sUP主的合作权限已成功变更当前权限为%s'
# MCN申请与UP主绑定的权限变更
[[property.msg]]
msgType = 23
code = "116_6_4"
title = "您与%sMCN的授权发生变更请确认是否同意"
content = '%sMCN申请与您的权限变更为%s#{点击链接}{"https://member.bilibili.com/studio/mcn/authorization/%d?type=reauth"}确认是否同意变更权限'

View File

@@ -0,0 +1,43 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["conf.go"],
importpath = "go-common/app/interface/main/mcn/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/mcn/model:go_default_library",
"//app/interface/main/mcn/tool/datacenter:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/conf:go_default_library",
"//library/database/orm:go_default_library",
"//library/ecode/tip:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/antispam:go_default_library",
"//library/net/rpc/warden:go_default_library",
"//library/net/trace:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/BurntSushi/toml: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,166 @@
package conf
import (
"errors"
"flag"
"go-common/app/admin/main/mcn/model"
"go-common/library/cache/memcache"
"go-common/library/conf"
"go-common/library/database/orm"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/antispam"
"go-common/library/net/rpc/warden"
"go-common/library/net/trace"
"go-common/library/time"
"go-common/app/interface/main/mcn/tool/datacenter"
"github.com/BurntSushi/toml"
)
var (
confPath string
client *conf.Client
// Conf config
Conf = &Config{}
)
// Config .
type Config struct {
Log *log.Config
BM *bm.ServerConfig
Tracer *trace.Config
Memcache *MemcacheConfig
MCNorm *orm.Config
Ecode *ecode.Config
BFS *BFS
Host *Host
// http client
HTTPClient *bm.ClientConfig
Property *Property
Other *OtherConfig
GRPCClient *GRPCClient
RankCache *GCacheConfig
//upload Antispam
UploadAntispam *antispam.Config
DataClientConf *datacenter.ClientConfig
}
// AfterLoad .
func (s *Config) AfterLoad() {
s.Other.WhiteListMidMap = make(map[int64]struct{}, len(s.Other.WhiteListMid))
for _, v := range s.Other.WhiteListMid {
s.Other.WhiteListMidMap[v] = struct{}{}
}
}
// GRPCClient .
type GRPCClient struct {
Tag *warden.ClientConfig
Account *warden.ClientConfig
Member *warden.ClientConfig
Archive *warden.ClientConfig
}
// MemcacheConfig .
type MemcacheConfig struct {
memcache.Config
McnSignCacheExpire time.Duration
McnDataCacheExpire time.Duration
}
// Property .
type Property struct {
MSG []*model.MSG
}
// BFS bfs config
type BFS struct {
Bucket string
Key string
Secret string
}
// Host host config .
type Host struct {
Bfs string
Msg string
Videoup string
API string
}
//OtherConfig some config.
type OtherConfig struct {
Debug bool
PublicationPriceChangeLimit time.Duration
WhiteListMid []int64 // 超级查看权限
WhiteListMidMap map[int64]struct{}
}
//IsWhiteList check is in white list
func (s *OtherConfig) IsWhiteList(mid int64) bool {
_, ok := s.WhiteListMidMap[mid]
return ok
}
//GCacheConfig gcache
type GCacheConfig struct {
Size int // gcache
ExpireTime time.Duration // key expire time
RecommendPoolExpireTime time.Duration
}
func init() {
flag.StringVar(&confPath, "conf", "", "default config path")
}
// Init init conf
func Init() error {
defer Conf.AfterLoad()
if confPath != "" {
return local()
}
return remote()
}
func local() (err error) {
_, err = toml.DecodeFile(confPath, &Conf)
return
}
func remote() (err error) {
if client, err = conf.New(); err != nil {
return
}
if err = load(); err != nil {
return
}
go func() {
for range client.Event() {
log.Info("config reload")
if load() != nil {
log.Error("config reload error (%v)", err)
}
}
}()
return
}
func load() (err error) {
var (
s string
ok bool
tmpConf *Config
)
if s, ok = client.Toml2(); !ok {
return errors.New("load config center error")
}
if _, err = toml.Decode(s, &tmpConf); err != nil {
return errors.New("could not decode config")
}
*Conf = *tmpConf
return
}

View File

@@ -0,0 +1,28 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/interface/main/mcn/dao/bfs:all-srcs",
"//app/interface/main/mcn/dao/cache:all-srcs",
"//app/interface/main/mcn/dao/datadao:all-srcs",
"//app/interface/main/mcn/dao/global:all-srcs",
"//app/interface/main/mcn/dao/mcndao:all-srcs",
"//app/interface/main/mcn/dao/msg:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,52 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"upload.go",
],
importpath = "go-common/app/interface/main/mcn/dao/bfs",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/mcn/conf: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"],
)
go_test(
name = "go_default_test",
srcs = [
"dao_test.go",
"upload_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/mcn/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
"//vendor/gopkg.in/h2non/gock.v1:go_default_library",
],
)

View File

@@ -0,0 +1,26 @@
package bfs
import (
"go-common/app/interface/main/mcn/conf"
)
// Dao dao
type Dao struct {
c *conf.Config
bucket string
key string
secret string
bfs string
}
// New init mysql db
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
bucket: c.BFS.Bucket,
key: c.BFS.Key,
secret: c.BFS.Secret,
bfs: c.Host.Bfs,
}
return
}

View File

@@ -0,0 +1,47 @@
package bfs
import (
"flag"
"os"
"strings"
"testing"
"go-common/app/interface/main/mcn/conf"
"gopkg.in/h2non/gock.v1"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.mcn-interface")
flag.Set("conf_token", "49e4671bafbf93059aeb602685052ca0")
flag.Set("tree_id", "58909")
flag.Set("conf_version", "docker-1")
flag.Set("deploy_env", "uat")
flag.Set("conf_host", "config.bilibili.co")
flag.Set("conf_path", "/tmp")
flag.Set("region", "sh")
flag.Set("zone", "sh001")
} else {
flag.Set("conf", "../../cmd/mcn-interface.toml")
}
if os.Getenv("UT_LOCAL_TEST") != "" {
flag.Set("conf", "../../cmd/mcn-interface.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
os.Exit(m.Run())
}
func httpMock(method, url string) *gock.Request {
r := gock.New(url)
r.Method = strings.ToUpper(method)
return r
}

View File

@@ -0,0 +1,74 @@
package bfs
import (
"context"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"fmt"
"hash"
"io"
"net/http"
"strconv"
"go-common/library/log"
)
const (
uploadurl = "/bfs/%s/%s"
template = "%s\n%s\n%s\n%d\n"
method = "PUT"
)
// Upload upload picture or log file to bfs
func (d *Dao) Upload(c context.Context, fileName, fileType string, expire int64, body io.Reader) (location string, err error) {
var (
url string
req *http.Request
resp *http.Response
code int
)
client := &http.Client{}
url = fmt.Sprintf(d.bfs+uploadurl, d.bucket, fileName)
if req, err = http.NewRequest(method, url, body); err != nil {
log.Error("http.NewRequest() Upload(%v) error(%v)", url, err)
return
}
authorization := authorize(d.key, d.secret, method, d.bucket, fileName, expire)
req.Header.Set("Host", d.bfs)
req.Header.Add("Date", fmt.Sprint(expire))
req.Header.Add("Authorization", authorization)
req.Header.Add("Content-Type", fileType)
resp, err = client.Do(req)
if err != nil {
log.Error("resp.Do(%s) error(%v)", url, err)
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
err = fmt.Errorf("status code error:%v", resp.StatusCode)
return
}
code, err = strconv.Atoi(resp.Header.Get("code"))
if err != nil || code != http.StatusOK {
err = fmt.Errorf("response code error:%v", code)
return
}
location = resp.Header.Get("Location")
return
}
// authorize returns authorization for upload file to bfs
func authorize(key, secret, method, bucket, file string, expire int64) (authorization string) {
var (
content string
mac hash.Hash
signature string
)
content = fmt.Sprintf(template, method, bucket, file, expire)
mac = hmac.New(sha1.New, []byte(secret))
mac.Write([]byte(content))
signature = base64.StdEncoding.EncodeToString(mac.Sum(nil))
authorization = fmt.Sprintf("%s:%s:%d", key, signature, expire)
return
}

View File

@@ -0,0 +1,51 @@
package bfs
import (
"bytes"
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
"gopkg.in/h2non/gock.v1"
)
func TestBfsUpload(t *testing.T) {
convey.Convey("Upload", t, func(ctx convey.C) {
var (
c = context.Background()
fileName = ""
fileType = "plain/text"
expire = int64(0)
body = bytes.NewBuffer([]byte("just test"))
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
defer gock.OffAll()
httpMock("PUT", d.bfs).Reply(200).SetHeader("code", "200").SetHeader("Location", "baidu")
location, err := d.Upload(c, fileName, fileType, expire, body)
ctx.Convey("Then err should be nil.location should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(location, convey.ShouldNotBeNil)
})
})
})
}
func TestBfsauthorize(t *testing.T) {
convey.Convey("authorize", t, func(ctx convey.C) {
var (
key = "1234"
secret = "wer1234"
method = "poost"
bucket = "dte"
file = "www"
expire = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
authorization := authorize(key, secret, method, bucket, file, expire)
ctx.Convey("Then authorization should not be nil.", func(ctx convey.C) {
ctx.So(authorization, convey.ShouldNotBeNil)
})
})
})
}

57
app/interface/main/mcn/dao/cache/BUILD vendored Normal file
View File

@@ -0,0 +1,57 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"cache.go",
"tag.go",
"video_types.go",
],
importpath = "go-common/app/interface/main/mcn/dao/cache",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/model/tag:go_default_library",
"//app/interface/main/mcn/conf:go_default_library",
"//app/service/main/videoup/model/archive:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster: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"],
)
go_test(
name = "go_default_test",
srcs = [
"cache_test.go",
"tag_test.go",
"video_types_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/model/tag:go_default_library",
"//app/interface/main/mcn/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,9 @@
package cache
import "time"
//LoadCache load cache
func LoadCache() {
var now = time.Now()
RefreshUpType(now)
}

View File

@@ -0,0 +1,46 @@
package cache
import (
"flag"
"os"
"testing"
"go-common/app/interface/main/mcn/conf"
"github.com/smartystreets/goconvey/convey"
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.mcn-interface")
flag.Set("conf_token", "49e4671bafbf93059aeb602685052ca0")
flag.Set("tree_id", "58909")
flag.Set("conf_version", "docker-1")
flag.Set("deploy_env", "uat")
flag.Set("conf_host", "config.bilibili.co")
flag.Set("conf_path", "/tmp")
flag.Set("region", "sh")
flag.Set("zone", "sh001")
} else {
flag.Set("conf", "../../cmd/mcn-interface.toml")
}
if os.Getenv("UT_LOCAL_TEST") != "" {
flag.Set("conf", "../../cmd/mcn-interface.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
os.Exit(m.Run())
}
func TestCacheLoadCache(t *testing.T) {
convey.Convey("LoadCache", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
LoadCache()
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}

46
app/interface/main/mcn/dao/cache/tag.go vendored Normal file
View File

@@ -0,0 +1,46 @@
package cache
import (
"sync"
"time"
"go-common/app/interface/main/creative/model/tag"
)
var (
//TagCache tag's cache key=>tag_id, value=>*tag.Meta
TagCache = make(map[int64]*tag.Meta)
tagMutex sync.Mutex
)
//ClearTagCache clear all tag cache
func ClearTagCache(tm time.Time) {
TagCache = make(map[int64]*tag.Meta)
}
//AddTagCache add tag cache
func AddTagCache(meta *tag.Meta) {
if meta == nil {
return
}
tagMutex.Lock()
TagCache[meta.TagID] = meta
tagMutex.Unlock()
}
//GetTagCache get tag cache
func GetTagCache(ids ...int64) (result map[int64]*tag.Meta, leftIDs []int64) {
result = make(map[int64]*tag.Meta)
tagMutex.Lock()
for _, v := range ids {
var d, ok = TagCache[v]
if !ok {
leftIDs = append(leftIDs, v)
continue
}
result[v] = d
}
tagMutex.Unlock()
return
}

View File

@@ -0,0 +1,52 @@
package cache
import (
"testing"
"time"
"go-common/app/interface/main/creative/model/tag"
"github.com/smartystreets/goconvey/convey"
)
func TestCacheClearTagCache(t *testing.T) {
convey.Convey("ClearTagCache", t, func(ctx convey.C) {
var (
tm = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
ClearTagCache(tm)
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}
func TestCacheAddTagCache(t *testing.T) {
convey.Convey("AddTagCache", t, func(ctx convey.C) {
var (
meta = &tag.Meta{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
AddTagCache(meta)
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}
func TestCacheGetTagCache(t *testing.T) {
convey.Convey("GetTagCache", t, func(ctx convey.C) {
var (
ids = int64(3)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
LoadCache()
result, leftIDs := GetTagCache(ids)
ctx.Convey("Then result,leftIDs should not be nil.", func(ctx convey.C) {
ctx.So(leftIDs, convey.ShouldNotBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,60 @@
package cache
import (
"context"
"time"
"go-common/app/interface/main/mcn/conf"
"go-common/app/service/main/videoup/model/archive"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
var (
//VideoUpTypeCache cache for video types, map key is tid
VideoUpTypeCache = make(map[int]archive.Type)
)
//RefreshUpTypeAsync refresh in a goroutine
func RefreshUpTypeAsync(tm time.Time) {
go RefreshUpType(tm)
}
//RefreshUpType refresh
func RefreshUpType(tm time.Time) {
var url = conf.Conf.Host.Videoup + "/videoup/types"
var client = bm.NewClient(conf.Conf.HTTPClient)
var result struct {
Code int `json:"code"`
Data map[int]archive.Type `json:"data"`
}
var err = client.Get(context.Background(), url, "", nil, &result)
if err != nil {
log.Error("refresh videoup types fail, err=%v", err)
return
}
log.Info("refresh videoup types ok")
VideoUpTypeCache = result.Data
}
//GetTidName get tid name
func GetTidName(tid int64) string {
info, ok := VideoUpTypeCache[int(tid)]
if !ok {
return ""
}
return info.Name
}
// GetTidNames get tid name
func GetTidNames(tids []int64) (tpNames map[int64]string) {
tpNames = make(map[int64]string, len(tids))
for _, tid := range tids {
info, ok := VideoUpTypeCache[int(tid)]
if !ok {
continue
}
tpNames[tid] = info.Name
}
return
}

View File

@@ -0,0 +1,48 @@
package cache
import (
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestCacheRefreshUpTypeAsync(t *testing.T) {
convey.Convey("RefreshUpTypeAsync", t, func(ctx convey.C) {
var (
tm = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
RefreshUpTypeAsync(tm)
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}
func TestCacheRefreshUpType(t *testing.T) {
convey.Convey("RefreshUpType", t, func(ctx convey.C) {
var (
tm = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
RefreshUpType(tm)
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}
func TestCacheGetTidName(t *testing.T) {
convey.Convey("GetTidName", t, func(ctx convey.C) {
var (
tid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := GetTidName(tid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}

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 = [
"api_test.go",
"cache_test.go",
"creative_test.go",
"dao_test.go",
],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/interface/main/mcn/conf:go_default_library",
"//app/interface/main/mcn/dao/global:go_default_library",
"//app/interface/main/mcn/model/datamodel:go_default_library",
"//app/interface/main/mcn/tool/datacenter:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//vendor/github.com/bouk/monkey:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
"//vendor/gopkg.in/h2non/gock.v1:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"api.go",
"cache.go",
"creative.go",
"dao.go",
],
importpath = "go-common/app/interface/main/mcn/dao/datadao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/mcn/conf:go_default_library",
"//app/interface/main/mcn/dao/cache:go_default_library",
"//app/interface/main/mcn/dao/global:go_default_library",
"//app/interface/main/mcn/model/datamodel:go_default_library",
"//app/interface/main/mcn/model/mcnmodel:go_default_library",
"//app/interface/main/mcn/tool/cache:go_default_library",
"//app/interface/main/mcn/tool/datacenter:go_default_library",
"//app/interface/main/tag/api:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/metadata: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,577 @@
package datadao
import (
"context"
"fmt"
"net/http"
"net/url"
"time"
"go-common/app/interface/main/mcn/dao/cache"
"go-common/app/interface/main/mcn/dao/global"
"go-common/app/interface/main/mcn/model/datamodel"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/app/interface/main/mcn/tool/datacenter"
tagmdl "go-common/app/interface/main/tag/api"
"go-common/library/log"
"go-common/library/sync/errgroup"
)
// const url for api
const (
APIMcnSummary = "http://berserker.bilibili.co/avenger/api/155/query" // 7 see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690
APIIndexInc = "http://berserker.bilibili.co/avenger/api/156/query" // 3.1
APIIndexSource = "http://berserker.bilibili.co/avenger/api/159/query" // 3.2
APIPlaySource = "http://berserker.bilibili.co/avenger/api/161/query" // 3.3
APIMcnFans = "http://berserker.bilibili.co/avenger/api/168/query" // 3.4
APIMcnFansInc = "http://berserker.bilibili.co/avenger/api/171/query" // 3.5
APIMcnFansDec = "http://berserker.bilibili.co/avenger/api/169/query" // 3.6
APIMcnFansAttentionWay = "http://berserker.bilibili.co/avenger/api/170/query" // 3.7
APIMcnFansSex = "http://berserker.bilibili.co/avenger/api/162/query" // 3.8
APIMcnFansAge = "http://berserker.bilibili.co/avenger/api/163/query" // 3.8
APIMcnFansPlayWay = "http://berserker.bilibili.co/avenger/api/164/query" // 3.8
APIMcnFansArea = "http://berserker.bilibili.co/avenger/api/165/query" // 3.9
APIMcnFansType = "http://berserker.bilibili.co/avenger/api/166/query" // 3.10
APIMcnFansTag = "http://berserker.bilibili.co/avenger/api/167/query" // 3.11
)
func (d *Dao) callDataAPI(c context.Context, api string, query *datacenter.Query, res interface{}) (err error) {
var response = &datacenter.Response{
Result: res,
}
if query.Error() != nil {
err = query.Error()
log.Error("query error, err=%s", err)
return
}
var params = url.Values{}
params.Add("query", query.String())
if err = d.Client.Get(c, api, params, response); err != nil {
log.Error("fail to get response, err=%+v", err)
return
}
if response.Code != http.StatusOK {
err = fmt.Errorf("code:%d, msg:%s", response.Code, response.Msg)
return
}
return
}
// GetMcnSummary 7
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-7.mcn获取概要数据
func (d *Dao) GetMcnSummary(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetDataSummaryReply, err error) {
res = new(mcnmodel.McnGetDataSummaryReply)
var tmp []*datamodel.DmConMcnArchiveD
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionLte(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
).Limit(1, 0).Order("log_date desc")
var api = APIMcnSummary
if err = d.callDataAPI(c, api, q, &tmp); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
if len(tmp) > 0 {
res.CopyFromDmConMcnArchiveD(tmp[0])
}
//log.Info("%s query arg(%d,%+v) res(%+v)", api, signID, date, tmp[0])
return
}
//GetMcnSummaryCache GetMcnSummary with cache
func (d *Dao) GetMcnSummaryCache(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetDataSummaryReply, err error) {
res = new(mcnmodel.McnGetDataSummaryReply)
var cache = NewCacheMcnDataSignID(signID, date, res, "McnGetDataSummaryReply", func(c context.Context, signID int64, date time.Time) (res interface{}, err error) {
return d.GetMcnSummary(c, signID, date)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}
// GetIndexInc 3.1
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-3.1.查询MCN增量趋势
func (d *Dao) GetIndexInc(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetIndexIncReply, err error) {
res = new(mcnmodel.McnGetIndexIncReply)
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionLte(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
datacenter.ConditionMapType{"type": datacenter.ConditionIn(tp)},
).Limit(30, 0).Order("log_date desc")
var api = APIIndexInc
if err = d.callDataAPI(c, api, q, &res.Result); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
//log.Info("%s query arg(%d,%+v,%s) res(%+v)", api, signID, date, tp, res.Result[0])
return
}
//GetIndexIncCache GetIndexInc with cache
func (d *Dao) GetIndexIncCache(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetIndexIncReply, err error) {
res = new(mcnmodel.McnGetIndexIncReply)
var cache = NewCacheMcnDataWithTp(signID, date, tp, res, "McnGetIndexIncReply", func(c context.Context, signID int64, date time.Time, tp string) (res interface{}, err error) {
return d.GetIndexInc(c, signID, date, tp)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}
// GetIndexSource 3.2
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-3.2.查询MCN下播放稿件来源所在分区
func (d *Dao) GetIndexSource(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetIndexSourceReply, err error) {
res = new(mcnmodel.McnGetIndexSourceReply)
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionIn(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
datacenter.ConditionMapType{"type": datacenter.ConditionIn(tp)},
)
var api = APIIndexSource
if err = d.callDataAPI(c, api, q, &res.Result); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
var tids []int64
for _, v := range res.Result {
tids = append(tids, v.TypeID)
}
tpNames := cache.GetTidNames(tids)
for _, v := range res.Result {
if tpName, ok := tpNames[v.TypeID]; ok {
v.TypeName = tpName
}
}
//log.Info("%s query arg(%d,%+v,%s) res(%+v)", api, signID, date, tp, res.Result[0])
return
}
//GetIndexSourceCache GetIndexSource with cache
func (d *Dao) GetIndexSourceCache(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetIndexSourceReply, err error) {
res = new(mcnmodel.McnGetIndexSourceReply)
var cache = NewCacheMcnDataWithTp(signID, date, tp, res, "McnGetIndexSourceReply", func(c context.Context, signID int64, date time.Time, tp string) (res interface{}, err error) {
return d.GetIndexSource(c, signID, date, tp)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}
// GetPlaySource 3.3
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-3.3.查询MCN播放设备占比
func (d *Dao) GetPlaySource(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetPlaySourceReply, err error) {
res = new(mcnmodel.McnGetPlaySourceReply)
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionLte(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
).Limit(1, 0).Order("log_date desc")
var api = APIPlaySource
var tmp []*mcnmodel.McnGetPlaySourceReply
if err = d.callDataAPI(c, api, q, &tmp); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
if len(tmp) > 0 {
res = tmp[0]
}
//log.Info("%s query arg(%d,%+v) res(%+v)", api, signID, date, tmp)
return
}
//GetPlaySourceCache GetPlaySource with cache
func (d *Dao) GetPlaySourceCache(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetPlaySourceReply, err error) {
res = new(mcnmodel.McnGetPlaySourceReply)
var cache = NewCacheMcnDataSignID(signID, date, res, "McnGetPlaySourceReply", func(c context.Context, signID int64, date time.Time) (res interface{}, err error) {
return d.GetPlaySource(c, signID, date)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}
// GetMcnFans 3.4
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-3.4.查询MCN粉丝数与活跃度
func (d *Dao) GetMcnFans(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetMcnFansReply, err error) {
res = new(mcnmodel.McnGetMcnFansReply)
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionLte(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
).Limit(1, 0).Order("log_date desc")
var tmp []*mcnmodel.McnGetMcnFansReply
var api = APIMcnFans
if err = d.callDataAPI(c, api, q, &tmp); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
if len(tmp) > 0 {
res = tmp[0]
}
//log.Info("%s query arg(%d,%+v) res(%+v)", api, signID, date, tmp[0])
return
}
//GetMcnFansCache GetMcnFans with cache
func (d *Dao) GetMcnFansCache(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetMcnFansReply, err error) {
res = new(mcnmodel.McnGetMcnFansReply)
var cache = NewCacheMcnDataSignID(signID, date, res, "McnGetMcnFansReply", func(c context.Context, signID int64, date time.Time) (res interface{}, err error) {
return d.GetMcnFans(c, signID, date)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}
// GetMcnFansInc 3.5
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-3.5.查询MCN粉丝按天增量
func (d *Dao) GetMcnFansInc(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetMcnFansIncReply, err error) {
res = new(mcnmodel.McnGetMcnFansIncReply)
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionLte(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
).Limit(30, 0).Order("log_date desc")
var api = APIMcnFansInc
if err = d.callDataAPI(c, api, q, &res.Result); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
//log.Info("%s query arg(%d,%+v) res(%+v)", api, signID, date, res.Result[0])
return
}
//GetMcnFansIncCache GetMcnFansInc with cache
func (d *Dao) GetMcnFansIncCache(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetMcnFansIncReply, err error) {
res = new(mcnmodel.McnGetMcnFansIncReply)
var cache = NewCacheMcnDataSignID(signID, date, res, "McnGetMcnFansIncReply", func(c context.Context, signID int64, date time.Time) (res interface{}, err error) {
return d.GetMcnFansInc(c, signID, date)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}
// GetMcnFansDec 3.6
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-3.6.查询MCN粉丝取关数按天
func (d *Dao) GetMcnFansDec(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetMcnFansDecReply, err error) {
res = new(mcnmodel.McnGetMcnFansDecReply)
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionLte(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
).Limit(30, 0).Order("log_date desc")
var api = APIMcnFansDec
if err = d.callDataAPI(c, api, q, &res.Result); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
//log.Info("%s query arg(%d,%+v) res(%+v)", api, signID, date, res.Result[0])
return
}
//GetMcnFansDecCache GetMcnFansDec with cache
func (d *Dao) GetMcnFansDecCache(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetMcnFansDecReply, err error) {
res = new(mcnmodel.McnGetMcnFansDecReply)
var cache = NewCacheMcnDataSignID(signID, date, res, "McnGetMcnFansDecReply", func(c context.Context, signID int64, date time.Time) (res interface{}, err error) {
return d.GetMcnFansDec(c, signID, date)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}
// GetMcnFansAttentionWay 3.7
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-3.7.查询MCN粉丝关注渠道
func (d *Dao) GetMcnFansAttentionWay(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetMcnFansAttentionWayReply, err error) {
res = new(mcnmodel.McnGetMcnFansAttentionWayReply)
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionLte(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
).Limit(1, 0).Order("log_date desc")
var tmp []*mcnmodel.McnGetMcnFansAttentionWayReply
var api = APIMcnFansAttentionWay
if err = d.callDataAPI(c, api, q, &tmp); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
if len(tmp) > 0 {
res = tmp[0]
}
//log.Info("%s query arg(%d,%+v) res(%+v)", api, signID, date, tmp[0])
return
}
//GetMcnFansAttentionWayCache GetMcnFansAttentionWay with cache
func (d *Dao) GetMcnFansAttentionWayCache(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetMcnFansAttentionWayReply, err error) {
res = new(mcnmodel.McnGetMcnFansAttentionWayReply)
var cache = NewCacheMcnDataSignID(signID, date, res, "McnGetMcnFansAttentionWayReply", func(c context.Context, signID int64, date time.Time) (res interface{}, err error) {
return d.GetMcnFansAttentionWay(c, signID, date)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}
// GetFansBaseFansAttr 3.8
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-3.8.查询MCN粉丝/游客基本属性分析(性别占比 观众年龄 观看途径)
func (d *Dao) GetFansBaseFansAttr(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetBaseFansAttrReply, err error) {
res = new(mcnmodel.McnGetBaseFansAttrReply)
var group, _ = errgroup.WithContext(c)
group.Go(func() (err error) {
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionLte(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
datacenter.ConditionMapType{"type": datacenter.ConditionIn(tp)},
).Limit(1, 0).Order("log_date desc")
var api = APIMcnFansSex
var tmp []*datamodel.DmConMcnFansSexW
if err = d.callDataAPI(context.Background(), api, q, &tmp); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
if len(tmp) > 0 {
res.FansSex = tmp[0]
}
//log.Info("%s query arg(%d,%+v,%s) res(%+v)", api, signID, date, tp, tmp[0])
return
})
group.Go(func() (err error) {
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionLte(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
datacenter.ConditionMapType{"type": datacenter.ConditionIn(tp)},
).Limit(1, 0).Order("log_date desc")
var tmp []*datamodel.DmConMcnFansAgeW
var api = APIMcnFansAge
if err = d.callDataAPI(context.Background(), api, q, &tmp); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
if len(tmp) > 0 {
res.FansAge = tmp[0]
}
//log.Info("%s query arg(%d,%+v,%s) res(%+v)", api, signID, date, tp, tmp[0])
return
})
group.Go(func() (err error) {
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionLte(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
datacenter.ConditionMapType{"type": datacenter.ConditionIn(tp)},
).Limit(1, 0).Order("log_date desc")
var tmp []*datamodel.DmConMcnFansPlayWayW
var api = APIMcnFansPlayWay
if err = d.callDataAPI(context.Background(), api, q, &tmp); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
if len(tmp) > 0 {
res.FansPlayWay = tmp[0]
}
//log.Info("%s query arg(%d,%+v,%s) res(%+v)", api, signID, date, tp, tmp[0])
return
})
err = group.Wait()
if err != nil {
log.Error("fail to get data, err=%v", err)
return
}
return
}
//GetFansBaseFansAttrCache GetFansBaseFansAttr with cache
func (d *Dao) GetFansBaseFansAttrCache(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetBaseFansAttrReply, err error) {
res = new(mcnmodel.McnGetBaseFansAttrReply)
var cache = NewCacheMcnDataWithTp(signID, date, tp, res, "McnGetBaseFansAttrReply", func(c context.Context, signID int64, date time.Time, tp string) (res interface{}, err error) {
return d.GetFansBaseFansAttr(c, signID, date, tp)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}
// GetFansArea 3.9
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-3.9.查询MCN粉丝/游客地区分布分析
func (d *Dao) GetFansArea(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetFansAreaReply, err error) {
res = new(mcnmodel.McnGetFansAreaReply)
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionIn(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
datacenter.ConditionMapType{"type": datacenter.ConditionIn(tp)},
)
var api = APIMcnFansArea
if err = d.callDataAPI(c, api, q, &res.Result); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
//log.Info("%s query arg(%d,%+v,%s) res(%+v)", api, signID, date, tp, res.Result[0])
return
}
//GetFansAreaCache GetFansArea with cache
func (d *Dao) GetFansAreaCache(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetFansAreaReply, err error) {
res = new(mcnmodel.McnGetFansAreaReply)
var cache = NewCacheMcnDataWithTp(signID, date, tp, res, "McnGetFansAreaReply", func(c context.Context, signID int64, date time.Time, tp string) (res interface{}, err error) {
return d.GetFansArea(c, signID, date, tp)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}
// GetFansType 3.10
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-3.10.查询MCN粉丝/游客内容倾向分析
func (d *Dao) GetFansType(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetFansTypeReply, err error) {
res = new(mcnmodel.McnGetFansTypeReply)
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionIn(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
datacenter.ConditionMapType{"type": datacenter.ConditionIn(tp)},
)
var api = APIMcnFansType
if err = d.callDataAPI(c, api, q, &res.Result); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
var tids []int64
for _, v := range res.Result {
tids = append(tids, v.TypeID)
}
tpNames := cache.GetTidNames(tids)
for _, v := range res.Result {
if tpName, ok := tpNames[v.TypeID]; ok {
v.TypeName = tpName
}
}
//log.Info("%s query arg(%d,%+v,%s) res(%+v)", api, signID, date, tp, res.Result[0])
return
}
//GetFansTypeCache GetFansType with cache
func (d *Dao) GetFansTypeCache(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetFansTypeReply, err error) {
res = new(mcnmodel.McnGetFansTypeReply)
var cache = NewCacheMcnDataWithTp(signID, date, tp, res, "McnGetFansTypeReply", func(c context.Context, signID int64, date time.Time, tp string) (res interface{}, err error) {
return d.GetFansType(c, signID, date, tp)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}
// GetFansTag 3.11
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-3.11.查询MCN粉丝/游客标签地图分析
func (d *Dao) GetFansTag(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetFansTagReply, err error) {
res = new(mcnmodel.McnGetFansTagReply)
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionIn(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
datacenter.ConditionMapType{"type": datacenter.ConditionIn(tp)},
)
var api = APIMcnFansTag
if err = d.callDataAPI(c, api, q, &res.Result); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
var tagIDs []int64
for _, v := range res.Result {
tagIDs = append(tagIDs, v.TagID)
}
var tagsReply *tagmdl.TagsReply
if tagsReply, err = global.GetTagGRPC().Tags(c, &tagmdl.TagsReq{Tids: tagIDs}); err != nil {
log.Error("tag(%+v) grpc client fail, err=%s", tagIDs, err)
err = nil
}
for _, v := range res.Result {
if tagsReply == nil {
continue
}
if tag, ok := tagsReply.Tags[v.TagID]; ok {
v.TagName = tag.Name
}
}
//log.Info("%s query arg(%d,%+v,%s) res(%+v)", api, signID, date, tp, res.Result[0])
return
}
//GetFansTagCache GetFansTag with cache
func (d *Dao) GetFansTagCache(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetFansTagReply, err error) {
res = new(mcnmodel.McnGetFansTagReply)
var cache = NewCacheMcnDataWithTp(signID, date, tp, res, "McnGetFansTagReply", func(c context.Context, signID int64, date time.Time, tp string) (res interface{}, err error) {
return d.GetFansTag(c, signID, date, tp)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}

View File

@@ -0,0 +1,448 @@
package datadao
import (
"context"
"go-common/app/interface/main/mcn/tool/datacenter"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
"go-common/app/interface/main/mcn/model/datamodel"
)
func TestDatadaocallDataAPI(t *testing.T) {
convey.Convey("callDataAPI", t, func(ctx convey.C) {
var (
c = context.Background()
api = APIMcnSummary
query = &datacenter.Query{}
res []*datamodel.DmConMcnArchiveD
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.callDataAPI(c, api, query, res)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDatadaoGetMcnSummary(t *testing.T) {
convey.Convey("GetMcnSummary", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetMcnSummary(c, signID, date)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoGetMcnSummaryCache(t *testing.T) {
convey.Convey("GetMcnSummaryCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetMcnSummaryCache(c, signID, date)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoGetIndexInc(t *testing.T) {
convey.Convey("GetIndexInc", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetIndexInc(c, signID, date, tp)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoGetIndexIncCache(t *testing.T) {
convey.Convey("GetIndexIncCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetIndexIncCache(c, signID, date, tp)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoGetIndexSource(t *testing.T) {
convey.Convey("GetIndexSource", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetIndexSource(c, signID, date, tp)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoGetIndexSourceCache(t *testing.T) {
convey.Convey("GetIndexSourceCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetIndexSourceCache(c, signID, date, tp)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoGetPlaySource(t *testing.T) {
convey.Convey("GetPlaySource", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetPlaySource(c, signID, date)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoGetPlaySourceCache(t *testing.T) {
convey.Convey("GetPlaySourceCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetPlaySourceCache(c, signID, date)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoGetMcnFans(t *testing.T) {
convey.Convey("GetMcnFans", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetMcnFans(c, signID, date)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoGetMcnFansCache(t *testing.T) {
convey.Convey("GetMcnFansCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetMcnFansCache(c, signID, date)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoGetMcnFansInc(t *testing.T) {
convey.Convey("GetMcnFansInc", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetMcnFansInc(c, signID, date)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoGetMcnFansIncCache(t *testing.T) {
convey.Convey("GetMcnFansIncCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetMcnFansIncCache(c, signID, date)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoGetMcnFansDec(t *testing.T) {
convey.Convey("GetMcnFansDec", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetMcnFansDec(c, signID, date)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoGetMcnFansDecCache(t *testing.T) {
convey.Convey("GetMcnFansDecCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetMcnFansDecCache(c, signID, date)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoGetMcnFansAttentionWay(t *testing.T) {
convey.Convey("GetMcnFansAttentionWay", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetMcnFansAttentionWay(c, signID, date)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoGetMcnFansAttentionWayCache(t *testing.T) {
convey.Convey("GetMcnFansAttentionWayCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetMcnFansAttentionWayCache(c, signID, date)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoGetFansBaseFansAttr(t *testing.T) {
convey.Convey("GetFansBaseFansAttr", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetFansBaseFansAttr(c, signID, date, tp)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoGetFansBaseFansAttrCache(t *testing.T) {
convey.Convey("GetFansBaseFansAttrCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetFansBaseFansAttrCache(c, signID, date, tp)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoGetFansArea(t *testing.T) {
convey.Convey("GetFansArea", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetFansArea(c, signID, date, tp)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoGetFansAreaCache(t *testing.T) {
convey.Convey("GetFansAreaCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetFansAreaCache(c, signID, date, tp)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoGetFansType(t *testing.T) {
convey.Convey("GetFansType", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetFansType(c, signID, date, tp)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoGetFansTypeCache(t *testing.T) {
convey.Convey("GetFansTypeCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetFansTypeCache(c, signID, date, tp)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoGetFansTag(t *testing.T) {
convey.Convey("GetFansTag", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetFansTag(c, signID, date, tp)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoGetFansTagCache(t *testing.T) {
convey.Convey("GetFansTagCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetFansTagCache(c, signID, date, tp)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,143 @@
package datadao
import (
"context"
"encoding/json"
"fmt"
"go-common/app/interface/main/mcn/conf"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/app/interface/main/mcn/tool/cache"
"time"
)
var (
dateFmt = "20060102"
)
//CacheBaseLoader base loader
type CacheBaseLoader struct {
SignID int64
Date time.Time
Val interface{}
desc string
}
func descHelper(d cache.DataLoader) (key string) {
return d.Desc()
}
func newCacheBaseLoader(signID int64, date time.Time, val interface{}, desc string) CacheBaseLoader {
return CacheBaseLoader{SignID: signID, Date: date, Val: val, desc: desc}
}
//Key cache's key
func (s *CacheBaseLoader) Key() (key string) {
return fmt.Sprintf("%s_%d_%s", descHelper(s), s.SignID, s.Date.Format(dateFmt))
}
//Value cache's value
func (s *CacheBaseLoader) Value() (value interface{}) {
return s.Val
}
//LoadValue need load value
func (s *CacheBaseLoader) LoadValue(c context.Context) (value interface{}, err error) {
panic("implement me")
}
//Expire expiration
func (s *CacheBaseLoader) Expire() time.Duration {
return time.Duration(conf.Conf.Memcache.McnDataCacheExpire)
}
//Desc key desc
func (s *CacheBaseLoader) Desc() string {
return s.desc
}
// -----------------------------------------
//LoadFuncWithTp sign with type
type LoadFuncWithTp func(c context.Context, signID int64, date time.Time, tp string) (res interface{}, err error)
//LoadFuncOnlySign only sign
type LoadFuncOnlySign func(c context.Context, signID int64, date time.Time) (res interface{}, err error)
//NewCacheMcnDataWithTp reply
func NewCacheMcnDataWithTp(signID int64, date time.Time, tp string, val interface{}, desc string, loadFunc LoadFuncWithTp) *cacheMcnDataWithTp {
return &cacheMcnDataWithTp{
CacheBaseLoader: newCacheBaseLoader(signID, date, val, desc),
Tp: tp,
LoadFunc: loadFunc,
}
}
//cacheMcnDataWithTp cache
type cacheMcnDataWithTp struct {
CacheBaseLoader
Tp string
LoadFunc LoadFuncWithTp
}
//Key key
func (s *cacheMcnDataWithTp) Key() (key string) {
return fmt.Sprintf("%s_%d_%s_%s", s.Desc(), s.SignID, s.Date.Format(dateFmt), s.Tp)
}
//LoadValue load
func (s *cacheMcnDataWithTp) LoadValue(c context.Context) (value interface{}, err error) {
value, err = s.LoadFunc(c, s.SignID, s.Date, s.Tp)
if err != nil {
s.Val = nil
return
}
if sorter, ok := value.(mcnmodel.Sorter); ok {
sorter.Sort()
}
// 如果s.Val存在则将结果populate到s.Val上因为外部会直接使用原始传入的s.Val值
if s.Val != nil {
var b, _ = json.Marshal(value)
json.Unmarshal(b, s.Val)
}
return
}
// NewCacheMcnDataSignID 请求只有sign id的情况
func NewCacheMcnDataSignID(signID int64, date time.Time, val interface{}, desc string, loadFunc LoadFuncOnlySign) *cacheMcnDataSignID {
return &cacheMcnDataSignID{
CacheBaseLoader: newCacheBaseLoader(signID, date, val, desc),
LoadFunc: loadFunc,
}
}
type cacheMcnDataSignID struct {
CacheBaseLoader
LoadFunc LoadFuncOnlySign
}
//Key key
func (s *cacheMcnDataSignID) Key() (key string) {
return fmt.Sprintf("%s_%d_%s", s.Desc(), s.SignID, s.Date.Format(dateFmt))
}
//LoadValue load
func (s *cacheMcnDataSignID) LoadValue(c context.Context) (value interface{}, err error) {
value, err = s.LoadFunc(c, s.SignID, s.Date)
if err != nil {
s.Val = nil
return
}
if sorter, ok := value.(mcnmodel.Sorter); ok {
sorter.Sort()
}
// 如果s.Val存在则将结果populate到s.Val上因为外部会直接使用原始传入的s.Val值
if s.Val != nil {
var b, _ = json.Marshal(value)
json.Unmarshal(b, s.Val)
}
return
}

View File

@@ -0,0 +1,203 @@
package datadao
import (
"context"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestDatadaodescHelper(t *testing.T) {
convey.Convey("descHelper", t, func(ctx convey.C) {
var (
d = &CacheBaseLoader{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
key := descHelper(d)
ctx.Convey("Then key should not be nil.", func(ctx convey.C) {
ctx.So(key, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaonewCacheBaseLoader(t *testing.T) {
convey.Convey("newCacheBaseLoader", t, func(ctx convey.C) {
var (
signID = int64(0)
date = time.Now()
val = interface{}(0)
desc = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := newCacheBaseLoader(signID, date, val, desc)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoKeyCacheBaseLoader(t *testing.T) {
var (
c = CacheBaseLoader{}
)
convey.Convey("Key", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
key := c.Key()
ctx.Convey("Then key should not be nil.", func(ctx convey.C) {
ctx.So(key, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoValueCacheBaseLoader(t *testing.T) {
var (
c = CacheBaseLoader{Val: 1}
)
convey.Convey("Value", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
value := c.Value()
ctx.Convey("Then value should not be nil.", func(ctx convey.C) {
ctx.So(value, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoExpireCacheBaseLoader(t *testing.T) {
var (
c = CacheBaseLoader{Val: 1}
)
convey.Convey("Expire", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := c.Expire()
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoDesc(t *testing.T) {
var (
c = CacheBaseLoader{Val: 1}
)
convey.Convey("Desc", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := c.Desc()
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoNewCacheMcnDataWithTp(t *testing.T) {
convey.Convey("NewCacheMcnDataWithTp", t, func(ctx convey.C) {
var (
signID = int64(0)
date = time.Now()
tp = ""
val = interface{}(0)
desc = ""
loadFunc LoadFuncWithTp
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := NewCacheMcnDataWithTp(signID, date, tp, val, desc, loadFunc)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoKeyCacheMcnDataWithTp(t *testing.T) {
var (
s = cacheMcnDataWithTp{CacheBaseLoader: CacheBaseLoader{Val: 1}}
)
convey.Convey("Key", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
key := s.Key()
ctx.Convey("Then key should not be nil.", func(ctx convey.C) {
ctx.So(key, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoLoadValuecacheMcnDataWithTp(t *testing.T) {
convey.Convey("LoadValue", t, func(ctx convey.C) {
var (
c = context.Background()
s = cacheMcnDataWithTp{
CacheBaseLoader: CacheBaseLoader{Val: 1},
LoadFunc: func(c context.Context, signID int64, date time.Time, tp string) (res interface{}, err error) {
return d.GetIndexSource(c, signID, date, tp)
},
}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
value, err := s.LoadValue(c)
ctx.Convey("Then err should be nil.value should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(value, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoNewCacheMcnDataSignID(t *testing.T) {
convey.Convey("NewCacheMcnDataSignID", t, func(ctx convey.C) {
var (
signID = int64(0)
date = time.Now()
val = interface{}(0)
desc = ""
loadFunc LoadFuncOnlySign
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := NewCacheMcnDataSignID(signID, date, val, desc, loadFunc)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoKeycacheMcnDataSignID(t *testing.T) {
var (
s = cacheMcnDataSignID{CacheBaseLoader: CacheBaseLoader{Val: 1}}
)
convey.Convey("Key", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
key := s.Key()
ctx.Convey("Then key should not be nil.", func(ctx convey.C) {
ctx.So(key, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoLoadValuecacheMcnDataSignID(t *testing.T) {
convey.Convey("LoadValue", t, func(ctx convey.C) {
var (
c = context.Background()
s = cacheMcnDataSignID{
CacheBaseLoader: CacheBaseLoader{Val: 1},
LoadFunc: func(c context.Context, signID int64, date time.Time) (res interface{}, err error) {
return d.GetMcnFans(c, signID, date)
},
}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
value, err := s.LoadValue(c)
ctx.Convey("Then err should be nil.value should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(value, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,118 @@
package datadao
import (
"context"
"encoding/json"
"fmt"
"net/url"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
)
// HTTPDataHandle .
func (d *Dao) HTTPDataHandle(c context.Context, params url.Values, key string) (data interface{}, err error) {
var (
uri string
res struct {
Code int `json:"code"`
Data json.RawMessage `json:"data"`
Message string `json:"message"`
}
)
if uri, err = d.getURI(key); err != nil {
return
}
if err = d.bmClient.Get(c, uri, metadata.String(c, metadata.RemoteIP), params, &res); err != nil {
return
}
if res.Code != 0 {
log.Error("d.bmClient.Get(%s,%d)", uri+"?"+params.Encode(), res.Code)
err = ecode.Error(ecode.Int(res.Code), res.Message)
return
}
data = res.Data
return
}
// getURI .
func (d *Dao) getURI(key string) (uri string, err error) {
var (
ok bool
url struct {
host string
uri string
}
_url = map[string]struct {
host string
uri string
}{
"archives": {
uri: "/x/internal/creative/archives",
host: d.Conf.Host.API,
},
"archiveHistoryList": {
uri: "/x/internal/creative/archive/history/list",
host: d.Conf.Host.API,
},
"archiveVideos": {
uri: "/x/internal/creative/archive/videos",
host: d.Conf.Host.API,
},
"dataArchive": {
uri: "/x/internal/creative/data/archive",
host: d.Conf.Host.API,
},
"dataVideoQuit": {
uri: "/x/internal/creative/data/videoquit",
host: d.Conf.Host.API,
},
"danmuDistri": {
uri: "/x/internal/creative/danmu/distri",
host: d.Conf.Host.API,
},
"dataBase": {
uri: "/x/internal/creative/data/base",
host: d.Conf.Host.API,
},
"dataTrend": {
uri: "/x/internal/creative/data/trend",
host: d.Conf.Host.API,
},
"dataAction": {
uri: "/x/internal/creative/data/action",
host: d.Conf.Host.API,
},
"dataFan": {
uri: "/x/internal/creative/data/fan",
host: d.Conf.Host.API,
},
"dataPandect": {
uri: "/x/internal/creative/data/pandect",
host: d.Conf.Host.API,
},
"dataSurvey": {
uri: "/x/internal/creative/data/survey",
host: d.Conf.Host.API,
},
"dataPlaySource": {
uri: "/x/internal/creative/data/playsource",
host: d.Conf.Host.API,
},
"dataPlayAnalysis": {
uri: "/x/internal/creative/data/playanalysis",
host: d.Conf.Host.API,
},
"dataArticleRank": {
uri: "/x/internal/creative/data/article/rank",
host: d.Conf.Host.API,
},
}
)
if url, ok = _url[key]; !ok {
return uri, fmt.Errorf("url(%s) not exist", key)
}
uri = url.host + url.uri
return uri, err
}

View File

@@ -0,0 +1,56 @@
package datadao
import (
"context"
"encoding/json"
"github.com/bouk/monkey"
"go-common/library/net/http/blademaster"
"net/url"
"reflect"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDatadaoHTTPDataHandle(t *testing.T) {
var (
c = context.Background()
params url.Values
key = "archives"
)
convey.Convey("HTTPDataHandle", t, func(ctx convey.C) {
type result struct {
Code int `json:"code"`
Data json.RawMessage `json:"data"`
Message string `json:"message"`
}
res := new(result)
guard := monkey.PatchInstanceMethod(reflect.TypeOf(d.bmClient), "Get", func(_ *blademaster.Client, _ context.Context, _, _ string, _ url.Values, _ interface{}) error {
res.Code = 0
res.Data = json.RawMessage("play")
res.Message = "success"
return nil
})
defer guard.Unpatch()
_, err := d.HTTPDataHandle(c, params, key)
ctx.Convey("Then err should be nil.data should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDatadaogetURI(t *testing.T) {
convey.Convey("getURI", t, func(ctx convey.C) {
var (
key = "archives"
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
uri, err := d.getURI(key)
ctx.Convey("Then err should be nil.uri should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(uri, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,30 @@
package datadao
import (
"go-common/app/interface/main/mcn/conf"
"go-common/app/interface/main/mcn/dao/global"
"go-common/app/interface/main/mcn/tool/cache"
"go-common/app/interface/main/mcn/tool/datacenter"
"go-common/library/cache/memcache"
bm "go-common/library/net/http/blademaster"
)
//Dao data dao
type Dao struct {
Client *datacenter.HttpClient
Conf *conf.Config
mc *memcache.Pool
McWrapper *cache.MCWrapper
bmClient *bm.Client
}
//New .
func New(c *conf.Config) *Dao {
return &Dao{
Client: datacenter.New(c.DataClientConf),
Conf: c,
mc: global.GetMc(),
McWrapper: cache.New(global.GetMc()),
bmClient: global.GetBMClient(),
}
}

View File

@@ -0,0 +1,60 @@
package datadao
import (
"flag"
"net/http"
"os"
"testing"
"go-common/app/interface/main/mcn/conf"
"go-common/app/interface/main/mcn/dao/global"
"gopkg.in/h2non/gock.v1"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.mcn-interface")
flag.Set("conf_token", "49e4671bafbf93059aeb602685052ca0")
flag.Set("tree_id", "58909")
flag.Set("conf_version", "docker-1")
flag.Set("deploy_env", "uat")
flag.Set("conf_host", "config.bilibili.co")
flag.Set("conf_path", "/tmp")
flag.Set("region", "sh")
flag.Set("zone", "sh001")
} else {
flag.Set("conf", "../../cmd/mcn-interface.toml")
}
if os.Getenv("UT_LOCAL_TEST") != "" {
flag.Set("conf", "../../cmd/mcn-interface.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
global.Init(conf.Conf)
d = New(conf.Conf)
d.Client.SetTransport(gock.DefaultTransport)
var result = `{
"code": 200,
"msg": "success",
"result": [ ]
}`
gock.New("http://berserker.bilibili.co/avenger/api").Get("/").AddMatcher(
func(request *http.Request, request2 *gock.Request) (bool, error) {
return true, nil
}).Persist().Reply(200).JSON(result)
defer gock.OffAll()
os.Exit(m.Run())
}
// func httpMock(method, url string) *gock.Request {
// r := gock.New(url)
// r.Method = strings.ToUpper(method)
// return r
// }

View File

@@ -0,0 +1,58 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"account.go",
"resource.go",
],
importpath = "go-common/app/interface/main/mcn/dao/global",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/mcn/conf:go_default_library",
"//app/interface/main/tag/api:go_default_library",
"//app/service/main/account/api:go_default_library",
"//app/service/main/account/model:go_default_library",
"//app/service/main/archive/api:go_default_library",
"//app/service/main/member/api:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//vendor/github.com/pkg/errors: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"],
)
go_test(
name = "go_default_test",
srcs = [
"account_test.go",
"resource_test.go",
],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/interface/main/mcn/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,49 @@
package global
import (
"context"
accgrpc "go-common/app/service/main/account/api"
accmdl "go-common/app/service/main/account/model"
"go-common/library/log"
)
//GetInfo get info
func GetInfo(c context.Context, mid int64) (res *accmdl.Info, err error) {
if mid == 0 {
return
}
var infoReply *accgrpc.InfoReply
if infoReply, err = accGRPC.Info3(c, &accgrpc.MidReq{Mid: mid}); err != nil {
return
}
res = infoReply.Info
return
}
//GetInfos get many infos
func GetInfos(c context.Context, mids []int64) (res map[int64]*accmdl.Info, err error) {
if len(mids) == 0 {
return
}
var infosReply *accgrpc.InfosReply
if infosReply, err = accGRPC.Infos3(c, &accgrpc.MidsReq{Mids: mids}); err != nil {
return
}
res = infosReply.Infos
return
}
//GetName get user name
func GetName(c context.Context, mid int64) (nickname string) {
accInfos, e := GetInfos(c, []int64{mid})
if e == nil && accInfos != nil {
var info, ok = accInfos[mid]
if ok {
nickname = info.Name
}
} else {
log.Warn("get up info fail, err=%s", e)
}
return
}

View File

@@ -0,0 +1,55 @@
package global
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestGlobalGetInfo(t *testing.T) {
convey.Convey("GetInfo", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(417851)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := GetInfo(c, mid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestGlobalGetInfos(t *testing.T) {
convey.Convey("GetInfos", t, func(ctx convey.C) {
var (
c = context.Background()
mid = []int64{417851}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := GetInfos(c, mid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestGlobalGetName(t *testing.T) {
convey.Convey("GetName", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
nickname := GetName(c, mid)
ctx.Convey("Then nickname should not be nil.", func(ctx convey.C) {
ctx.So(nickname, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,74 @@
package global
import (
"go-common/app/interface/main/mcn/conf"
taggrpc "go-common/app/interface/main/tag/api"
accgrpc "go-common/app/service/main/account/api"
arcgrpc "go-common/app/service/main/archive/api"
memgrpc "go-common/app/service/main/member/api"
"go-common/library/cache/memcache"
bm "go-common/library/net/http/blademaster"
"github.com/pkg/errors"
)
var (
accGRPC accgrpc.AccountClient
memGRPC memgrpc.MemberClient
arcGRPC arcgrpc.ArchiveClient
tagGRPC taggrpc.TagRPCClient
mc *memcache.Pool
bmClient *bm.Client
)
// GetAccGRPC .
func GetAccGRPC() accgrpc.AccountClient {
return accGRPC
}
// GetMemGRPC .
func GetMemGRPC() memgrpc.MemberClient {
return memGRPC
}
// GetArcGRPC .
func GetArcGRPC() arcgrpc.ArchiveClient {
return arcGRPC
}
// GetTagGRPC .
func GetTagGRPC() taggrpc.TagRPCClient {
return tagGRPC
}
// GetMc get mc
func GetMc() *memcache.Pool {
return mc
}
// GetBMClient get http client
func GetBMClient() *bm.Client {
return bmClient
}
//Init init global
func Init(c *conf.Config) {
var err error
if accGRPC, err = accgrpc.NewClient(c.GRPCClient.Account); err != nil {
panic(errors.WithMessage(err, "Failed to dial account service"))
}
if memGRPC, err = memgrpc.NewClient(c.GRPCClient.Member); err != nil {
panic(errors.WithMessage(err, "Failed to dial member service"))
}
if arcGRPC, err = arcgrpc.NewClient(c.GRPCClient.Archive); err != nil {
panic(errors.WithMessage(err, "Failed to dial archive service"))
}
if tagGRPC, err = taggrpc.NewClient(c.GRPCClient.Tag); err != nil {
panic(errors.WithMessage(err, "Failed to dial tag service"))
}
mc = memcache.NewPool(&c.Memcache.Config)
bmClient = bm.NewClient(c.HTTPClient)
}

View File

@@ -0,0 +1,69 @@
package global
import (
"flag"
"os"
"testing"
"go-common/app/interface/main/mcn/conf"
"github.com/smartystreets/goconvey/convey"
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.mcn-interface")
flag.Set("conf_token", "49e4671bafbf93059aeb602685052ca0")
flag.Set("tree_id", "58909")
flag.Set("conf_version", "docker-1")
flag.Set("deploy_env", "uat")
flag.Set("conf_host", "config.bilibili.co")
flag.Set("conf_path", "/tmp")
flag.Set("region", "sh")
flag.Set("zone", "sh001")
} else {
flag.Set("conf", "../../cmd/mcn-interface.toml")
}
if os.Getenv("UT_LOCAL_TEST") != "" {
flag.Set("conf", "../../cmd/mcn-interface.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
Init(conf.Conf)
os.Exit(m.Run())
}
func TestGlobalGetAccGRPC(t *testing.T) {
convey.Convey("GetAccGRPC", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := GetAccGRPC()
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestGlobalGetMemGRPC(t *testing.T) {
convey.Convey("GetMemGRPC", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := GetMemGRPC()
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestGlobalGetArcGRPC(t *testing.T) {
convey.Convey("GetArcGRPC", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := GetArcGRPC()
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,354 @@
-- mcn签约表
drop table if exists mcn_sign;
create table mcn_sign (
id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
mcn_mid int(11) unsigned NOT NULL DEFAULT 0 COMMENT 'mcn的mid',
company_name varchar(32) NOT NULL DEFAULT '' COMMENT '企业名称',
company_license_id varchar(32) NOT NULL DEFAULT '' COMMENT '营业执照注册号',
company_license_link varchar(255) NOT NULL DEFAULT '' COMMENT '营业执照链接',
contract_link varchar(255) NOT NULL DEFAULT '' COMMENT '合同链接',
contact_name varchar(16) NOT NULL DEFAULT '' COMMENT '对接人姓名',
contact_title varchar(16) NOT NULL DEFAULT '' COMMENT '对接人职务',
contact_idcard varchar(32) NOT NULL DEFAULT '' COMMENT '对接人身份证号',
contact_phone varchar(16) NOT NULL DEFAULT '' COMMENT '对接人手机号',
begin_date date NOT NULL DEFAULT '0000-00-00' COMMENT '合同开始时间',
end_date date NOT NULL DEFAULT '0000-00-00' COMMENT '合同结束时间',
reject_reason varchar(255) NOT NULL DEFAULT '' COMMENT '驳回理由',
`reject_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '驳回时间',
`pay_expire_state` tinyint(4) NOT NULL DEFAULT '1' COMMENT '付款到期状态:1:未到期 2:即将到期',
state tinyint(4) NOT NULL DEFAULT 0 COMMENT '状态,0未申请1待审核2已驳回10已签约11冷却中12已到期13封禁14清退, 15待开启100移除',
ctime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '添加时间',
mtime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
KEY `ix_mcn_mid` (`mcn_mid`),
KEY `ix_mtime` (`mtime`),
KEY `ix_state` (`state`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='mcn签约表';
-- mcn付款表
drop table if exists mcn_sign_pay;
CREATE TABLE mcn_sign_pay (
id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
mcn_mid int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn mid',
sign_id int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn签约ID',
due_date date NOT NULL DEFAULT '0000-00-00' COMMENT '付款时间',
pay_value BIGINT(20) NOT NULL DEFAULT '0' COMMENT '金额',
state tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态0未支付1已支付100删除',
note varchar(255) NOT NULL DEFAULT '' COMMENT '备注',
ctime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
mtime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (id),
KEY ix_signid (sign_id),
KEY ix_mcn_mid (mcn_mid),
KEY ix_generate_date (due_date),
KEY ix_mtime (mtime)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='付款表';
-- mcn up绑定表
drop table if exists mcn_up;
CREATE TABLE mcn_up (
id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
sign_id int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn签约ID',
mcn_mid int(11) unsigned NOT NULL DEFAULT 0 COMMENT 'mcn的mid',
up_mid int(11) unsigned NOT NULL DEFAULT 0 COMMENT '绑定up的mid',
begin_date date NOT NULL DEFAULT '0000-00-00' COMMENT '合同开始时间',
end_date date NOT NULL DEFAULT '0000-00-00' COMMENT '合同结束时间',
contract_link varchar(255) NOT NULL DEFAULT '' COMMENT '与up合同链接',
up_auth_link varchar(255) NOT NULL DEFAULT '' COMMENT 'up授权协议链接',
reject_reason varchar(255) NOT NULL DEFAULT '' COMMENT '驳回理由',
reject_time timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '驳回时间',
state tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态0未授权1已拒绝2审核中3已驳回10已签约11已冻结12已到期13封禁14已解约100删除',
state_change_time timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '状态变化时间',
ctime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
mtime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (id),
UNIQUE KEY uk_sign_id_mcn_mid_up_mid (sign_id, mcn_mid, up_mid),
KEY ix_up_mid(up_mid),
KEY ix_mtime (mtime)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='mcn绑定up表';
-- 数据相关表
-- 1。mcn整体数据表
-- 2。mcn下各up主数据表
-- 3。Top稿件表
-- 1。mcn整体数据表
drop table if exists mcn_data_summary;
create table mcn_data_summary (
id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
mcn_mid int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn mid',
sign_id int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn签约ID',
up_count int(11) unsigned NOT NULL DEFAULT '0' COMMENT '签约UP主数',
fans_count_accumulate int(11) unsigned NOT NULL DEFAULT '0' COMMENT '累计粉丝量',
fans_count_online int(11) unsigned NOT NULL DEFAULT '0' COMMENT '线上涨粉量',
fans_count_real int(11) unsigned NOT NULL DEFAULT '0' COMMENT '实际涨粉量',
fans_count_cheat_accumulate int(11) unsigned NOT NULL DEFAULT '0' COMMENT '累计作弊粉丝',
fans_count_increase_day int(11) unsigned NOT NULL DEFAULT '0' COMMENT '当日新增粉丝数',
play_count_accumulate int(11) unsigned NOT NULL DEFAULT '0' COMMENT '累计播放数',
play_count_increase_day int(11) unsigned NOT NULL DEFAULT '0' COMMENT '当日新增播放数',
archive_count_accumulate int(11) unsigned NOT NULL DEFAULT '0' COMMENT '累计投稿量',
active_tid smallint(6) unsigned NOT NULL DEFAULT '0' COMMENT '分区,表示某个分区',
generate_date date NOT NULL DEFAULT '0000-00-00' COMMENT '计算日',
data_type tinyint(4) NOT NULL DEFAULT '0' COMMENT '数据类型1按天2按月',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_sign_id_generate_date_active_tid_data_type` (sign_id, generate_date, active_tid, data_type),
KEY ix_mcn_mid (mcn_mid),
KEY `ix_mtime` (`mtime`),
KEY `ix_generate_date` (`generate_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='mcn整体数据';
drop table if exists mcn_data_up_detail;
create table mcn_data_up_detail (
id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
mcn_mid int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn mid',
sign_id int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn签约ID',
up_mid int(11) unsigned NOT NULL DEFAULT '0' COMMENT '签约UP主ID',
fans_count_accumulate int(11) unsigned NOT NULL DEFAULT '0' COMMENT '累计粉丝量',
fans_count_online int(11) unsigned NOT NULL DEFAULT '0' COMMENT '线上涨粉量',
fans_count_real int(11) unsigned NOT NULL DEFAULT '0' COMMENT '实际涨粉量',
fans_count_cheat_accumulate int(11) unsigned NOT NULL DEFAULT '0' COMMENT '累计作弊粉丝',
fans_count_increase_day int(11) unsigned NOT NULL DEFAULT '0' COMMENT '当日新增粉丝数',
play_count_accumulate int(11) unsigned NOT NULL DEFAULT '0' COMMENT '累计播放数',
play_count_increase_day int(11) unsigned NOT NULL DEFAULT '0' COMMENT '当日新增播放数',
archive_count_accumulate int(11) unsigned NOT NULL DEFAULT '0' COMMENT '累计投稿量',
active_tid smallint(6) unsigned NOT NULL DEFAULT '0' COMMENT 'Up所属分区',
generate_date date NOT NULL DEFAULT '0000-00-00' COMMENT '计算日',
data_type tinyint(4) NOT NULL DEFAULT '0' COMMENT '数据类型1按天2按月',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_sign_id_generate_date_data_type_up_mid` (sign_id, generate_date, data_type, up_mid),
KEY ix_mcn_mid (mcn_mid),
KEY `ix_mtime` (`mtime`),
KEY `ix_generate_date` (`generate_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='mcn up整体数据';
-- 2。mcn下各up主数据表
drop table if exists mcn_data_up;
create table mcn_data_up (
id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
mcn_mid int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn mid',
sign_id int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn签约ID',
up_mid int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'up的mid',
data_type tinyint(4) NOT NULL DEFAULT '0' COMMENT '数据类型1累计2昨日3上周4上月',
fans_increase_accumulate int(11) unsigned NOT NULL default '0' COMMENT '粉丝数增涨量',
archive_count int(11) unsigned NOT NULL default '0' COMMENT '投搞量',
play_count int(11) unsigned NOT NULL default '0' COMMENT '播放量',
fans_increase_month int(11) unsigned NOT NULL default '0' COMMENT '近一个月涨粉量',
fans_count int(11) unsigned NOT NULL DEFAULT '0' COMMENT '粉丝总量',
fans_count_active int(11) unsigned NOT NULL DEFAULT '0' COMMENT '活跃粉丝总量',
generate_date date NOT NULL DEFAULT '0000-00-00' COMMENT '计算日',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_sign_id_generate_date_data_type` (sign_id, generate_date, data_type),
KEY ix_mcn_mid (mcn_mid),
KEY ix_up_mid (up_mid),
KEY `ix_mtime` (`mtime`),
KEY `ix_generate_date` (`generate_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='mcn下up数据';
-- alter table mcn_up_test add column state_change_time timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '状态变化时间';
-- 增加字段, fat 1, uat 1, prod 1
alter table mcn_data_summary add column fans_count_real_accumulate bigint(20) NOT NULL DEFAULT '0' COMMENT '累计实际涨粉量';
alter table mcn_data_summary add column fans_count_online_accumulate bigint(20) NOT NULL DEFAULT '0' COMMENT '累计线上涨粉量';
alter table mcn_data_summary add column archive_count_day int(11) NOT NULL DEFAULT '0' COMMENT '当日新增投稿量';
alter table mcn_data_up_detail add column fans_count_real_accumulate bigint(20) NOT NULL DEFAULT '0' COMMENT '累计实际涨粉量';
alter table mcn_data_up_detail add column fans_count_online_accumulate bigint(20) NOT NULL DEFAULT '0' COMMENT '累计线上涨粉量';
alter table mcn_data_up_detail add column archive_count_day int(11) NOT NULL DEFAULT '0' COMMENT '当日新增投稿量';
-- 修改数据字段类型去掉unsigned 修改播放相关的为bigint, fat 1, uat 1, prod 1
alter table mcn_data_summary modify column fans_count_accumulate int(11) NOT NULL DEFAULT '0' COMMENT '累计粉丝量';
alter table mcn_data_summary modify column fans_count_online int(11) NOT NULL DEFAULT '0' COMMENT '线上涨粉量';
alter table mcn_data_summary modify column fans_count_real int(11) NOT NULL DEFAULT '0' COMMENT '实际涨粉量';
alter table mcn_data_summary modify column fans_count_cheat_accumulate int(11) NOT NULL DEFAULT '0' COMMENT '累计作弊粉丝';
alter table mcn_data_summary modify column fans_count_increase_day int(11) NOT NULL DEFAULT '0' COMMENT '当日新增粉丝数';
alter table mcn_data_summary modify column play_count_accumulate int(11) NOT NULL DEFAULT '0' COMMENT '累计播放数';
alter table mcn_data_summary modify column play_count_increase_day int(11) NOT NULL DEFAULT '0' COMMENT '当日新增播放数';
alter table mcn_data_summary modify column archive_count_accumulate int(11) NOT NULL DEFAULT '0' COMMENT '累计投稿量';
alter table mcn_data_up_detail modify column fans_count_accumulate int(11) NOT NULL DEFAULT '0' COMMENT '累计粉丝量';
alter table mcn_data_up_detail modify column fans_count_online int(11) NOT NULL DEFAULT '0' COMMENT '线上涨粉量';
alter table mcn_data_up_detail modify column fans_count_real int(11) NOT NULL DEFAULT '0' COMMENT '实际涨粉量';
alter table mcn_data_up_detail modify column fans_count_cheat_accumulate int(11) NOT NULL DEFAULT '0' COMMENT '累计作弊粉丝';
alter table mcn_data_up_detail modify column fans_count_increase_day int(11) NOT NULL DEFAULT '0' COMMENT '当日新增粉丝数';
alter table mcn_data_up_detail modify column play_count_accumulate int(11) NOT NULL DEFAULT '0' COMMENT '累计播放数';
alter table mcn_data_up_detail modify column play_count_increase_day int(11) NOT NULL DEFAULT '0' COMMENT '当日新增播放数';
alter table mcn_data_up_detail modify column archive_count_accumulate int(11) NOT NULL DEFAULT '0' COMMENT '累计投稿量';
alter table mcn_data_up modify column fans_increase_accumulate int(11) NOT NULL default '0' COMMENT '粉丝数增涨量';
alter table mcn_data_up modify column archive_count int(11) NOT NULL default '0' COMMENT '投搞量';
alter table mcn_data_up modify column play_count bigint(20) NOT NULL default '0' COMMENT '播放量';
alter table mcn_data_up modify column fans_increase_month int(11) NOT NULL default '0' COMMENT '近一个月涨粉量';
alter table mcn_data_up modify column fans_count int(11) NOT NULL DEFAULT '0' COMMENT '粉丝总量';
alter table mcn_data_up modify column fans_count_active int(11) NOT NULL DEFAULT '0' COMMENT '活跃粉丝总量';
-- fat 1, uat 1, prod 1
alter table mcn_data_summary modify column play_count_accumulate bigint(20) NOT NULL DEFAULT '0' COMMENT '累计播放数';
alter table mcn_data_summary modify column play_count_increase_day bigint(20) NOT NULL DEFAULT '0' COMMENT '当日/月新增播放数';
alter table mcn_data_up_detail modify column play_count_accumulate bigint(20) NOT NULL DEFAULT '0' COMMENT '累计播放数';
alter table mcn_data_up_detail modify column play_count_increase_day bigint(20) NOT NULL DEFAULT '0' COMMENT '当日/月新增播放数';
alter table mcn_sign modify column reject_time datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '驳回时间';
-- fat 1, uat 1, prod 1, 增加时间上的索引
create index ix_end_date on mcn_sign (end_date);
create index ix_begin_date on mcn_sign (begin_date);
create index ix_end_date on mcn_up (end_date);
create index ix_begin_date on mcn_up (begin_date);
--------- 2期
-- fat 1, uat 1, prod 1, 增加表
alter table mcn_up add column up_type tinyint(4) not null default '0' comment '用户类型0为站内1为站外';
alter table mcn_up add column site_link varchar(255) not null default '' comment 'up主站外账号链接';
-- mcn_data_import_up: table
CREATE TABLE `mcn_data_import_up` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
`mcn_mid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn mid',
`sign_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn签约ID',
`up_mid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'UP主 mid',
`standard_fans_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '达标粉丝数类型, 1: 1w粉丝',
`standard_fans_date` int(11) NOT NULL DEFAULT '0' COMMENT '达到粉丝数门槛花费的时间,秒',
`standard_archive_count` int(11) NOT NULL DEFAULT '0' COMMENT '达标时投稿量',
`standard_fans_count` int(11) NOT NULL DEFAULT '0' COMMENT '达标时粉丝数',
`is_reward` int(11) NOT NULL DEFAULT '0' COMMENT '奖励情况 0:未奖励 1:已奖励',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_sign_id_mid_type` (`sign_id`,`up_mid`,`standard_fans_type`),
KEY `ix_mtime` (`mtime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='引入账号数据表';
-- mcn_up_recommend_pool: table
CREATE TABLE `mcn_up_recommend_pool` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
`up_mid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'up mid',
`fans_count` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '粉丝量',
`fans_count_increase_month` int(11) NOT NULL DEFAULT '0' COMMENT '本月粉丝增长量',
`archive_count` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '总稿件数',
`play_count_accumulate` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '累积播放量',
`play_count_average` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '稿均播放量',
`active_tid` smallint(6) unsigned NOT NULL DEFAULT '0' COMMENT '分区,表示某个分区',
`last_archive_time` datetime NOT NULL DEFAULT '1970-01-01 08:00:00' COMMENT '最近投稿时间',
`state` tinyint(4) unsigned NOT NULL DEFAULT '1' COMMENT '推荐池状态: 1:未推荐 2:推荐 3:禁止推荐 100:移除',
`source` tinyint(4) unsigned NOT NULL DEFAULT '1' COMMENT '推荐池来源: 1:自动添加(大数据) 2:手动添加',
`generate_time` datetime NOT NULL DEFAULT '1970-01-01 08:00:00' COMMENT '大数据更新时间',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_up_mid` (`up_mid`),
KEY `ix_state` (`state`),
KEY `ix_active_tid` (`active_tid`),
KEY `ix_fans_count` (`fans_count`),
KEY `ix_play_count_accumulate` (`play_count_accumulate`),
KEY `ix_play_count_average` (`play_count_average`),
KEY `ix_fans_count_increase_month` (`fans_count_increase_month`),
KEY `ix_source` (`source`),
KEY `ix_generate_time` (`generate_time`),
KEY `ix_mtime` (`mtime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='mcn-up主推荐池';
-- mcn_up_recommend_source: table
CREATE TABLE `mcn_up_recommend_source` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
`up_mid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'up mid',
`fans_count` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '粉丝量',
`fans_count_increase_month` int(11) NOT NULL DEFAULT '0' COMMENT '本月粉丝增长量',
`archive_count` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '总稿件数',
`play_count_accumulate` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '累积播放量',
`play_count_average` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '稿均播放量',
`active_tid` smallint(6) unsigned NOT NULL DEFAULT '0' COMMENT '分区,表示某个分区',
`last_archive_time` datetime NOT NULL DEFAULT '1970-01-01 08:00:00' COMMENT '最近投稿时间',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`id`),
KEY `ix_up_mid` (`up_mid`),
KEY `ix_mtime` (`mtime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='mcn-up主推荐池的来源(大数据提供)';
-- fat 1, uat 1, prod 0
-- 1。涨粉量排名
create table mcn_rank_up_fans (
id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
mcn_mid int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn mid',
sign_id int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn签约ID',
up_mid int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'up的mid',
value1 int(11) NOT NULL default '0' COMMENT '数据1',
value2 int(11) NOT NULL default '0' COMMENT '数据2',
active_tid smallint(6) unsigned NOT NULL DEFAULT '0' COMMENT '分区,表示某个分区',
data_type tinyint(4) NOT NULL DEFAULT '0' COMMENT '数据类型1累计总榜2昨日3上周4上月5活跃粉丝(累计)',
generate_date date NOT NULL DEFAULT '0000-00-00' COMMENT '计算日',
ctime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
mtime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_sign_id_generate_date_data_type_up_mid` (sign_id, generate_date, data_type, up_mid),
KEY ix_mcn_mid (mcn_mid),
KEY ix_up_mid (up_mid),
KEY `ix_mtime` (`mtime`),
KEY `ix_generate_date` (`generate_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='mcn下up涨粉量排名';
-- 2。Top稿件表
create table mcn_rank_archive_likes (
id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
mcn_mid int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn mid',
sign_id int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn签约ID',
up_mid int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'up的mid',
archive_id bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '稿件id',
like_count bigint(20) NOT NULL DEFAULT '0' COMMENT '日/周/月新增点赞数根据data_type统计',
data_type tinyint(4) NOT NULL DEFAULT '0' COMMENT '数据类型1累计2昨日3上周4上月',
tid smallint(6) unsigned NOT NULL DEFAULT '0' COMMENT '分区ID',
generate_date date NOT NULL DEFAULT '0000-00-00' COMMENT '计算日',
ctime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
mtime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`id`),
KEY ix_mcn_mid (mcn_mid),
KEY `ix_mtime` (`mtime`),
KEY `ix_generate_date` (`generate_date`),
UNIQUE KEY `uk_sign_id_generate_date_data_type_archive_id` (sign_id, generate_date, data_type, archive_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='mcn下top稿件表';
-- mcn_data_up_cheat: table
CREATE TABLE `mcn_data_up_cheat` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`mcn_mid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn mid',
`sign_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn签约ID',
`up_mid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'up主 mid',
`generate_date` date NOT NULL DEFAULT '0000-00-00' COMMENT '计算日',
`fans_count_cheat_increase_day` int(11) NOT NULL DEFAULT '0' COMMENT '新增作弊粉丝量',
`fans_count_cheat_cleaned_accumulate` int(11) NOT NULL DEFAULT '0' COMMENT '已清除粉丝量',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_up_mid_sign_id_generate_date` (`up_mid`,`sign_id`,`generate_date`),
KEY `ix_mcn_mid` (`mcn_mid`),
KEY `ix_mtime` (`mtime`),
KEY `ix_generate_date` (`generate_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='作弊筛选详情表'
;
-- fat 1, uat 1, prod 0
ALTER TABLE mcn_rank_archive_likes CHANGE archive_id avid bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '稿件id';
ALTER TABLE `bilibili_upcrm`.`mcn_data_up_cheat`
ADD COLUMN `fans_count_cheat_accumulate` int(11) NOT NULL DEFAULT '0' COMMENT '累计作弊粉丝',
ADD COLUMN `fans_count_accumulate` int(11) NOT NULL DEFAULT '0' COMMENT '实际粉丝量';
-- fat 1, uat 1, prod 0
ALTER TABLE mcn_up ADD COLUMN confirm_time timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'up确认时间';
---------------
alter table mcn_sign add permission int(11) unsigned default '1' not null comment '权限列表-属性位';
alter table mcn_up
add permission int(11) unsigned default '1' not null comment '权限列表-属性位',
add publication_price bigint default '0' not null comment '刊例价(千分位*1000)';

View File

@@ -0,0 +1,254 @@
#投稿数及昨日增量
CREATE TABLE `dm_con_mcn_archive_d` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`up_all` int(11) NOT NULL DEFAULT '0' COMMENT '绑定up主数',
`archive_all` bigint(20) NOT NULL DEFAULT '0' COMMENT '总投稿数',
`archive_inc` bigint(20) NOT NULL DEFAULT '0' COMMENT '投稿数昨日增量',
`play_all` bigint(20) NOT NULL DEFAULT '0' COMMENT '总播放数',
`play_inc` bigint(20) NOT NULL DEFAULT '0' COMMENT '播放数昨日增量',
`danmu_all` bigint(20) NOT NULL DEFAULT '0' COMMENT '总弹幕数',
`danmu_inc` bigint(20) NOT NULL DEFAULT '0' COMMENT '弹幕数昨日增量',
`reply_all` bigint(20) NOT NULL DEFAULT '0' COMMENT '总评论数',
`reply_inc` bigint(20) NOT NULL DEFAULT '0' COMMENT '评论数昨日增量',
`share_all` bigint(20) NOT NULL DEFAULT '0' COMMENT '总分享数',
`share_inc` bigint(20) NOT NULL DEFAULT '0' COMMENT '分享数昨日增量',
`coin_all` bigint(20) NOT NULL DEFAULT '0' COMMENT '总硬币数',
`coin_inc` bigint(20) NOT NULL DEFAULT '0' COMMENT '硬币数昨日增量',
`fav_all` bigint(20) NOT NULL DEFAULT '0' COMMENT '总收藏数',
`fav_inc` bigint(20) NOT NULL DEFAULT '0' COMMENT '收藏数昨日增量',
`like_all` bigint(20) NOT NULL DEFAULT '0' COMMENT '总点赞数',
`like_inc` bigint(20) NOT NULL DEFAULT '0' COMMENT '点赞数昨日增量',
`fans_all` bigint(20) NOT NULL DEFAULT '0' COMMENT '总粉丝数',
`fans_inc` bigint(20) NOT NULL DEFAULT '0' COMMENT '昨日粉丝增量',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='mcn稿件汇总指标';
#播放/弹幕/评论/分享/硬币/收藏/点赞数每日增量
CREATE TABLE `dm_con_mcn_index_inc_d` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`value` bigint(20) NOT NULL DEFAULT '0' COMMENT '当日播放/弹幕/评论/分享/硬币/收藏/点赞数',
`type` varchar(20) NOT NULL COMMENT '分区类型play、danmu、reply、share、coin、fav、like',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`,`type`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='播放/弹幕/评论/分享/硬币/收藏/点赞数每日增量';
#mcn播放/弹幕/评论/分享/硬币/收藏/点赞来源分区
CREATE TABLE `dm_con_mcn_index_source_d` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`type_id` int(11) NOT NULL COMMENT '一级分区ID',
`rank` int(11) NOT NULL COMMENT '排名',
`value` bigint(20) NOT NULL DEFAULT '0' COMMENT '一级分区',
`type` varchar(20) NOT NULL COMMENT '分区类型play、danmu、reply、share、coin、fav、like',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`,`type_id`,`type`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='mcn播放/弹幕/评论/分享/硬币/收藏/点赞来源分区';
#mcn稿件播放来源占比
CREATE TABLE `dm_con_mcn_play_source_d` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`iphone` bigint(20) NOT NULL COMMENT 'iphone播放量',
`andriod` bigint(20) NOT NULL COMMENT 'andriod播放量',
`pc` bigint(20) NOT NULL COMMENT 'pc播放量',
`h5` bigint(20) NOT NULL COMMENT 'h5播放量',
`other` bigint(20) NOT NULL COMMENT 'other播放量',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='mcn稿件播放来源占比';
#游客/粉丝性别占比
CREATE TABLE `dm_con_mcn_fans_sex_w` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`male` bigint(20) NOT NULL COMMENT '男性人数',
`female` bigint(20) NOT NULL COMMENT '女性人数',
`type` varchar(20) NOT NULL COMMENT '粉丝类型guest、fans',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`,`type`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='游客/粉丝性别占比';
#游客/粉丝年龄分布
CREATE TABLE `dm_con_mcn_fans_age_w` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`a` bigint(20) NOT NULL COMMENT '0-16岁人数',
`b` bigint(20) NOT NULL COMMENT '16-25岁人数',
`c` bigint(20) NOT NULL COMMENT '25-40岁人数',
`d` bigint(20) NOT NULL COMMENT '40岁以上人数',
`type` varchar(20) NOT NULL COMMENT '粉丝类型guest、fans',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`,`type`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='游客/粉丝年龄分布';
#游客/粉丝观看途径
CREATE TABLE `dm_con_mcn_fans_play_way_w` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`app` bigint(20) NOT NULL COMMENT 'app观看人数',
`pc` bigint(20) NOT NULL COMMENT 'pc观看人数',
`outside` bigint(20) NOT NULL COMMENT '站外观看人数',
`other` bigint(20) NOT NULL COMMENT '其他观看人数',
`type` varchar(20) NOT NULL COMMENT '粉丝类型guest、fans',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`,`type`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='游客/粉丝观看途径';
#游客/粉丝地区分布
CREATE TABLE `dm_con_mcn_fans_area_w` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`province` varchar(200) NOT NULL COMMENT '省份',
`user` bigint(20) NOT NULL COMMENT '人数',
`type` varchar(20) NOT NULL COMMENT '粉丝类型guest、fans',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`,`province`,`type`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='游客/粉丝地区分布';
#游客/粉丝倾向分布
CREATE TABLE `dm_con_mcn_fans_type_w` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`type_id` int(11) NOT NULL COMMENT '二级分区ID',
`user` bigint(20) NOT NULL COMMENT '人数',
`type` varchar(20) NOT NULL COMMENT '粉丝类型guest、fans',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`,`type_id`,`type`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='游客/粉丝倾向分布';
#游客/粉丝标签地图分布
CREATE TABLE `dm_con_mcn_fans_tag_w` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`tag_id` int(11) NOT NULL COMMENT '标签ID',
`user` bigint(20) NOT NULL COMMENT '人数',
`type` varchar(20) NOT NULL COMMENT '粉丝类型guest、fans',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`,`tag_id`,`type`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='游客/粉丝标签地图分布';
#mcn粉丝数相关
CREATE TABLE `dm_con_mcn_fans_d` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`fans_all` bigint(20) NOT NULL COMMENT 'mcn总粉丝数',
`fans_inc` bigint(20) NOT NULL COMMENT 'mcn粉丝数昨日增量',
`act_fans` bigint(20) NOT NULL COMMENT 'mcn活跃粉丝数',
`fans_dec_all` bigint(20) NOT NULL COMMENT 'mcn取关粉丝总数',
`fans_dec` bigint(20) NOT NULL COMMENT 'mcn昨日取关粉丝数',
`view_fans_rate` float(3,2) NOT NULL COMMENT '观看活跃度',
`act_fans_rate` float(3,2) NOT NULL COMMENT '互动活跃度',
`reply_fans_rate` float(3,2) NOT NULL COMMENT '评论活跃度',
`danmu_fans_rate` float(3,2) NOT NULL COMMENT '弹幕活跃度',
`coin_fans_rate` float(3,2) NOT NULL COMMENT '投币活跃度',
`like_fans_rate` float(3,2) NOT NULL COMMENT '点赞活跃度',
`fav_fans_rate` float(3,2) NOT NULL COMMENT '收藏活跃度',
`share_fans_rate` float(3,2) NOT NULL COMMENT '分享活跃度',
`live_gift_fans_rate` float(3,2) NOT NULL COMMENT '直播礼物活跃度',
`live_danmu_fans_rate` float(3,2) NOT NULL COMMENT '直播弹幕活跃度',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='mcn粉丝数相关';
#mcn粉丝按天增量
CREATE TABLE `dm_con_mcn_fans_inc_d` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`fans_inc` bigint(20) NOT NULL COMMENT '当日新增粉丝数',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='mcn粉丝按天增量';
#mcn粉丝按天取关数
CREATE TABLE `dm_con_mcn_fans_dec_d` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`fans_dec` bigint(20) NOT NULL COMMENT '当日取关粉丝数',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='mcn粉丝按天取关数';
#mcn粉丝关注渠道
CREATE TABLE `dm_con_mcn_fans_attention_way_d` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`homepage` bigint(20) NOT NULL COMMENT '主站个人空间关注用户数',
`video` bigint(20) NOT NULL COMMENT '主站视频页关注用户数',
`article` bigint(20) NOT NULL COMMENT '专栏关注用户数',
`music` bigint(20) NOT NULL COMMENT '音频关注用户数',
`other` bigint(20) NOT NULL COMMENT '其他关注用户数',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='mcn粉丝关注渠道';

View File

@@ -0,0 +1,87 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"crm.go",
"dao.cache.go",
"dao.go",
"data.go",
"mc.cache.go",
"memcahe.go",
"rank.go",
"recommend_pool.go",
"sign.go",
],
importpath = "go-common/app/interface/main/mcn/dao/mcndao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/mcn/model:go_default_library",
"//app/admin/main/up/util:go_default_library",
"//app/admin/main/up/util/mathutil:go_default_library",
"//app/interface/main/mcn/conf:go_default_library",
"//app/interface/main/mcn/dao/cache:go_default_library",
"//app/interface/main/mcn/dao/global:go_default_library",
"//app/interface/main/mcn/model:go_default_library",
"//app/interface/main/mcn/model/mcnmodel:go_default_library",
"//app/interface/main/mcn/tool/validate:go_default_library",
"//app/service/main/archive/api:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/stat/prom:go_default_library",
"//library/sync/pipeline/fanout:go_default_library",
"//vendor/github.com/bluele/gcache:go_default_library",
"//vendor/github.com/jinzhu/gorm:go_default_library",
"//vendor/github.com/pkg/errors: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"],
)
go_test(
name = "go_default_test",
srcs = [
"crm_test.go",
"dao.cache_test.go",
"dao_test.go",
"data_test.go",
"mc.cache_test.go",
"memcahe_test.go",
"rank_test.go",
"recommend_pool_test.go",
"sign_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/mcn/conf:go_default_library",
"//app/interface/main/mcn/dao/global:go_default_library",
"//app/interface/main/mcn/model:go_default_library",
"//app/interface/main/mcn/model/mcnmodel:go_default_library",
"//library/ecode:go_default_library",
"//vendor/github.com/bluele/gcache:go_default_library",
"//vendor/github.com/jinzhu/gorm:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,38 @@
package mcndao
import (
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/library/log"
)
//GetActiveTid get tid from crm database
func (d *Dao) GetActiveTid(mids []int64) (res map[int64]int64, err error) {
var infoList []*mcnmodel.UpBaseInfo
err = d.mcndb.Select("mid, active_tid").Where("mid in (?) and business_type=1", mids).Find(&infoList).Error
if err != nil {
log.Error("fail to get active_tid from crm, err=%s", err)
return
}
res = make(map[int64]int64, len(infoList))
for _, v := range infoList {
res[v.Mid] = v.ActiveTid
}
return
}
//GetUpBaseInfo get up base info from crm database
func (d *Dao) GetUpBaseInfo(fields string, mids []int64) (res map[int64]*mcnmodel.UpBaseInfo, err error) {
var infoList []*mcnmodel.UpBaseInfo
err = d.mcndb.Select(fields).Where("mid in (?) and business_type=1", mids).Find(&infoList).Error
if err != nil {
log.Error("fail to get active_tid from crm, err=%s", err)
return
}
res = make(map[int64]*mcnmodel.UpBaseInfo, len(infoList))
for _, v := range infoList {
res[v.Mid] = v
}
return
}

View File

@@ -0,0 +1,22 @@
package mcndao
import (
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestMcndaoGetActiveTid(t *testing.T) {
convey.Convey("GetActiveTid", t, func(ctx convey.C) {
var (
mids = []int64{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.GetActiveTid(mids)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,133 @@
// Code generated by $GOPATH/src/go-common/app/tool/cache/gen. DO NOT EDIT.
/*
Package mcndao is a generated cache proxy package.
It is generated from:
type _cache interface {
//cache: -nullcache=&mcnmodel.McnSign{ID:-1} -check_null_code=$!=nil&&$.ID==-1
McnSign(c context.Context, mcnmid int64) (up *mcnmodel.McnSign, err error)
//cache: -nullcache=&mcnmodel.McnGetDataSummaryReply{IsNull:true} -check_null_code=$!=nil&&$.IsNull
McnDataSummary(c context.Context, mcnmid int64, generateDate time.Time) (res *mcnmodel.McnGetDataSummaryReply, err error)
//cache: -nullcache=&mcnmodel.UpPermissionCache{IsNull:true} -check_null_code=$!=nil&&$.IsNull
UpPermission(c context.Context, signID int64, mid int64) (data *mcnmodel.UpPermissionCache, err error)
}
*/
package mcndao
import (
"context"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/library/stat/prom"
"time"
)
var _ _cache
// McnSign get data from cache if miss will call source method, then add to cache.
func (d *Dao) McnSign(c context.Context, id int64) (res *mcnmodel.McnSign, err error) {
addCache := true
res, err = d.CacheMcnSign(c, id)
if err != nil {
addCache = false
err = nil
}
defer func() {
if res != nil && res.ID == -1 {
res = nil
}
}()
if res != nil {
prom.CacheHit.Incr("McnSign")
return
}
prom.CacheMiss.Incr("McnSign")
res, err = d.RawMcnSign(c, id)
if err != nil {
return
}
miss := res
if miss == nil {
miss = &mcnmodel.McnSign{ID: -1}
}
if !addCache {
return
}
d.cache.Do(c, func(c context.Context) {
d.AddCacheMcnSign(c, id, miss)
})
return
}
// McnDataSummary get data from cache if miss will call source method, then add to cache.
func (d *Dao) McnDataSummary(c context.Context, id int64, generateDate time.Time) (res *mcnmodel.McnGetDataSummaryReply, err error) {
addCache := true
res, err = d.CacheMcnDataSummary(c, id, generateDate)
if err != nil {
addCache = false
err = nil
}
defer func() {
if res != nil && res.IsNull {
res = nil
}
}()
if res != nil {
prom.CacheHit.Incr("McnDataSummary")
return
}
prom.CacheMiss.Incr("McnDataSummary")
res, err = d.RawMcnDataSummary(c, id, generateDate)
if err != nil {
return
}
miss := res
if miss == nil {
miss = &mcnmodel.McnGetDataSummaryReply{IsNull: true}
}
if !addCache {
return
}
d.cache.Do(c, func(c context.Context) {
d.AddCacheMcnDataSummary(c, id, miss, generateDate)
})
return
}
// UpPermission get data from cache if miss will call source method, then add to cache.
func (d *Dao) UpPermission(c context.Context, id int64, mid int64) (res *mcnmodel.UpPermissionCache, err error) {
addCache := true
res, err = d.CacheUpPermission(c, id, mid)
if err != nil {
addCache = false
err = nil
}
defer func() {
if res != nil && res.IsNull {
res = nil
}
}()
if res != nil {
prom.CacheHit.Incr("UpPermission")
return
}
prom.CacheMiss.Incr("UpPermission")
res, err = d.RawUpPermission(c, id, mid)
if err != nil {
return
}
miss := res
if miss == nil {
miss = &mcnmodel.UpPermissionCache{IsNull: true}
}
if !addCache {
return
}
d.cache.Do(c, func(c context.Context) {
d.AddCacheUpPermission(c, id, miss, mid)
})
return
}

View File

@@ -0,0 +1,42 @@
package mcndao
import (
"context"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestMcndaoMcnSign(t *testing.T) {
convey.Convey("McnSign", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.McnSign(c, id)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestMcndaoMcnDataSummary(t *testing.T) {
convey.Convey("McnDataSummary", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
generateDate = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.McnDataSummary(c, id, generateDate)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,74 @@
package mcndao
import (
"context"
"fmt"
"runtime"
"time"
"go-common/app/interface/main/mcn/conf"
"go-common/app/interface/main/mcn/dao/global"
"go-common/library/cache/memcache"
"go-common/library/sync/pipeline/fanout"
"github.com/bluele/gcache"
"github.com/jinzhu/gorm"
)
// Dao dao
type Dao struct {
c *conf.Config
mc *memcache.Pool
mcndb *gorm.DB
//cache tool
cache *fanout.Fanout
mcnSignExpire int32
mcnDataExpire int32
localcache gcache.Cache
}
// New init mysql db
func New(c *conf.Config, localcache gcache.Cache) (dao *Dao) {
dao = &Dao{
c: c,
mc: global.GetMc(),
// cache worker
cache: fanout.New("cache", fanout.Worker(runtime.NumCPU()), fanout.Buffer(1024)),
mcnSignExpire: int32(time.Duration(c.Memcache.McnSignCacheExpire) / time.Second),
mcnDataExpire: int32(time.Duration(c.Memcache.McnDataCacheExpire) / time.Second),
localcache: localcache,
}
if localcache == nil {
dao.localcache = gcache.New(c.RankCache.Size).Simple().Build()
}
if dao.mcnDataExpire == 0 {
dao.mcnDataExpire = 3600
}
if dao.mcnSignExpire == 0 {
dao.mcnSignExpire = 3600
}
var err error
dao.mcndb, err = gorm.Open("mysql", c.MCNorm.DSN)
if err != nil {
panic(fmt.Errorf("db connect fail, err=%s", err))
}
dao.mcndb.LogMode(c.Other.Debug)
return
}
// Close close the resource.
func (d *Dao) Close() {
d.cache.Close()
d.mc.Close()
d.mcndb.Close()
}
// Ping dao ping
func (d *Dao) Ping(c context.Context) error {
return nil
}
//GetMcnDB get mcn db
func (d *Dao) GetMcnDB() *gorm.DB {
return d.mcndb
}

View File

@@ -0,0 +1,43 @@
package mcndao
import (
"flag"
"os"
"testing"
"go-common/app/interface/main/mcn/conf"
"github.com/bluele/gcache"
"go-common/app/interface/main/mcn/dao/global"
)
var (
d *Dao
localcache = gcache.New(1024).Simple().Build()
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.mcn-interface")
flag.Set("conf_token", "49e4671bafbf93059aeb602685052ca0")
flag.Set("tree_id", "58909")
flag.Set("conf_version", "docker-1")
flag.Set("deploy_env", "uat")
flag.Set("conf_host", "config.bilibili.co")
flag.Set("conf_path", "/tmp")
flag.Set("region", "sh")
flag.Set("zone", "sh001")
} else {
flag.Set("conf", "../../cmd/mcn-interface.toml")
}
if os.Getenv("UT_LOCAL_TEST") != "" {
flag.Set("conf", "../../cmd/mcn-interface.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
global.Init(conf.Conf)
d = New(conf.Conf, localcache)
os.Exit(m.Run())
}

View File

@@ -0,0 +1,145 @@
package mcndao
import (
"time"
"go-common/app/interface/main/mcn/model"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/library/log"
"github.com/jinzhu/gorm"
)
const (
dateFmt = "2006-01-02"
tidSummary = 65535 // 特殊的tid表示所有分区数据之和
)
//GetMcnDataSummary .
func (d *Dao) GetMcnDataSummary(selec string, query interface{}, args ...interface{}) (res *mcnmodel.McnDataSummary, err error) {
res = new(mcnmodel.McnDataSummary)
err = d.mcndb.Select(selec).Where(query, args...).Limit(1).Find(res).Error
if err != nil {
log.Error("query db fail, err=%s", err)
return
}
return
}
//GetMcnDataSummaryWithDiff get data with datacenter diff
func (d *Dao) GetMcnDataSummaryWithDiff(signID int64, dataTYpe mcnmodel.McnDataType, generateDate time.Time) (res *mcnmodel.McnGetDataSummaryReply, err error) {
dataDay0, err := d.GetMcnDataSummary("up_count, fans_count_accumulate, archive_count_accumulate, play_count_accumulate, generate_date", "sign_id=? and data_type=? and generate_date=? and active_tid=?", signID, dataTYpe, generateDate.Format(dateFmt), tidSummary)
if int64(dataDay0.GenerateDate) == 0 {
err = gorm.ErrRecordNotFound
}
if err != nil {
if err == gorm.ErrRecordNotFound {
err = nil
log.Warn("not found generate date=%s, sign id=%d", generateDate.Format(dateFmt), signID)
return
}
log.Error("fail to get data db, err=%s, sign id=%d", err, signID)
return
}
dataDay1, err := d.GetMcnDataSummary("up_count, fans_count_accumulate, archive_count_accumulate, play_count_accumulate, generate_date", "sign_id=? and data_type=? and generate_date=? and active_tid=?", signID, dataTYpe, generateDate.AddDate(0, 0, -1).Format(dateFmt), tidSummary)
if int64(dataDay1.GenerateDate) == 0 {
err = gorm.ErrRecordNotFound
}
if err != nil {
if err == gorm.ErrRecordNotFound {
err = nil
log.Warn("not found generate date=%s, sign id=%d", generateDate.Format(dateFmt), signID)
dataDay1 = new(mcnmodel.McnDataSummary)
} else {
log.Error("fail to get data db, err=%s, sign id=%d", err, signID)
return
}
}
res = new(mcnmodel.McnGetDataSummaryReply)
res.CopyFrom(dataDay0)
res.CalcDiff(dataDay1)
return
}
//GetDataUpLatestDate .
func (d *Dao) GetDataUpLatestDate(dataType mcnmodel.DataType, signID int64) (generateDate time.Time, err error) {
var model = mcnmodel.McnDataUp{}
err = d.mcndb.Select("generate_date").Where("data_type=? and sign_id=?", dataType, signID).Order("generate_date desc").Limit(1).Find(&model).Error
if err != nil {
log.Error("get latest date from mcn_data_up fail, err=%s", err)
return
}
generateDate = model.GenerateDate.Time()
return
}
//GetAllUpData .
func (d *Dao) GetAllUpData(signID int64, upmid int64, generateDate time.Time) (res []*mcnmodel.McnUpDataInfo, err error) {
var sqlstr = `select
u.begin_date,
u.end_date,
u.state,
u.up_mid,
u.publication_price,
u.permission,
d.fans_increase_accumulate,
d.archive_count,
d.play_count,
d.fans_increase_month,
d.fans_count,
d.fans_count_active,
generate_date
from
mcn_up as u left join mcn_data_up as d
on (d.sign_id = u.sign_id and d.up_mid = u.up_mid and d.data_type=1 and generate_date=? )
where u.sign_id=? and u.state not in (?)`
var values = []interface{}{generateDate, signID, []model.MCNUPState{model.MCNUPStateOnDelete}}
if upmid != 0 {
sqlstr += " and u.up_mid=?"
values = append(values, upmid)
}
err = d.mcndb.Raw(sqlstr, values...).Find(&res).Error
if err != nil {
log.Error("query db fail, err=%s", err)
return
}
return
}
//GetAllUpDataTemp .
func (d *Dao) GetAllUpDataTemp(signID int64, upmid int64, generateDate time.Time) (res []*mcnmodel.McnUpDataInfo, err error) {
/*
前台这边一期的数据
1.首页 - 绑定up主总数
2.up主列表 - 总粉数
3.up主列表 - 投稿数
4.up主列表 - up分区
5.up主列表 - 签约及到期时间
*/
var sqlstr = `select
u.begin_date,
u.end_date,
u.state,
u.up_mid,
d.article_count_accumulate as archive_count,
d.fans_count,
d.active_fans as fans_count_active
from
mcn_up as u left join up_base_info as d
on (d.mid = u.up_mid and d.business_type = 1)
where u.sign_id=? and u.state not in (?)`
var values = []interface{}{signID, []model.MCNUPState{model.MCNUPStateOnDelete, model.MCNUPStateOnExpire, model.MCNUPStateOnClear}}
if upmid != 0 {
sqlstr += " and u.up_mid=?"
values = append(values, upmid)
}
err = d.mcndb.Raw(sqlstr, values...).Find(&res).Error
if err != nil {
log.Error("query db fail, err=%s", err)
return
}
return
}

View File

@@ -0,0 +1,94 @@
package mcndao
import (
"testing"
"time"
"go-common/app/interface/main/mcn/model/mcnmodel"
"github.com/jinzhu/gorm"
"github.com/smartystreets/goconvey/convey"
)
func TestMcndaoGetMcnDataSummary(t *testing.T) {
convey.Convey("GetMcnDataSummary", t, func(ctx convey.C) {
var (
selec = "*"
query = "1=?"
args = "1"
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.GetMcnDataSummary(selec, query, args)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoGetMcnDataSummaryWithDiff(t *testing.T) {
convey.Convey("GetMcnDataSummaryWithDiff", t, func(ctx convey.C) {
var (
signID = int64(0)
dataTYpe mcnmodel.McnDataType
generateDate = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.GetMcnDataSummaryWithDiff(signID, dataTYpe, generateDate)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestMcndaoGetDataUpLatestDate(t *testing.T) {
convey.Convey("GetDataUpLatestDate", t, func(ctx convey.C) {
var (
dataType = mcnmodel.DataType(1)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
generateDate, err := d.GetDataUpLatestDate(dataType, 0)
ctx.Convey("Then err should be nil.generateDate should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldEqual, gorm.ErrRecordNotFound)
ctx.So(generateDate, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoGetAllUpData(t *testing.T) {
convey.Convey("GetAllUpData", t, func(ctx convey.C) {
var (
signID = int64(0)
upmid = int64(0)
generateDate = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.GetAllUpData(signID, upmid, generateDate)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoGetAllUpDataTemp(t *testing.T) {
convey.Convey("GetAllUpDataTemp", t, func(ctx convey.C) {
var (
signID = int64(0)
upmid = int64(0)
generateDate = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.GetAllUpDataTemp(signID, upmid, generateDate)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,287 @@
// Code generated by $GOPATH/src/go-common/app/tool/cache/mc. DO NOT EDIT.
/*
Package mcndao is a generated mc cache package.
It is generated from:
type _mc interface {
//mc: -key=mcnSignCacheKey -expire=d.mcnSignExpire -encode=json
AddCacheMcnSign(c context.Context, mcnmid int64, up *mcnmodel.McnSign) (err error)
//mc: -key=mcnSignCacheKey
CacheMcnSign(c context.Context, mcnmid int64) (up *mcnmodel.McnSign, err error)
//mc: -key=mcnSignCacheKey
DelCacheMcnSign(c context.Context, mcnmid int64) (err error)
//mc: -key=mcnDataCacheKey -expire=d.mcnDataExpire -encode=json
AddCacheMcnDataSummary(c context.Context, mcnmid int64, data *mcnmodel.McnGetDataSummaryReply, generateDate time.Time) (err error)
//mc: -key=mcnDataCacheKey
CacheMcnDataSummary(c context.Context, mcnmid int64, generateDate time.Time) (data *mcnmodel.McnGetDataSummaryReply, err error)
//mc: -key=mcnDataCacheKey
DelMcnDataSummary(c context.Context, mcnmid int64, generateDate time.Time) (err error)
//mc: -key=mcnPublicationPriceKey -expire=0 -encode=json
AddCachePublicationPrice(c context.Context, signID int64, data *mcnmodel.PublicationPriceCache, mid int64) (err error)
//mc: -key=mcnPublicationPriceKey
CachePublicationPrice(c context.Context, signID int64, mid int64) (data *mcnmodel.PublicationPriceCache, err error)
//mc: -key=mcnPublicationPriceKey
DelPublicationPrice(c context.Context, signID int64, mid int64) (err error)
//mc: -key=mcnUpPermissionKey -expire=d.mcnSignExpire -encode=json
AddCacheUpPermission(c context.Context, signID int64, data *mcnmodel.UpPermissionCache, mid int64) (err error)
//mc: -key=mcnUpPermissionKey
CacheUpPermission(c context.Context, signID int64, mid int64) (data *mcnmodel.UpPermissionCache, err error)
//mc: -key=mcnUpPermissionKey
DelUpPermission(c context.Context, signID int64, mid int64) (err error)
}
*/
package mcndao
import (
"context"
"fmt"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/library/cache/memcache"
"go-common/library/log"
"go-common/library/stat/prom"
"time"
)
var _ _mc
// AddCacheMcnSign Set data to mc
func (d *Dao) AddCacheMcnSign(c context.Context, id int64, val *mcnmodel.McnSign) (err error) {
if val == nil {
return
}
conn := d.mc.Get(c)
defer conn.Close()
key := mcnSignCacheKey(id)
item := &memcache.Item{Key: key, Object: val, Expiration: d.mcnSignExpire, Flags: memcache.FlagJSON}
if err = conn.Set(item); err != nil {
prom.BusinessErrCount.Incr("mc:AddCacheMcnSign")
log.Errorv(c, log.KV("AddCacheMcnSign", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// CacheMcnSign get data from mc
func (d *Dao) CacheMcnSign(c context.Context, id int64) (res *mcnmodel.McnSign, err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := mcnSignCacheKey(id)
reply, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:CacheMcnSign")
log.Errorv(c, log.KV("CacheMcnSign", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
res = &mcnmodel.McnSign{}
err = conn.Scan(reply, res)
if err != nil {
prom.BusinessErrCount.Incr("mc:CacheMcnSign")
log.Errorv(c, log.KV("CacheMcnSign", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// DelCacheMcnSign delete data from mc
func (d *Dao) DelCacheMcnSign(c context.Context, id int64) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := mcnSignCacheKey(id)
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:DelCacheMcnSign")
log.Errorv(c, log.KV("DelCacheMcnSign", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// AddCacheMcnDataSummary Set data to mc
func (d *Dao) AddCacheMcnDataSummary(c context.Context, id int64, val *mcnmodel.McnGetDataSummaryReply, generateDate time.Time) (err error) {
if val == nil {
return
}
conn := d.mc.Get(c)
defer conn.Close()
key := mcnDataCacheKey(id, generateDate)
item := &memcache.Item{Key: key, Object: val, Expiration: d.mcnDataExpire, Flags: memcache.FlagJSON}
if err = conn.Set(item); err != nil {
prom.BusinessErrCount.Incr("mc:AddCacheMcnDataSummary")
log.Errorv(c, log.KV("AddCacheMcnDataSummary", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// CacheMcnDataSummary get data from mc
func (d *Dao) CacheMcnDataSummary(c context.Context, id int64, generateDate time.Time) (res *mcnmodel.McnGetDataSummaryReply, err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := mcnDataCacheKey(id, generateDate)
reply, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:CacheMcnDataSummary")
log.Errorv(c, log.KV("CacheMcnDataSummary", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
res = &mcnmodel.McnGetDataSummaryReply{}
err = conn.Scan(reply, res)
if err != nil {
prom.BusinessErrCount.Incr("mc:CacheMcnDataSummary")
log.Errorv(c, log.KV("CacheMcnDataSummary", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// DelMcnDataSummary delete data from mc
func (d *Dao) DelMcnDataSummary(c context.Context, id int64, generateDate time.Time) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := mcnDataCacheKey(id, generateDate)
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:DelMcnDataSummary")
log.Errorv(c, log.KV("DelMcnDataSummary", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// AddCachePublicationPrice Set data to mc
func (d *Dao) AddCachePublicationPrice(c context.Context, id int64, val *mcnmodel.PublicationPriceCache, mid int64) (err error) {
if val == nil {
return
}
conn := d.mc.Get(c)
defer conn.Close()
key := mcnPublicationPriceKey(id, mid)
item := &memcache.Item{Key: key, Object: val, Expiration: 0, Flags: memcache.FlagJSON}
if err = conn.Set(item); err != nil {
prom.BusinessErrCount.Incr("mc:AddCachePublicationPrice")
log.Errorv(c, log.KV("AddCachePublicationPrice", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// CachePublicationPrice get data from mc
func (d *Dao) CachePublicationPrice(c context.Context, id int64, mid int64) (res *mcnmodel.PublicationPriceCache, err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := mcnPublicationPriceKey(id, mid)
reply, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:CachePublicationPrice")
log.Errorv(c, log.KV("CachePublicationPrice", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
res = &mcnmodel.PublicationPriceCache{}
err = conn.Scan(reply, res)
if err != nil {
prom.BusinessErrCount.Incr("mc:CachePublicationPrice")
log.Errorv(c, log.KV("CachePublicationPrice", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// DelPublicationPrice delete data from mc
func (d *Dao) DelPublicationPrice(c context.Context, id int64, mid int64) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := mcnPublicationPriceKey(id, mid)
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:DelPublicationPrice")
log.Errorv(c, log.KV("DelPublicationPrice", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// AddCacheUpPermission Set data to mc
func (d *Dao) AddCacheUpPermission(c context.Context, id int64, val *mcnmodel.UpPermissionCache, mid int64) (err error) {
if val == nil {
return
}
conn := d.mc.Get(c)
defer conn.Close()
key := mcnUpPermissionKey(id, mid)
item := &memcache.Item{Key: key, Object: val, Expiration: d.mcnSignExpire, Flags: memcache.FlagJSON}
if err = conn.Set(item); err != nil {
prom.BusinessErrCount.Incr("mc:AddCacheUpPermission")
log.Errorv(c, log.KV("AddCacheUpPermission", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// CacheUpPermission get data from mc
func (d *Dao) CacheUpPermission(c context.Context, id int64, mid int64) (res *mcnmodel.UpPermissionCache, err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := mcnUpPermissionKey(id, mid)
reply, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:CacheUpPermission")
log.Errorv(c, log.KV("CacheUpPermission", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
res = &mcnmodel.UpPermissionCache{}
err = conn.Scan(reply, res)
if err != nil {
prom.BusinessErrCount.Incr("mc:CacheUpPermission")
log.Errorv(c, log.KV("CacheUpPermission", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// DelUpPermission delete data from mc
func (d *Dao) DelUpPermission(c context.Context, id int64, mid int64) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := mcnUpPermissionKey(id, mid)
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:DelUpPermission")
log.Errorv(c, log.KV("DelUpPermission", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}

View File

@@ -0,0 +1,108 @@
package mcndao
import (
"context"
"testing"
"time"
"go-common/app/interface/main/mcn/model/mcnmodel"
"github.com/smartystreets/goconvey/convey"
)
func TestMcndaoAddCacheMcnSign(t *testing.T) {
convey.Convey("AddCacheMcnSign", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
val = &mcnmodel.McnSign{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.AddCacheMcnSign(c, id, val)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMcndaoCacheMcnSign(t *testing.T) {
convey.Convey("CacheMcnSign", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.CacheMcnSign(c, id)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoDelCacheMcnSign(t *testing.T) {
convey.Convey("DelCacheMcnSign", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.DelCacheMcnSign(c, id)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMcndaoAddCacheMcnDataSummary(t *testing.T) {
convey.Convey("AddCacheMcnDataSummary", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
val = &mcnmodel.McnGetDataSummaryReply{}
generateDate = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.AddCacheMcnDataSummary(c, id, val, generateDate)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMcndaoCacheMcnDataSummary(t *testing.T) {
convey.Convey("CacheMcnDataSummary", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
generateDate = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.CacheMcnDataSummary(c, id, generateDate)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoDelMcnDataSummary(t *testing.T) {
convey.Convey("DelMcnDataSummary", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
generateDate = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.DelMcnDataSummary(c, id, generateDate)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,116 @@
package mcndao
import (
"context"
"fmt"
"time"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/library/log"
"github.com/jinzhu/gorm"
)
//go:generate $GOPATH/src/go-common/app/tool/cache/gen
type _cache interface {
//cache: -nullcache=&mcnmodel.McnSign{ID:-1} -check_null_code=$!=nil&&$.ID==-1
McnSign(c context.Context, mcnmid int64) (up *mcnmodel.McnSign, err error)
//cache: -nullcache=&mcnmodel.McnGetDataSummaryReply{IsNull:true} -check_null_code=$!=nil&&$.IsNull
McnDataSummary(c context.Context, mcnmid int64, generateDate time.Time) (res *mcnmodel.McnGetDataSummaryReply, err error)
//cache: -nullcache=&mcnmodel.UpPermissionCache{IsNull:true} -check_null_code=$!=nil&&$.IsNull
UpPermission(c context.Context, signID int64, mid int64) (data *mcnmodel.UpPermissionCache, err error)
}
//go:generate $GOPATH/src/go-common/app/tool/cache/mc
type _mc interface {
//mc: -key=mcnSignCacheKey -expire=d.mcnSignExpire -encode=json
AddCacheMcnSign(c context.Context, mcnmid int64, up *mcnmodel.McnSign) (err error)
//mc: -key=mcnSignCacheKey
CacheMcnSign(c context.Context, mcnmid int64) (up *mcnmodel.McnSign, err error)
//mc: -key=mcnSignCacheKey
DelCacheMcnSign(c context.Context, mcnmid int64) (err error)
//mc: -key=mcnDataCacheKey -expire=d.mcnDataExpire -encode=json
AddCacheMcnDataSummary(c context.Context, mcnmid int64, data *mcnmodel.McnGetDataSummaryReply, generateDate time.Time) (err error)
//mc: -key=mcnDataCacheKey
CacheMcnDataSummary(c context.Context, mcnmid int64, generateDate time.Time) (data *mcnmodel.McnGetDataSummaryReply, err error)
//mc: -key=mcnDataCacheKey
DelMcnDataSummary(c context.Context, mcnmid int64, generateDate time.Time) (err error)
//mc: -key=mcnPublicationPriceKey -expire=0 -encode=json
AddCachePublicationPrice(c context.Context, signID int64, data *mcnmodel.PublicationPriceCache, mid int64) (err error)
//mc: -key=mcnPublicationPriceKey
CachePublicationPrice(c context.Context, signID int64, mid int64) (data *mcnmodel.PublicationPriceCache, err error)
//mc: -key=mcnPublicationPriceKey
DelPublicationPrice(c context.Context, signID int64, mid int64) (err error)
//mc: -key=mcnUpPermissionKey -expire=d.mcnSignExpire -encode=json
AddCacheUpPermission(c context.Context, signID int64, data *mcnmodel.UpPermissionCache, mid int64) (err error)
//mc: -key=mcnUpPermissionKey
CacheUpPermission(c context.Context, signID int64, mid int64) (data *mcnmodel.UpPermissionCache, err error)
//mc: -key=mcnUpPermissionKey
DelUpPermission(c context.Context, signID int64, mid int64) (err error)
}
func mcnSignCacheKey(mcnmid int64) string {
return fmt.Sprintf("mcn_s_%d", mcnmid)
}
//RawMcnSign raw db .
func (d *Dao) RawMcnSign(c context.Context, mcnmid int64) (up *mcnmodel.McnSign, err error) {
up, _, err = d.GetMcnSignState("*", mcnmid)
if err != nil {
if err == gorm.ErrRecordNotFound {
err = nil
return
}
log.Error("error get state, err=%s", err)
return
}
return
}
//AsyncDelCacheMcnSign delete in async way
func (d *Dao) AsyncDelCacheMcnSign(id int64) (err error) {
return d.cache.Do(context.Background(), func(c context.Context) {
d.DelCacheMcnSign(c, id)
})
}
func mcnDataCacheKey(signID int64, generateDate time.Time) string {
var key = fmt.Sprintf("mcn_data_%d_%s", signID, generateDate.Format(dateFmt))
return key
}
//RawMcnDataSummary raw get
func (d *Dao) RawMcnDataSummary(c context.Context, signID int64, generateDate time.Time) (res *mcnmodel.McnGetDataSummaryReply, err error) {
return d.GetMcnDataSummaryWithDiff(signID, mcnmodel.McnDataTypeDay, generateDate)
}
func mcnPublicationPriceKey(signID int64, mid int64) string {
return fmt.Sprintf("mcn_pubprice_%d_%d", signID, mid)
}
func mcnUpPermissionKey(signID int64, mid int64) string {
var s = fmt.Sprintf("mcn_upperm_%d_%d", signID, mid)
log.Info("key=%s", s)
return s
}
//RawUpPermission get permissino from db
func (d *Dao) RawUpPermission(c context.Context, signID int64, mid int64) (res *mcnmodel.UpPermissionCache, err error) {
upList, err := d.GetUpBind("up_mid=? and sign_id=? and state in (?)", mid, signID, UpSignedStates)
if err != nil {
log.Error("get up from db fail, err=%v, signid=%d, mid=%d", err, signID, mid)
return
}
if len(upList) == 0 {
log.Warn("up not found, sign_id=%d, mid=%d", signID, mid)
return
}
res = new(mcnmodel.UpPermissionCache)
res.Permission = upList[0].Permission
return
}

View File

@@ -0,0 +1,85 @@
package mcndao
import (
"context"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestMcndaomcnSignCacheKey(t *testing.T) {
convey.Convey("mcnSignCacheKey", t, func(ctx convey.C) {
var (
mcnmid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := mcnSignCacheKey(mcnmid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoRawMcnSign(t *testing.T) {
convey.Convey("RawMcnSign", t, func(ctx convey.C) {
var (
c = context.Background()
mcnmid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
up, err := d.RawMcnSign(c, mcnmid)
ctx.Convey("Then err should be nil.up should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(up, convey.ShouldBeNil)
})
})
})
}
func TestMcndaoAsyncDelCacheMcnSign(t *testing.T) {
convey.Convey("AsyncDelCacheMcnSign", t, func(ctx convey.C) {
var (
id = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.AsyncDelCacheMcnSign(id)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMcndaomcnDataCacheKey(t *testing.T) {
convey.Convey("mcnDataCacheKey", t, func(ctx convey.C) {
var (
signID = int64(0)
generateDate = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := mcnDataCacheKey(signID, generateDate)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoRawMcnDataSummary(t *testing.T) {
convey.Convey("RawMcnDataSummary", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
generateDate = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.RawMcnDataSummary(c, id, generateDate)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,426 @@
package mcndao
import (
"context"
"fmt"
"sort"
"time"
"go-common/app/admin/main/up/util"
"go-common/app/admin/main/up/util/mathutil"
"go-common/app/interface/main/mcn/conf"
"go-common/app/interface/main/mcn/dao/cache"
"go-common/app/interface/main/mcn/dao/global"
"go-common/app/interface/main/mcn/model/mcnmodel"
arcgrpc "go-common/app/service/main/archive/api"
"go-common/library/log"
"github.com/bluele/gcache"
)
// RankByTid .
// 存储rank的缓存
// 对每种排行榜的分类进行缓存
// 对排序进行实时计算
// 先去localcache中取取不到的话去db中取
type RankByTid struct {
// [tid][datatype] rank list
TidMap map[int16]map[mcnmodel.DataType][]mcnmodel.RankDataInterface
TidTypeListMap map[mcnmodel.DataType][]*mcnmodel.TidnameInfo
}
//RankFunc rank func
type RankFunc func(signId int64) (result *RankByTid, err error)
type tidnameUnique struct {
tidInfoMap map[mcnmodel.DataType]map[int16]*mcnmodel.TidnameInfo
}
func newTidNameUnique() *tidnameUnique {
return &tidnameUnique{tidInfoMap: make(map[mcnmodel.DataType]map[int16]*mcnmodel.TidnameInfo)}
}
func (t *tidnameUnique) addTid(tid int16, name string, datatype mcnmodel.DataType) {
var dmap map[int16]*mcnmodel.TidnameInfo
var ok bool
if dmap, ok = t.tidInfoMap[datatype]; !ok {
dmap = make(map[int16]*mcnmodel.TidnameInfo)
t.tidInfoMap[datatype] = dmap
}
dmap[tid] = &mcnmodel.TidnameInfo{Tid: tid, Name: name}
}
func (t *tidnameUnique) getList(datatype mcnmodel.DataType) (typeList []*mcnmodel.TidnameInfo) {
for _, v := range t.tidInfoMap[datatype] {
typeList = append(typeList, v)
}
return
}
func (t *tidnameUnique) export(dmap map[mcnmodel.DataType][]*mcnmodel.TidnameInfo) {
for dataType, tidMap := range t.tidInfoMap {
var typeList []*mcnmodel.TidnameInfo
for k, v := range tidMap {
if k == 0 {
continue
}
typeList = append(typeList, v)
}
dmap[dataType] = typeList
}
}
// // 排序根据increase数量做倒序
// type rankByFansIncreaseDesc []*mcnmodel.RankUpFansInfo
// func (s rankByFansIncreaseDesc) Len() int {
// return len(s)
// }
// func (s rankByFansIncreaseDesc) Swap(i, j int) {
// s[i], s[j] = s[j], s[i]
// }
// func (s rankByFansIncreaseDesc) Less(i, j int) bool {
// return s[i].FansIncrease > s[j].FansIncrease
// }
type sortRankFunc func(p1, p2 mcnmodel.RankDataInterface) bool
type rankDataSorter struct {
datas []mcnmodel.RankDataInterface
by sortRankFunc // Closure used in the Less method.
}
// Len is part of sort.Interface.
func (s *rankDataSorter) Len() int {
return len(s.datas)
}
// Swap is part of sort.Interface.
func (s *rankDataSorter) Swap(i, j int) {
s.datas[i], s.datas[j] = s.datas[j], s.datas[i]
}
// Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter.
func (s *rankDataSorter) Less(i, j int) bool {
return s.by(s.datas[i], s.datas[j])
}
func byValueDesc(p1, p2 mcnmodel.RankDataInterface) bool {
return p1.GetValue() > p2.GetValue()
}
//GetList get list
func (s *RankByTid) GetList(tid int16, dataType mcnmodel.DataType) (res []mcnmodel.RankDataInterface) {
if s.TidMap == nil {
return
}
tMap, ok := s.TidMap[tid]
if !ok || tMap == nil {
return
}
if res, ok = tMap[dataType]; !ok {
res = nil
}
return
}
var nulltidlist = make([]*mcnmodel.TidnameInfo, 0)
//GetTypeList get type's list
func (s *RankByTid) GetTypeList(dataType mcnmodel.DataType) (res []*mcnmodel.TidnameInfo) {
res = s.TidTypeListMap[dataType]
if res == nil {
res = nulltidlist
}
return
}
func (s *RankByTid) addRank(v mcnmodel.RankDataInterface) {
var dmap, allMap map[mcnmodel.DataType][]mcnmodel.RankDataInterface
if s.TidMap == nil {
s.TidMap = make(map[int16]map[mcnmodel.DataType][]mcnmodel.RankDataInterface)
}
var ok bool
if v.GetTid() != 0 {
if dmap, ok = s.TidMap[v.GetTid()]; !ok {
dmap = make(map[mcnmodel.DataType][]mcnmodel.RankDataInterface)
s.TidMap[v.GetTid()] = dmap
}
dmap[v.GetDataType()] = append(dmap[v.GetDataType()], v)
}
if allMap, ok = s.TidMap[0]; !ok {
allMap = make(map[mcnmodel.DataType][]mcnmodel.RankDataInterface)
s.TidMap[0] = allMap
}
allMap[v.GetDataType()] = append(allMap[v.GetDataType()], v)
}
func (s *RankByTid) addTidMap(v *tidnameUnique) {
if s.TidTypeListMap == nil {
s.TidTypeListMap = make(map[mcnmodel.DataType][]*mcnmodel.TidnameInfo)
}
v.export(s.TidTypeListMap)
}
//Truncate truncate all the sorted list by max item number
func (s *RankByTid) Truncate(max int) {
for _, v := range s.TidMap {
for k2, v2 := range v {
var length = len(v2)
if length == 0 {
continue
}
var m = mathutil.Min(max, length)
v[k2] = v2[0:m]
}
}
}
// Sort sort by sorting function
func (s *RankByTid) Sort(sortFunc sortRankFunc) {
for _, v := range s.TidMap {
for k2, v2 := range v {
var sorter = &rankDataSorter{
datas: v2,
by: sortFunc,
}
sort.Sort(sorter)
v[k2] = v2
}
}
}
type keyFunc func(int64) string
type loadRankFunc func(signID int64, date time.Time) (result *RankByTid, err error)
// GetRankUpFans get fans
func (d *Dao) GetRankUpFans(signID int64) (result *RankByTid, err error) {
return d.getRankCache(signID, cacheKeyRankFans, d.loadRankUpFansCache)
}
// GetRankArchiveLikes get fans
func (d *Dao) GetRankArchiveLikes(signID int64) (result *RankByTid, err error) {
return d.getRankCache(signID, cacheKeyRankArchiveLikes, d.loadRankArchiveLikesCache)
}
func (d *Dao) getRankCache(signID int64, keyCalc keyFunc, load loadRankFunc) (result *RankByTid, err error) {
var key = keyCalc(signID)
v, err := d.localcache.Get(key)
if err != nil {
if err == gcache.KeyNotFoundError {
// load cache
v, err = load(signID, time.Now())
if err != nil {
log.Error("load cache error, signID=%d, err=%s", signID, err)
return
}
d.localcache.SetWithExpire(key, v, time.Duration(conf.Conf.RankCache.ExpireTime))
} else {
log.Error("get from gcache err, signID=%d, err=%s", signID, err)
return
}
}
if v == nil {
return
}
result, _ = v.(*RankByTid)
return
}
func cacheKeyRankFans(signID int64) string {
return fmt.Sprintf("rank_fans_%d", signID)
}
func cacheKeyRankArchiveLikes(signID int64) string {
return fmt.Sprintf("rank_likes_%d", signID)
}
var dataTypes = []mcnmodel.DataType{
mcnmodel.DataTypeAccumulate,
mcnmodel.DataTypeDay,
mcnmodel.DataTypeWeek,
mcnmodel.DataTypeMonth,
mcnmodel.DataTypeActiveFans,
}
// --------------------------------------- load rank up fans -------------------------------
func (d *Dao) loadRankUpFansCache(signID int64, date time.Time) (result *RankByTid, err error) {
rawRanks, err := d.RawRankUpFans(signID, date)
if err != nil {
log.Error("fail to get raw rank up fans, signid=%d, err=%s", signID, err)
return
}
result = new(RankByTid)
if len(rawRanks) == 0 {
log.Info("up fans rank data is empty, sign id=%d", signID)
return
}
var midMap = make(map[int64]struct{})
//var accumulateMap = make(map[int64]*mcnmodel.McnRankUpFan)
// 获取mid列表
for _, v := range rawRanks {
midMap[v.UpMid] = struct{}{}
//if v.DataType == mcnmodel.DataTypeAccumulate {
// accumulateMap[v.UpMid] = v
//}
}
var mids []int64
for k := range midMap {
mids = append(mids, k)
}
// 获取账号信息,头像
accInfos, err := global.GetInfos(context.Background(), mids)
if err != nil || accInfos == nil {
log.Warn("get infos fail, err=%s", err)
}
var tidUnique = newTidNameUnique()
// 组装信息
for _, v := range rawRanks {
var info mcnmodel.RankUpFansInfo
info.Copy(v)
if account, ok := accInfos[v.UpMid]; ok {
info.Name = account.Name
info.UpFaceLink = account.Face
info.TidName = cache.GetTidName(int64(info.Tid))
if info.TidName == "" {
info.TidName = "其他"
}
tidUnique.addTid(info.Tid, info.TidName, info.DataType)
}
//if accumulateData, ok := accumulateMap[v.UpMid]; ok {
// info.FansAccumulate = accumulateData.Value1
//}
result.addRank(&info)
}
result.addTidMap(tidUnique)
// 排序
result.Sort(byValueDesc)
// 截断到10个截断需要在排序之后
result.Truncate(10)
return
}
//RawRankUpFans get from db
func (d *Dao) RawRankUpFans(signID int64, date time.Time) (result []*mcnmodel.McnRankUpFan, err error) {
// 有X种类型
// 昨日、上周、上月、累计
// 每种类型取最近日期的数据
for _, typ := range dataTypes {
var tmpResult []*mcnmodel.McnRankUpFan
e := d.mcndb.Raw(`select * from mcn_rank_up_fans where data_type=? and sign_id=?
and generate_date=(select generate_date from mcn_rank_up_fans where data_type=? and sign_id=? and generate_date <= ? order by generate_date desc limit 1)`,
typ, signID, typ, signID, date).
Find(&tmpResult).Error
if e != nil {
log.Error("fail to get rank, type=%d, sign id=%d, err=%s", typ, signID, e)
continue
}
result = append(result, tmpResult...)
}
log.Info("get rank from db, sign id=%d, len=%d, date=%s", signID, len(result), date.Format(dateFmt))
return
}
//ReloadRank reload rank from db
func (d *Dao) ReloadRank(signID int64) (err error) {
// load cache
v, err := d.loadRankUpFansCache(signID, time.Now())
if err != nil {
log.Error("load cache error, signID=%d, err=%s", signID, err)
return
}
var key = cacheKeyRankFans(signID)
d.localcache.SetWithExpire(key, v, time.Hour)
log.Info("reload rank cache, sign id=%d", signID)
return
}
// ----------------------------------------- load rank archive likes ------------------------------------
func (d *Dao) loadRankArchiveLikesCache(signID int64, date time.Time) (result *RankByTid, err error) {
rawArchiveLike, err := d.RawRankArchiveLikes(signID, date)
if err != nil {
log.Error("fail to get raw rank up fans, signid=%d, err=%s", signID, err)
return
}
result = new(RankByTid)
if len(rawArchiveLike) == 0 {
log.Info("archive likes rank data is empty, sign id=%d", signID)
return
}
// 获取 aid列表
var aids []int64
//var accumulateMap = make(map[int64]*mcnmodel.McnRankArchiveLike)
for _, v := range rawArchiveLike {
aids = append(aids, v.ArchiveID)
//if v.DataType == mcnmodel.DataTypeAccumulate {
// accumulateMap[v.ArchiveID] = v
//}
}
aids = util.Unique(aids)
// 获取archive信息
arcsReply, err := global.GetArcGRPC().Arcs(context.Background(), &arcgrpc.ArcsRequest{Aids: aids})
if err != nil {
log.Error("fail to get archive info, sign_id=%d err=%s", signID, err)
return
}
archiveDataMap := arcsReply.Arcs
var tidUnique = newTidNameUnique()
// 组装archive信息
for _, v := range rawArchiveLike {
var info = mcnmodel.RankArchiveLikeInfo{}
info.CopyFromDB(v)
var archive, ok = archiveDataMap[v.ArchiveID]
if !ok {
continue
}
info.CopyFromArchive(archive)
tidUnique.addTid(info.Tid, info.TidName, info.DataType)
//if accumulateData, ok := accumulateMap[v.ArchiveID]; ok {
// info.LikesAccumulate = accumulateData.LikeCount
//}
result.addRank(&info)
}
result.addTidMap(tidUnique)
// 排序
result.Sort(byValueDesc)
result.Truncate(10)
return
}
//RawRankArchiveLikes get from db
func (d *Dao) RawRankArchiveLikes(signID int64, date time.Time) (result []*mcnmodel.McnRankArchiveLike, err error) {
// 有X种类型
// 昨日、上周、上月、累计
// 每种类型取最近日期的数据
for _, typ := range dataTypes {
var tmpResult []*mcnmodel.McnRankArchiveLike
e := d.mcndb.Raw(`select * from mcn_rank_archive_likes where data_type=? and sign_id=?
and generate_date=(select generate_date from mcn_rank_archive_likes where data_type=? and sign_id=? and generate_date <= ? order by generate_date desc limit 1)`,
typ, signID, typ, signID, date).
Find(&tmpResult).Error
if e != nil {
log.Error("fail to get rank, type=%d, sign id=%d, err=%s", typ, signID, e)
continue
}
result = append(result, tmpResult...)
}
log.Info("get rank from db, sign id=%d, len=%d, date=%s", signID, len(result), date.Format(dateFmt))
return
}

View File

@@ -0,0 +1,193 @@
package mcndao
import (
"testing"
"time"
"go-common/app/interface/main/mcn/model/mcnmodel"
"github.com/smartystreets/goconvey/convey"
)
func TestMcndaobyValueDesc(t *testing.T) {
convey.Convey("byValueDesc", t, func(ctx convey.C) {
var (
p1 = &mcnmodel.RankUpFansInfo{Mid: 1}
p2 = &mcnmodel.RankUpFansInfo{Mid: 2}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := byValueDesc(p1, p2)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoGetRankUpFans(t *testing.T) {
convey.Convey("GetRankUpFans", t, func(ctx convey.C) {
var (
signID = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.GetRankUpFans(signID)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoGetRankArchiveLikes(t *testing.T) {
convey.Convey("GetRankArchiveLikes", t, func(ctx convey.C) {
var (
signID = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.GetRankArchiveLikes(signID)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaogetRankCache(t *testing.T) {
convey.Convey("getRankCache", t, func(ctx convey.C) {
var (
signID = int64(1)
keyCalc keyFunc
load loadRankFunc
)
keyCalc = cacheKeyRankFans
load = d.loadRankUpFansCache
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.getRankCache(signID, keyCalc, load)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
if result == nil {
ctx.So(result, convey.ShouldBeNil)
} else {
ctx.So(result, convey.ShouldNotBeNil)
}
})
})
})
}
func TestMcndaocacheKeyRankFans(t *testing.T) {
convey.Convey("cacheKeyRankFans", t, func(ctx convey.C) {
var (
signID = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := cacheKeyRankFans(signID)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaocacheKeyRankArchiveLikes(t *testing.T) {
convey.Convey("cacheKeyRankArchiveLikes", t, func(ctx convey.C) {
var (
signID = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := cacheKeyRankArchiveLikes(signID)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoloadRankUpFansCache(t *testing.T) {
convey.Convey("loadRankUpFansCache", t, func(ctx convey.C) {
var (
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.loadRankUpFansCache(signID, date)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoRawRankUpFans(t *testing.T) {
convey.Convey("RawRankUpFans", t, func(ctx convey.C) {
var (
signID = int64(1)
date = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.RawRankUpFans(signID, date)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
if len(result) == 0 {
ctx.So(result, convey.ShouldBeNil)
} else {
ctx.So(result, convey.ShouldNotBeNil)
}
})
})
})
}
func TestMcndaoReloadRank(t *testing.T) {
convey.Convey("ReloadRank", t, func(ctx convey.C) {
var (
signID = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.ReloadRank(signID)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMcndaoloadRankArchiveLikesCache(t *testing.T) {
convey.Convey("loadRankArchiveLikesCache", t, func(ctx convey.C) {
var (
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.loadRankArchiveLikesCache(signID, date)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoRawRankArchiveLikes(t *testing.T) {
convey.Convey("RawRankArchiveLikes", t, func(ctx convey.C) {
var (
signID = int64(1)
date = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.RawRankArchiveLikes(signID, date)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
if len(result) == 0 {
ctx.So(result, convey.ShouldBeEmpty)
} else {
ctx.So(result, convey.ShouldNotBeNil)
}
})
})
})
}

View File

@@ -0,0 +1,183 @@
package mcndao
import (
"context"
"sort"
"time"
"go-common/app/interface/main/mcn/conf"
"go-common/app/interface/main/mcn/dao/cache"
"go-common/app/interface/main/mcn/dao/global"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/library/log"
"github.com/bluele/gcache"
)
// RecommendPoolCache .
type RecommendPoolCache struct {
// map[tid] list
UpTidMap map[int16][]*mcnmodel.McnGetRecommendPoolInfo
TidTypeList []*mcnmodel.TidnameInfo
}
func (r *RecommendPoolCache) add(v *mcnmodel.McnGetRecommendPoolInfo) {
if v == nil {
return
}
if r.UpTidMap == nil {
r.UpTidMap = make(map[int16][]*mcnmodel.McnGetRecommendPoolInfo)
}
r.UpTidMap[v.ActiveTid] = append(r.UpTidMap[v.ActiveTid], v)
if v.ActiveTid != 0 {
// 加入到全部分类中
r.UpTidMap[0] = append(r.UpTidMap[0], v)
}
}
//RecommendSortFunc sort func
type RecommendSortFunc func(p1, p2 *mcnmodel.McnGetRecommendPoolInfo) bool
//RecommendDataSorter data sorter
type RecommendDataSorter struct {
Datas []*mcnmodel.McnGetRecommendPoolInfo
By RecommendSortFunc // Closure used in the Less method.
}
// Len is part of sort.Interface.
func (s *RecommendDataSorter) Len() int {
return len(s.Datas)
}
// Swap is part of sort.Interface.
func (s *RecommendDataSorter) Swap(i, j int) {
s.Datas[i], s.Datas[j] = s.Datas[j], s.Datas[i]
}
// Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter.
func (s *RecommendDataSorter) Less(i, j int) bool {
return s.By(s.Datas[i], s.Datas[j])
}
// RecommendSortByFansDesc .
func RecommendSortByFansDesc(p1, p2 *mcnmodel.McnGetRecommendPoolInfo) bool {
return p1.FansCount > p2.FansCount
}
// RecommendSortByFansAsc .
func RecommendSortByFansAsc(p1, p2 *mcnmodel.McnGetRecommendPoolInfo) bool {
return p1.FansCount < p2.FansCount
}
// RecommendSortByMonthFansDesc .
func RecommendSortByMonthFansDesc(p1, p2 *mcnmodel.McnGetRecommendPoolInfo) bool {
return p1.FansCountIncreaseMonth > p2.FansCountIncreaseMonth
}
// RecommendSortByArchiveCountDesc .
func RecommendSortByArchiveCountDesc(p1, p2 *mcnmodel.McnGetRecommendPoolInfo) bool {
return p1.ArchiveCount > p2.ArchiveCount
}
type loadRecommandFunc func() (res *RecommendPoolCache, err error)
func cacheKeyRecommend(int64) string {
return "recommend"
}
//rawGetRecommendPool get recommend pool
func (d *Dao) rawGetRecommendPool() (res []*mcnmodel.McnGetRecommendPoolInfo, err error) {
var dbresult []*mcnmodel.McnUpRecommendPool
err = d.mcndb.Where("state=?", mcnmodel.MCNUPRecommendStateOn).Find(&dbresult).Error
if err != nil {
log.Error("fail to get recommend pool, err=%s", err)
return
}
for _, v := range dbresult {
var info = &mcnmodel.McnGetRecommendPoolInfo{}
info.Copy(v)
res = append(res, info)
}
return
}
func (d *Dao) loadRecommendPool() (res *RecommendPoolCache, err error) {
recommendInfos, err := d.rawGetRecommendPool()
if err != nil {
log.Error("get recommend fail, err=%s", err)
return
}
var midMap = make(map[int64]struct{})
// 获取mid列表
for _, v := range recommendInfos {
midMap[v.UpMid] = struct{}{}
}
var mids []int64
for k := range midMap {
mids = append(mids, k)
}
// 获取账号信息,头像
accInfos, err := global.GetInfos(context.Background(), mids)
if err != nil || accInfos == nil {
log.Warn("get infos fail, err=%s", err)
}
var tidUnique = newTidNameUnique()
res = new(RecommendPoolCache)
for _, v := range recommendInfos {
if account, ok := accInfos[v.UpMid]; ok {
v.UpName = account.Name
}
v.TidName = cache.GetTidName(int64(v.ActiveTid))
// 这里DataTypeAccumulate只是用来记录一下
tidUnique.addTid(v.ActiveTid, v.TidName, mcnmodel.DataTypeAccumulate)
res.add(v)
}
res.TidTypeList = tidUnique.getList(mcnmodel.DataTypeAccumulate)
// 进行默认排序,按照粉丝数,降序
for k := range res.UpTidMap {
sort.Sort(&RecommendDataSorter{Datas: res.UpTidMap[k], By: RecommendSortByFansDesc})
}
return
}
func (d *Dao) getRecommendCache(keyCalc keyFunc, load loadRecommandFunc) (result *RecommendPoolCache, err error) {
var key = keyCalc(0)
v, err := d.localcache.Get(key)
if err != nil {
if err == gcache.KeyNotFoundError {
// load cache
v, err = load()
if err != nil {
log.Error("load cache error, key=%s. err=%s", key, err)
return
}
d.localcache.SetWithExpire(key, v, time.Duration(conf.Conf.RankCache.RecommendPoolExpireTime))
} else {
log.Error("get from gcache err, key=%s, err=%s", key, err)
return
}
}
if v == nil {
return
}
result, _ = v.(*RecommendPoolCache)
return
}
//GetRecommendPool get recommend pool
func (d *Dao) GetRecommendPool() (res *RecommendPoolCache, err error) {
res, err = d.getRecommendCache(cacheKeyRecommend, d.loadRecommendPool)
if err != nil {
log.Error("fail to get recommend pool, err=%s", err)
return
}
return
}

View File

@@ -0,0 +1,162 @@
package mcndao
import (
"go-common/app/interface/main/mcn/model/mcnmodel"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestMcndaoadd(t *testing.T) {
convey.Convey("add", t, func(ctx convey.C) {
var (
v = &mcnmodel.McnGetRecommendPoolInfo{}
s = &RecommendPoolCache{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
s.add(v)
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}
func TestMcndaoLen(t *testing.T) {
var (
s = &RecommendDataSorter{}
)
convey.Convey("Len", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := s.Len()
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoRecommendSortByFansDesc(t *testing.T) {
convey.Convey("RecommendSortByFansDesc", t, func(ctx convey.C) {
var (
p1 = &mcnmodel.McnGetRecommendPoolInfo{}
p2 = &mcnmodel.McnGetRecommendPoolInfo{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := RecommendSortByFansDesc(p1, p2)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoRecommendSortByFansAsc(t *testing.T) {
convey.Convey("RecommendSortByFansAsc", t, func(ctx convey.C) {
var (
p1 = &mcnmodel.McnGetRecommendPoolInfo{}
p2 = &mcnmodel.McnGetRecommendPoolInfo{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := RecommendSortByFansAsc(p1, p2)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoRecommendSortByMonthFansDesc(t *testing.T) {
convey.Convey("RecommendSortByMonthFansDesc", t, func(ctx convey.C) {
var (
p1 = &mcnmodel.McnGetRecommendPoolInfo{}
p2 = &mcnmodel.McnGetRecommendPoolInfo{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := RecommendSortByMonthFansDesc(p1, p2)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoRecommendSortByArchiveCountDesc(t *testing.T) {
convey.Convey("RecommendSortByArchiveCountDesc", t, func(ctx convey.C) {
var (
p1 = &mcnmodel.McnGetRecommendPoolInfo{}
p2 = &mcnmodel.McnGetRecommendPoolInfo{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := RecommendSortByArchiveCountDesc(p1, p2)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaocacheKeyRecommend(t *testing.T) {
convey.Convey("cacheKeyRecommend", t, func(ctx convey.C) {
var (
a1 = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := cacheKeyRecommend(a1)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaorawGetRecommendPool(t *testing.T) {
convey.Convey("rawGetRecommendPool", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.rawGetRecommendPool()
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(len(res), convey.ShouldBeGreaterThanOrEqualTo, 0)
})
})
})
}
func TestMcndaoloadRecommendPool(t *testing.T) {
convey.Convey("loadRecommendPool", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.loadRecommendPool()
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaogetRecommendCache(t *testing.T) {
convey.Convey("getRecommendCache", t, func(ctx convey.C) {
var (
keyCalc = cacheKeyRecommend
load = d.loadRecommendPool
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
result, err := d.getRecommendCache(keyCalc, load)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoGetRecommendPool(t *testing.T) {
convey.Convey("GetRecommendPool", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetRecommendPool()
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,255 @@
package mcndao
import (
"time"
adminmodel "go-common/app/admin/main/mcn/model"
"go-common/app/interface/main/mcn/model"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/app/interface/main/mcn/tool/validate"
"go-common/library/ecode"
"go-common/library/log"
"github.com/jinzhu/gorm"
"github.com/pkg/errors"
)
var (
signNotInStates = []model.MCNSignState{model.MCNSignStateOnDelete, model.MCNSignStateOnPreOpen, model.MCNSignStateOnExpire, model.MCNSignStateOnClear}
// 从高到低,先找到的返回
// 状态优先级:
// 0 封禁
// 1 签约
// 2
statePriority = []model.MCNSignState{
model.MCNSignStateOnBlock,
model.MCNSignStateOnSign,
model.MCNSignStateOnReject,
model.MCNSignStateOnReview,
model.MCNSignStateNoApply,
}
// mcnSign = mcnmodel.McnSign{}
// mcnUp = mcnmodel.McnUp{}
// UpPermissionApplyCannotApplyStates 在这此状态下不能再申请改变Up主
UpPermissionApplyCannotApplyStates = []adminmodel.MCNUPPermissionState{
adminmodel.MCNUPPermissionStateNoAuthorize, // 待Up主同意
adminmodel.MCNUPPermissionStateReview, // 待审核
}
// UpSignedStates up signed state
UpSignedStates = []model.MCNUPState{
model.MCNUPStateOnSign,
model.MCNUPStateOnPreOpen,
}
)
// GetMcnSignState .
// mcnList, it's all mcn sign found with the state
// state, the mcn's state of qualified, if multiple state found, will be return in priority
func (d *Dao) GetMcnSignState(fields string, mcnMid int64) (mcn *mcnmodel.McnSign, state model.MCNSignState, err error) {
var mcnList []*mcnmodel.McnSign
if err = d.mcndb.Select(fields).Where("mcn_mid=? and state not in(?)", mcnMid, signNotInStates).Find(&mcnList).Error; err != nil {
err = errors.WithStack(err)
return
}
if len(mcnList) == 0 {
log.Warn("mcn not exist, mcn id=%d", mcnMid)
err = ecode.NothingFound
return
}
var stateMap = make(map[model.MCNSignState]*mcnmodel.McnSign)
for _, v := range mcnList {
stateMap[model.MCNSignState(v.State)] = v
}
for _, v := range statePriority {
if mcnValue, ok := stateMap[v]; ok {
state = v
mcn = mcnValue
break
}
}
return
}
// GetUpBind .
func (d *Dao) GetUpBind(query interface{}, args ...interface{}) (upList []*mcnmodel.McnUp, err error) {
if err = d.mcndb.Select("*").Where(query, args...).Find(&upList).Error; err != nil {
if err == gorm.ErrRecordNotFound {
err = nil
} else {
log.Error("fail to get bind up from db, err=%s", err)
return
}
}
return
}
// BindUp .
func (d *Dao) BindUp(up *mcnmodel.McnUp, sign *mcnmodel.McnSign, arg *mcnmodel.McnBindUpApplyReq) (result *mcnmodel.McnUp, affectedRow int64, err error) {
if arg == nil || sign == nil {
return nil, 0, ecode.ServerErr
}
var db *gorm.DB
if up == nil {
up = &mcnmodel.McnUp{
SignID: sign.ID,
}
}
arg.CopyTo(up)
// 如果绑定自己,那么直接接受
if sign.McnMid == arg.UpMid {
up.State = model.MCNUPStateOnSign
// 签约周期为MCN的签约周期
if up.BeginDate == 0 {
up.BeginDate = sign.BeginDate
}
if up.EndDate == 0 {
up.EndDate = sign.EndDate
}
var (
now = time.Now()
date = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local)
)
if up.BeginDate.Time().After(date) {
up.State = model.MCNUPStateOnPreOpen
}
} else {
// 清除状态为未授权
up.State = model.MCNUPStateNoAuthorize
if !validate.RegHTTPCheck.MatchString(arg.ContractLink) || !validate.RegHTTPCheck.MatchString(arg.UpAuthLink) {
log.Error("contract link or up auth link is not http, arg=%v", arg)
err = ecode.RequestErr
return
}
}
// 判断开始时间与结束时间
if up.BeginDate == 0 || up.EndDate < up.BeginDate {
log.Error("begin date is after end date, arg=%v", arg)
err = ecode.MCNUpBindUpDateError
return
}
db = d.mcndb.Save(up)
affectedRow, err = db.RowsAffected, db.Error
if err != nil {
log.Error("save bind up info fail, err=%s, sign=%v", err, sign)
err = ecode.ServerErr
}
result = up
return
}
// UpdateBindUp .
func (d *Dao) UpdateBindUp(values map[string]interface{}, query interface{}, args ...interface{}) (affectedRow int64, err error) {
var db = d.mcndb.Table(mcnmodel.TableNameMcnUp).Where(query, args...).Updates(values)
affectedRow, err = db.RowsAffected, db.Error
if err != nil {
log.Error("fail to update bind up, err=%s", err)
}
return
}
//UpConfirm up confrim
func (d *Dao) UpConfirm(arg *mcnmodel.McnUpConfirmReq, state model.MCNUPState) (err error) {
var tx = d.mcndb.Begin()
defer func() {
if r := recover(); r != nil || err != nil {
tx.Rollback()
}
}()
var changeMap = map[string]interface{}{
"state": state,
"state_change_time": time.Now(),
}
if arg.Choice {
changeMap["confirm_time"] = time.Now()
}
err = tx.Table(mcnmodel.TableNameMcnUp).
Where("id=? and up_mid=? and state=?", arg.BindID, arg.UpMid, model.MCNUPStateNoAuthorize).
Updates(changeMap).Error
if err != nil {
log.Error("fail to update db, err=%s", err)
return
}
// 表示同意
if arg.Choice {
// 驳回其他的绑定请求
err = tx.Table(mcnmodel.TableNameMcnUp).
Where("id !=? and up_mid=? and state=?", arg.BindID, arg.UpMid, model.MCNUPStateNoAuthorize).
Updates(map[string]interface{}{
"state": model.MCNUPStateOnRefuse,
"state_change_time": time.Now(),
}).Error
if err != nil {
log.Error("fail to update db, err=%s", err)
return
}
}
return tx.Commit().Error
}
// GetBindInfo .
func (d *Dao) GetBindInfo(arg *mcnmodel.McnUpGetBindReq) (res *mcnmodel.McnGetBindReply, err error) {
var result mcnmodel.McnGetBindReply
err = d.mcndb.Raw(`select s.company_name, s.mcn_mid, u.up_auth_link, u.id as bind_id, u.permission as new_permission
from mcn_up as u inner join mcn_sign as s
on s.id = u.sign_id
where u.id = ? and u.up_mid=? and u.state = 0;`, arg.BindID, arg.UpMid).Find(&result).Error
res = &result
return
}
//GetMcnOldInfo 获取冷却中的信息
func (d *Dao) GetMcnOldInfo(mcnMid int64) (res *mcnmodel.McnSign, err error) {
res = new(mcnmodel.McnSign)
err = d.mcndb.Where("mcn_mid=? and state=?", mcnMid, model.MCNSignStateOnCooling).Order("id desc").Limit(1).Find(res).Error
if err != nil && err != gorm.ErrRecordNotFound {
log.Error("fail to get db, err=%s", err)
return
}
return
}
//GetUpPermissionApply 从permission apply表中读取数据
func (d *Dao) GetUpPermissionApply(fields string, query interface{}, args ...interface{}) (res []*mcnmodel.McnUpPermissionApply, err error) {
err = d.mcndb.Select(fields).Where(query, args...).Find(&res).Error
if err != nil {
log.Error("fail to get db, err=%v", err)
return
}
return
}
// GetUpPermissionBindInfo .
func (d *Dao) GetUpPermissionBindInfo(arg *mcnmodel.McnUpGetBindReq) (res *mcnmodel.McnGetBindReply, err error) {
var result mcnmodel.McnGetBindReply
err = d.mcndb.Raw(`select s.company_name, u.mcn_mid, u.up_auth_link, u.id as bind_id, u.old_permission, u.new_permission
from mcn_up_permission_apply as u inner join mcn_sign as s
on s.id = u.sign_id
where u.id = ? and u.up_mid=? and u.state = 0;`, arg.BindID, arg.UpMid).Find(&result).Error
res = &result
return
}
//UpPermissionConfirm up confrim
func (d *Dao) UpPermissionConfirm(arg *mcnmodel.McnUpConfirmReq, state adminmodel.MCNUPPermissionState) (err error) {
var db = d.mcndb
var changeMap = map[string]interface{}{
"state": state,
}
err = db.Table(mcnmodel.TableMcnUpPermissionApply).
Where("id=? and up_mid=? and state=?", arg.BindID, arg.UpMid, adminmodel.MCNUPPermissionStateNoAuthorize).
Updates(changeMap).Error
if err != nil {
log.Error("fail to update db, err=%s", err)
return
}
return
}

View File

@@ -0,0 +1,134 @@
package mcndao
import (
"testing"
"go-common/app/interface/main/mcn/model"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/library/ecode"
"github.com/smartystreets/goconvey/convey"
)
func TestMcndaoGetMcnSignState(t *testing.T) {
convey.Convey("GetMcnSignState", t, func(ctx convey.C) {
var (
fields = "*"
mcnMid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
mcn, state, err := d.GetMcnSignState(fields, mcnMid)
ctx.Convey("Then err should be nil.mcn,state should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldEqual, -404)
ctx.So(state, convey.ShouldNotBeNil)
ctx.So(mcn, convey.ShouldBeNil)
})
})
})
}
func TestMcndaoGetUpBind(t *testing.T) {
convey.Convey("GetUpBind", t, func(ctx convey.C) {
var (
query = "1=?"
args = "0"
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
upList, err := d.GetUpBind(query, args)
ctx.Convey("Then err should be nil.upList should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(upList, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoBindUp(t *testing.T) {
convey.Convey("BindUp", t, func(ctx convey.C) {
var (
up = &mcnmodel.McnUp{}
sign = &mcnmodel.McnSign{}
arg = &mcnmodel.McnBindUpApplyReq{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, affectedRow, err := d.BindUp(up, sign, arg)
ctx.Convey("Then err should be nil.result,affectedRow should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldEqual, 82010)
ctx.So(affectedRow, convey.ShouldEqual, 0)
ctx.So(result, convey.ShouldBeNil)
})
})
})
}
func TestMcndaoUpdateBindUp(t *testing.T) {
convey.Convey("UpdateBindUp", t, func(ctx convey.C) {
var (
values map[string]interface{}
query = interface{}(0)
args = interface{}(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
affectedRow, err := d.UpdateBindUp(values, query, args)
ctx.Convey("Then err should be nil.affectedRow should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affectedRow, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoUpConfirm(t *testing.T) {
convey.Convey("UpConfirm", t, func(ctx convey.C) {
var (
arg = &mcnmodel.McnUpConfirmReq{}
state model.MCNUPState
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.UpConfirm(arg, state)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMcndaoGetBindInfo(t *testing.T) {
convey.Convey("GetBindInfo", t, func(ctx convey.C) {
var (
arg = &mcnmodel.McnUpGetBindReq{}
)
arg.BindID = 10
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.GetBindInfo(arg)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
if err == ecode.NothingFound {
ctx.So(err, convey.ShouldNotBeNil)
} else {
ctx.So(err, convey.ShouldBeNil)
}
if res != nil {
ctx.So(res, convey.ShouldNotBeNil)
} else {
ctx.So(res, convey.ShouldBeNil)
}
})
})
})
}
func TestMcndaoGetMcnOldInfo(t *testing.T) {
convey.Convey("GetMcnOldInfo", t, func(ctx convey.C) {
var (
mcnMid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.GetMcnOldInfo(mcnMid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldEqual, -404)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,56 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"msg.go",
],
importpath = "go-common/app/interface/main/mcn/dao/msg",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/mcn/conf:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/xstr:go_default_library",
"//vendor/github.com/pkg/errors: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"],
)
go_test(
name = "go_default_test",
srcs = [
"dao_test.go",
"msg_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/mcn/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
"//vendor/gopkg.in/h2non/gock.v1:go_default_library",
],
)

View File

@@ -0,0 +1,28 @@
package msg
import (
"go-common/app/interface/main/mcn/conf"
bm "go-common/library/net/http/blademaster"
)
const (
msgurl = "/api/notify/send.user.notify.do"
)
// Dao .
type Dao struct {
c *conf.Config
client *bm.Client
msgURL string
}
// New new a Dao and return.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
// http client
client: bm.NewClient(c.HTTPClient),
msgURL: c.Host.Msg + msgurl,
}
return
}

View File

@@ -0,0 +1,48 @@
package msg
import (
"flag"
"os"
"strings"
"testing"
"go-common/app/interface/main/mcn/conf"
"gopkg.in/h2non/gock.v1"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.mcn-interface")
flag.Set("conf_token", "49e4671bafbf93059aeb602685052ca0")
flag.Set("tree_id", "58909")
flag.Set("conf_version", "docker-1")
flag.Set("deploy_env", "uat")
flag.Set("conf_host", "config.bilibili.co")
flag.Set("conf_path", "/tmp")
flag.Set("region", "sh")
flag.Set("zone", "sh001")
} else {
flag.Set("conf", "../../cmd/mcn-interface.toml")
}
if os.Getenv("UT_LOCAL_TEST") != "" {
flag.Set("conf", "../../cmd/mcn-interface.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
d.client.SetTransport(gock.DefaultTransport)
os.Exit(m.Run())
}
func httpMock(method, url string) *gock.Request {
r := gock.New(url)
r.Method = strings.ToUpper(method)
return r
}

View File

@@ -0,0 +1,61 @@
package msg
import (
"context"
"net/url"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/xstr"
"github.com/pkg/errors"
)
// MutliSendSysMsg Mutli send sys msg.
func (d *Dao) MutliSendSysMsg(c context.Context, allUids []int64, mc, title string, context string, ip string) (err error) {
var times int
ulen := len(allUids)
if ulen%100 == 0 {
times = ulen / 100
} else {
times = ulen/100 + 1
}
var uids []int64
for i := 0; i < times; i++ {
if i == times-1 {
uids = allUids[i*100:]
} else {
uids = allUids[i*100 : (i+1)*100]
}
if err = d.SendSysMsg(c, uids, mc, title, context, ip); err != nil {
continue
}
}
return
}
// SendSysMsg send sys msg.
func (d *Dao) SendSysMsg(c context.Context, uids []int64, mc, title string, context string, ip string) (err error) {
params := url.Values{}
params.Set("mc", mc)
params.Set("title", title)
params.Set("data_type", "4")
params.Set("context", context)
params.Set("mid_list", xstr.JoinInts(uids))
var res struct {
Code int `json:"code"`
Data *struct {
Status int8 `json:"status"`
Remark string `json:"remark"`
} `json:"data"`
}
if err = d.client.Post(c, d.msgURL, ip, params, &res); err != nil {
return
}
if res.Code != 0 {
err = errors.Wrapf(ecode.Int(res.Code), "SendSysMsg d.client.Post(%s,%d)", d.msgURL+"?"+params.Encode(), res.Code)
} else {
log.Info("send msg ok, resdata=%+v", res.Data)
}
return
}

View File

@@ -0,0 +1,51 @@
package msg
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
"gopkg.in/h2non/gock.v1"
)
func TestMsgMutliSendSysMsg(t *testing.T) {
convey.Convey("MutliSendSysMsg", t, func(ctx convey.C) {
var (
c = context.Background()
allUids = []int64{}
mc = ""
title = ""
context = ""
ip = ""
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.MutliSendSysMsg(c, allUids, mc, title, context, ip)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMsgSendSysMsg(t *testing.T) {
convey.Convey("SendSysMsg", t, func(ctx convey.C) {
var (
c = context.Background()
uids = []int64{}
mc = ""
title = ""
context = ""
ip = ""
)
defer gock.OffAll()
httpMock("POST", "http://message.bilibili.co/api/notify/send.user.notify.do").Reply(200).JSON(`{"code": 0}`)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.SendSysMsg(c, uids, mc, title, context, ip)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

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 = [
"base_model.go",
"model.go",
"request_base.go",
],
importpath = "go-common/app/interface/main/mcn/model",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/interface/main/mcn/model/datamodel:all-srcs",
"//app/interface/main/mcn/model/mcnmodel:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,59 @@
package model
import (
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"fmt"
"hash"
"math/rand"
"net/url"
"path/filepath"
"strings"
"time"
)
// const .
const (
_template = "%s\n%s\n%s\n%d\n"
BfsEasyPath = "/bfs/mcn"
TimeFormatSec = "2006-01-02 15:04:05"
TimeFormatDay = "2006-01-02"
)
// BuildBfsURL is.
func BuildBfsURL(raw string, appkey, secret, bucket, ePath string) string {
if raw == "" {
return ""
}
ori, err := url.Parse(raw)
if err != nil {
return raw
}
if strings.HasPrefix(ori.Path, ePath) {
token := authorize(appkey, secret, "GET", bucket, filepath.Base(ori.Path), time.Now().Unix())
p := url.Values{}
p.Set("token", token)
ori.RawQuery = p.Encode()
}
if ori.Hostname() == "" {
ori.Host = fmt.Sprintf("i%d.hdslb.com", rand.Int63n(3))
ori.Scheme = "http"
}
return ori.String()
}
// Authorize returns authorization for upload file to bfs
func authorize(key, secret, method, bucket, file string, expire int64) (authorization string) {
var (
content string
mac hash.Hash
signature string
)
content = fmt.Sprintf(_template, method, bucket, file, expire)
mac = hmac.New(sha1.New, []byte(secret))
mac.Write([]byte(content))
signature = base64.StdEncoding.EncodeToString(mac.Sum(nil))
authorization = fmt.Sprintf("%s:%s:%d", key, signature, expire)
return
}

View File

@@ -0,0 +1,40 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"api.go",
"tables.go",
],
importpath = "go-common/app/interface/main/mcn/model/datamodel",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = ["//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"],
)
go_test(
name = "go_default_test",
srcs = ["tables_test.go"],
embed = [":go_default_library"],
tags = ["automanaged"],
)

View File

@@ -0,0 +1,38 @@
package datamodel
import (
"time"
)
// GetLastDay get data daily
func GetLastDay() time.Time {
//return time.Date(2018, 11, 18, 0, 0, 0, 0, time.Local)
now := time.Now()
return time.Date(now.Year(), now.Month(), now.Day()-1, 0, 0, 0, 0, time.Local)
}
// GetLastWeek get data weekly
func GetLastWeek() time.Time {
//return time.Date(2018, 11, 18, 0, 0, 0, 0, time.Local)
now := time.Now()
gDate := getTuesday(now)
if now.Before(gDate.Add(12 * time.Hour)) {
return gDate.AddDate(0, 0, -9)
}
return gDate.AddDate(0, 0, -2)
}
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 == int(time.Sunday) {
weekday = int(time.Saturday) + 1
}
d := time.Duration(-weekday+2) * 24 * time.Hour
return t.Truncate(time.Hour).Add(d)
}

View File

@@ -0,0 +1,286 @@
package datamodel
import (
"strconv"
"time"
xtime "go-common/library/time"
)
// LogTime
// deserialize format "2006-01-02"
// serialize format unix timestamp
type LogTime time.Time
const (
timeLayout = "2006-01-02"
timeLayoutWithQuote = `"2006-01-02"`
)
//MarshalJSON marshal logdate as timestamp
func (t *LogTime) MarshalJSON() ([]byte, error) {
var scratch [64]byte
var dst = strconv.AppendInt(scratch[:0], (*time.Time)(t).Unix(), 10)
return dst, nil
}
//UnmarshalJSON parse timestamp or something like "2006-01-02"
func (t *LogTime) UnmarshalJSON(b []byte) (err error) {
var str = string(b)
if str == "null" {
return nil
}
if len(str) == 0 {
return
}
if str[0] == '"' {
// Fractional seconds are handled implicitly by Parse.
tmp, e := time.ParseInLocation(timeLayoutWithQuote, string(b), time.Local)
if e != nil {
err = e
return
}
*t = LogTime(tmp)
} else {
// parse as timestamp
num, e := strconv.ParseInt(str, 10, 64)
if e != nil {
err = e
return
}
*t = LogTime(time.Unix(num, 0))
}
return
}
//Time export library time
func (t *LogTime) Time() xtime.Time {
return xtime.Time(time.Time(*t).Unix())
}
// see mcn_data.sql for more info
//McnStatisticBaseInfo2 new from data center
type McnStatisticBaseInfo2 struct {
DanmuAll int64 `json:"danmu_all"`
DanmuInc int64 `json:"danmu_inc"`
ReplyAll int64 `json:"reply_all"`
ReplyInc int64 `json:"reply_inc"`
ShareAll int64 `json:"share_all"`
ShareInc int64 `json:"share_inc"`
CoinAll int64 `json:"coin_all"`
CoinInc int64 `json:"coin_inc"`
FavAll int64 `json:"fav_all"`
FavInc int64 `json:"fav_inc"`
LikeAll int64 `json:"like_all"`
LikeInc int64 `json:"like_inc"`
Ctime time.Time `json:"-"`
Mtime time.Time `json:"-"`
}
//DmConMcnArchiveD 投稿数及昨日增量
type DmConMcnArchiveD struct {
McnStatisticBaseInfo2
ID int64 `json:"-"`
SignID int64 `json:"-"`
McnMid int64 `json:"-"`
LogDate LogTime `json:"log_date"`
UpAll int64 `json:"up_all"`
ArchiveAll int64 `json:"archive_all"`
ArchiveInc int64 `json:"archive_inc"`
PlayAll int64 `json:"play_all"`
PlayInc int64 `json:"play_inc"`
FansAll int64 `json:"fans_all"`
FansInc int64 `json:"fans_inc"`
}
//DmConMcnIndexIncD 播放/弹幕/评论/分享/硬币/收藏/点赞数每日增量
type DmConMcnIndexIncD struct {
ID int64 `json:"-"`
SignID int64 `json:"-"`
McnMid int64 `json:"-"`
LogDate LogTime `json:"log_date"`
Value int64 `json:"value"`
Type string `json:"-"`
Ctime time.Time `json:"-"`
Mtime time.Time `json:"-"`
}
//DmConMcnIndexSourceD mcn播放/弹幕/评论/分享/硬币/收藏/点赞来源分区
type DmConMcnIndexSourceD struct {
ID int64 `json:"-"`
SignID int64 `json:"-"`
McnMid int64 `json:"-"`
LogDate LogTime `json:"log_date"`
TypeID int64 `json:"type_id"`
Rank int64 `json:"rank"`
Value int64 `json:"value"`
Type string `json:"-"`
Ctime time.Time `json:"-"`
Mtime time.Time `json:"-"`
TypeName string `json:"type_name"`
}
//DmConMcnPlaySourceD #mcn稿件播放来源占比
type DmConMcnPlaySourceD struct {
ID int64 `json:"-"`
SignID int64 `json:"-"`
McnMid int64 `json:"-"`
LogDate LogTime `json:"log_date"`
Iphone int64 `json:"iphone"`
Android int64 `json:"android"`
Pc int64 `json:"pc"`
H5 int64 `json:"h5"`
Other int64 `json:"other"`
Ctime time.Time `json:"-"`
Mtime time.Time `json:"-"`
}
//DmConMcnFansSexW #游客/粉丝性别占比
type DmConMcnFansSexW struct {
ID int64 `json:"-"`
SignID int64 `json:"-"`
McnMid int64 `json:"-"`
LogDate LogTime `json:"log_date"`
Male int64 `json:"male"`
Female int64 `json:"female"`
Type string `json:"-"`
Ctime time.Time `json:"-"`
Mtime time.Time `json:"-"`
}
//DmConMcnFansAgeW #游客/粉丝年龄分布
type DmConMcnFansAgeW struct {
ID int64 `json:"-"`
SignID int64 `json:"-"`
McnMid int64 `json:"-"`
LogDate LogTime `json:"log_date"`
A int64 `json:"a"` //'0-16岁人数',
B int64 `json:"b"` //'16-25岁人数',
C int64 `json:"c"` //'25-40岁人数',
D int64 `json:"d"` //'40岁以上人数',
Type string `json:"-"` //'粉丝类型guest、fans',
Ctime time.Time `json:"-"`
Mtime time.Time `json:"-"`
}
//DmConMcnFansPlayWayW 游客/粉丝观看途径
type DmConMcnFansPlayWayW struct {
ID int64 `json:"-"`
SignID int64 `json:"-"`
McnMid int64 `json:"-"`
LogDate LogTime `json:"log_date"`
App int64 `json:"app"`
Pc int64 `json:"pc"`
Outside int64 `json:"outside"`
Other int64 `json:"other"`
Type string `json:"-"`
Ctime time.Time `json:"-"`
Mtime time.Time `json:"-"`
}
//DmConMcnFansAreaW #游客/粉丝地区分布
type DmConMcnFansAreaW struct {
ID int64 `json:"-"`
SignID int64 `json:"-"`
McnMid int64 `json:"-"`
LogDate LogTime `json:"log_date"`
Province string `json:"province"`
User int64 `json:"user"`
Type string `json:"-"`
Ctime time.Time `json:"-"`
Mtime time.Time `json:"-"`
}
//DmConMcnFansTypeW #游客/粉丝倾向分布
type DmConMcnFansTypeW struct {
ID int64 `json:"-"`
SignID int64 `json:"-"`
McnMid int64 `json:"-"`
LogDate LogTime `json:"log_date"`
TypeID int64 `json:"type_id"`
Play int64 `json:"play"`
Type string `json:"-"`
Ctime time.Time `json:"-"`
Mtime time.Time `json:"-"`
TypeName string `json:"type_name"`
}
//DmConMcnFansD #mcn粉丝数相关
type DmConMcnFansD struct {
ID int64 `json:"-"`
SignId int64 `json:"-"`
McnMid int64 `json:"-"`
LogDate LogTime `json:"log_date"`
FansAll int64 `json:"fans_all"`
FansInc int64 `json:"fans_inc"`
ActFans int64 `json:"act_fans"`
FansDecAll int64 `json:"fans_dec_all"`
FansDec int64 `json:"fans_dec"`
ViewFansRate float64 `json:"view_fans_rate"`
ActFansRate float64 `json:"act_fans_rate"`
ReplyFansRate float64 `json:"reply_fans_rate"`
DanmuFansRate float64 `json:"danmu_fans_rate"`
CoinFansRate float64 `json:"coin_fans_rate"`
LikeFansRate float64 `json:"like_fans_rate"`
FavFansRate float64 `json:"fav_fans_rate"`
ShareFansRate float64 `json:"share_fans_rate"`
LiveGiftFansRate float64 `json:"live_gift_fans_rate"`
LiveDanmuFansRate float64 `json:"live_danmu_fans_rate"`
Ctime time.Time `json:"-"`
Mtime time.Time `json:"-"`
}
//DmConMcnFansIncD #mcn粉丝按天增量
type DmConMcnFansIncD struct {
ID int64 `json:"-"`
SignID int64 `json:"-"`
McnMid int64 `json:"-"`
LogDate LogTime `json:"log_date"`
FansInc int64 `json:"fans_inc"`
Ctime time.Time `json:"-"`
Mtime time.Time `json:"-"`
}
//DmConMcnFansDecD #mcn粉丝按天取关数
type DmConMcnFansDecD struct {
ID int64 `json:"-"`
SignID int64 `json:"-"`
McnMid int64 `json:"-"`
LogDate LogTime `json:"log_date"`
FansDec int64 `json:"fans_dec"`
Ctime time.Time `json:"-"`
Mtime time.Time `json:"-"`
}
//DmConMcnFansAttentionWayD #mcn粉丝关注渠道
type DmConMcnFansAttentionWayD struct {
ID int64 `json:"-"`
SignID int64 `json:"-"`
McnMid int64 `json:"-"`
LogDate LogTime `json:"log_date"`
Homepage int64 `json:"homepage"`
Video int64 `json:"video"`
Article int64 `json:"article"`
Music int64 `json:"music"`
Other int64 `json:"other"`
Ctime time.Time `json:"-"`
Mtime time.Time `json:"-"`
}
// DmConMcnFansTagW #游客/粉丝标签地图分布
type DmConMcnFansTagW struct {
ID int64 `json:"-"`
SignID int64 `json:"-"`
McnMid int64 `json:"-"`
LogDate LogTime `json:"log_date"`
TagID int64 `json:"tag_id"`
Play int64 `json:"play"`
Type string `json:"-"`
Ctime time.Time `json:"-"`
Mtime time.Time `json:"-"`
TagName string `json:"tag_name"`
}

View File

@@ -0,0 +1,39 @@
package datamodel
import (
"testing"
"time"
)
type timeTestCase struct {
In []byte
Out time.Time
}
func timeHelper(tm time.Time, err error) time.Time {
return tm
}
func TestLogTime_UnmarshalJSON(t *testing.T) {
var (
testcase = []timeTestCase{
{[]byte(`"2018-11-11"`), timeHelper(time.ParseInLocation("2006-01-02", "2018-11-11", time.Local))},
{[]byte(`1542795906`), time.Unix(1542795906, 0)},
}
)
for _, testcase := range testcase {
var ltm LogTime
var err = ltm.UnmarshalJSON(testcase.In)
if err != nil {
t.Errorf("err=%v", err)
t.Fail()
continue
}
if int64(ltm.Time()) != testcase.Out.Unix() {
t.Errorf("expect=%d, get=%d", testcase.Out, ltm.Time())
t.Fail()
continue
}
}
}

View File

@@ -0,0 +1,56 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"cmd.go",
"creative.go",
"mcncache.go",
"reply.go",
"req.go",
"tables.go",
"upcheck.go",
],
importpath = "go-common/app/interface/main/mcn/model/mcnmodel",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/mcn/model:go_default_library",
"//app/interface/main/mcn/model:go_default_library",
"//app/interface/main/mcn/model/datamodel:go_default_library",
"//app/interface/main/mcn/tool/validate:go_default_library",
"//app/service/main/archive/api: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"],
)
go_test(
name = "go_default_test",
srcs = ["reply_test.go"],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/admin/main/mcn/model:go_default_library",
"//app/interface/main/mcn/model:go_default_library",
],
)

View File

@@ -0,0 +1,10 @@
package mcnmodel
//EmptyCmd empty cmd
type EmptyCmd struct {
}
//CmdReloadRank reload rank
type CmdReloadRank struct {
SignID int64 `form:"sign_id"`
}

View File

@@ -0,0 +1,89 @@
package mcnmodel
// CreativeCommonReq common creative
type CreativeCommonReq struct {
UpMid int64 `form:"mid" validate:"required"`
McnMid int64
}
// AidCommonReq common aid
type AidCommonReq struct {
CreativeCommonReq
Aid int64 `form:"aid" validate:"required"`
}
// DataCommonReq request params
type DataCommonReq struct {
CreativeCommonReq
Type int8 `form:"type" validate:"required"`
}
// ArchivesReq request params
type ArchivesReq struct {
CreativeCommonReq
Pn int64 `form:"pn"`
Ps int64 `form:"ps"`
Order string `form:"order"`
TID int64 `form:"tid"`
KeyWord string `form:"keyword"`
Status string `form:"status" validate:"required"`
Coop int16 `form:"coop"`
}
// ArchiveHistoryListReq request params
type ArchiveHistoryListReq = AidCommonReq
// ArchiveVideosReq request params
type ArchiveVideosReq = AidCommonReq
// DataArchiveReq request params
type DataArchiveReq = AidCommonReq
// DataVideoQuitReq request params
type DataVideoQuitReq struct {
CreativeCommonReq
Cid int64 `form:"cid" validate:"required"`
}
// DanmuDistriReq .
type DanmuDistriReq struct {
CreativeCommonReq
Aid int64 `form:"aid" validate:"required"`
Cid int64 `form:"cid" validate:"required"`
}
// DataBaseReq request params
type DataBaseReq = CreativeCommonReq
// DataTrendReq request params
type DataTrendReq = CreativeCommonReq
// DataActionReq request params
type DataActionReq = CreativeCommonReq
// DataFanReq request params
type DataFanReq = CreativeCommonReq
// DataPandectReq request params
type DataPandectReq = DataCommonReq
// DataSurveyReq request params
type DataSurveyReq = DataCommonReq
// DataPlaySourceReq request params
type DataPlaySourceReq = CreativeCommonReq
// DataPlayAnalysisReq request params
type DataPlayAnalysisReq struct {
CreativeCommonReq
Copyright int8 `form:"copyright"`
}
// DataArticleRankReq request params
type DataArticleRankReq = DataCommonReq

View File

@@ -0,0 +1,14 @@
package mcnmodel
import "time"
// PublicationPriceCache .
type PublicationPriceCache struct {
ModifyTime time.Time `json:"mtime"`
}
// UpPermissionCache .
type UpPermissionCache struct {
IsNull bool `json:"is_null"` // 缓存用来标记
Permission uint32 `json:"permission"`
}

View File

@@ -0,0 +1,488 @@
package mcnmodel
import (
"sort"
mcnadminmodel "go-common/app/admin/main/mcn/model"
"go-common/app/interface/main/mcn/model"
"go-common/app/interface/main/mcn/model/datamodel"
arcgrpc "go-common/app/service/main/archive/api"
"go-common/library/time"
)
// McnGetStateReply .
type McnGetStateReply struct {
State int8 `json:"state"`
RejectReason string `json:"reject_reason"`
}
// CommonReply reply with nothing, base struct
type CommonReply struct{}
//Sorter can sort
type Sorter interface {
Sort()
}
// McnGetBindReply .
type McnGetBindReply struct {
BindID int64 `json:"bind_id" gorm:"column:bind_id"`
CompanyName string `json:"company_name" gorm:"column:company_name"`
McnMid uint32 `json:"mcn_mid" gorm:"column:mcn_mid"`
McnName string `json:"mcn_name"`
UpAuthLink string `json:"up_auth_link" gorm:"column:up_auth_link"`
OldPerm uint32 `json:"-" gorm:"column:old_permission"`
NewPerm uint32 `json:"-" gorm:"column:new_permission"`
OldPermission mcnadminmodel.Permits `json:"old_permission"`
NewPermission mcnadminmodel.Permits `json:"new_permission"`
}
//Finish call this before send
func (s *McnGetBindReply) Finish() {
s.OldPermission.SetAttrPermitVal(s.OldPerm)
s.NewPermission.SetAttrPermitVal(s.NewPerm)
}
// McnGetDataSummaryReply .
type McnGetDataSummaryReply struct {
datamodel.McnStatisticBaseInfo2
IsNull bool `json:"is_null"` // 缓存用来标记
UpCount int64 `json:"up_count"`
UpCountDiff int64 `json:"-"`
FansCountAccumulate int64 `json:"fans_count_accumulate"`
FansCountDiff int64 `json:"fans_count_diff"`
PlayCountAccumulate int64 `json:"play_count_accumulate"`
PlayCountDiff int64 `json:"play_count_diff"`
ArchiveCountAccumulate int64 `json:"archive_count_accumulate"`
ArchiveCountDiff int64 `json:"archive_count_diff"`
GenerateDate time.Time `json:"generate_date"`
}
// CopyFrom .
func (m *McnGetDataSummaryReply) CopyFrom(v *McnDataSummary) {
if v == nil {
return
}
m.UpCount = int64(v.UpCount)
m.FansCountAccumulate = int64(v.FansCountAccumulate)
m.PlayCountAccumulate = int64(v.PlayCountAccumulate)
m.ArchiveCountAccumulate = int64(v.ArchiveCountAccumulate)
m.GenerateDate = v.GenerateDate
}
//CopyFromDmConMcnArchiveD .
func (m *McnGetDataSummaryReply) CopyFromDmConMcnArchiveD(v *datamodel.DmConMcnArchiveD) {
if v == nil {
return
}
m.UpCount = v.UpAll
// m.UpCountDiff 不再使用了。
m.ArchiveCountAccumulate = v.ArchiveAll
m.ArchiveCountDiff = v.ArchiveInc
m.PlayCountAccumulate = v.PlayAll
m.PlayCountDiff = v.PlayInc
m.FansCountAccumulate = v.FansAll
m.FansCountDiff = v.FansInc
m.McnStatisticBaseInfo2 = v.McnStatisticBaseInfo2
m.GenerateDate = v.LogDate.Time()
}
// CalcDiff .
func (m *McnGetDataSummaryReply) CalcDiff(lastDay *McnDataSummary) {
if lastDay == nil {
return
}
m.UpCountDiff = m.UpCount - int64(lastDay.UpCount)
m.FansCountDiff = m.FansCountAccumulate - int64(lastDay.FansCountAccumulate)
m.PlayCountDiff = m.PlayCountAccumulate - int64(lastDay.PlayCountAccumulate)
m.ArchiveCountDiff = m.ArchiveCountAccumulate - int64(lastDay.ArchiveCountAccumulate)
}
// McnUpDataInfo mcn data
type McnUpDataInfo struct {
McnDataUp
ActiveTid int16 `json:"active_tid"`
TidName string `json:"tid_name"`
BeginDate time.Time `json:"begin_date" gorm:"column:begin_date"`
EndDate time.Time `json:"end_date" gorm:"column:end_date"`
State int8 `json:"state" gorm:"column:state"`
Name string `json:"name"`
Permission uint32 `gorm:"column:permission" json:"-"`
PublicationPrice int64 `gorm:"column:publication_price" json:"publication_price"` // 单位1/1000 元
Permits mcnadminmodel.Permits `json:"permits"`
}
// HideData if state is not right, hide the data
func (m *McnUpDataInfo) HideData(hideDate bool) {
m.FansIncreaseMonth = 0
m.PlayCount = 0
m.ArchiveCount = 0
m.FansIncreaseAccumulate = 0
m.FansCount = 0
m.FansCountActive = 0
if hideDate {
m.BeginDate = 0
m.EndDate = 0
}
}
//Finish call finish before send out
func (m *McnUpDataInfo) Finish() {
m.Permits.SetAttrPermitVal(m.Permission)
}
// McnBindUpApplyReply .
type McnBindUpApplyReply struct {
BindID int64 `json:"bind_id"`
}
// McnGetUpListReply list
type McnGetUpListReply struct {
Result []*McnUpDataInfo `json:"result"`
model.PageResult
}
//Finish call finish before send out
func (m *McnGetUpListReply) Finish() {
for _, v := range m.Result {
v.Finish()
}
}
// McnExistReply exist
type McnExistReply struct {
Exist int `json:"exist"`
}
// McnGetAccountReply reply
type McnGetAccountReply struct {
Mid int64 `json:"mid"`
Name string `json:"name"`
}
// McnGetMcnOldInfoReply req
type McnGetMcnOldInfoReply struct {
CompanyName string `json:"company_name"`
CompanyLicenseID string `json:"company_license_id"`
ContactName string `json:"contact_name"`
ContactTitle string `json:"contact_title"`
ContactIdcard string `json:"contact_idcard"`
ContactPhone string `json:"contact_phone"`
}
// Copy .
func (m *McnGetMcnOldInfoReply) Copy(v *McnSign) {
if v == nil {
return
}
m.CompanyName = v.CompanyName
m.CompanyLicenseID = v.CompanyLicenseID
m.ContactName = v.ContactName
m.ContactTitle = v.ContactTitle
m.ContactIdcard = v.ContactIdcard
m.ContactPhone = v.ContactPhone
}
// RankDataInterface 用来取排行用的数据
type RankDataInterface interface {
GetTid() int16
GetDataType() DataType
GetValue() int64
}
// RankDataBase 基本排行信息
type RankDataBase struct {
Tid int16 `json:"tid"`
DataType DataType `json:"data_type"`
}
// GetTid .
func (r *RankDataBase) GetTid() int16 {
return r.Tid
}
// GetDataType .
func (r *RankDataBase) GetDataType() DataType {
return r.DataType
}
// RankUpFansInfo reply info
type RankUpFansInfo struct {
RankDataBase
Mid int64 `json:"mid"`
UpFaceLink string `json:"up_face_link"`
Name string `json:"name"`
FansIncrease int64 `json:"fans_increase"`
FansAccumulate int64 `json:"fans_accumulate"`
TidName string `json:"tid_name"`
}
// GetValue .
func (r *RankUpFansInfo) GetValue() int64 {
return r.FansIncrease
}
// Copy copy from rank up .
func (r *RankUpFansInfo) Copy(v *McnRankUpFan) {
if v == nil {
return
}
r.DataType = v.DataType
r.Tid = v.ActiveTid
r.Mid = v.UpMid
r.FansIncrease = v.Value1
r.FansAccumulate = v.Value2
}
// McnGetRankUpFansReply reply
type McnGetRankUpFansReply struct {
Result []RankDataInterface `json:"result"` // 按顺序进行排名
TypeList []*TidnameInfo `json:"type_list"`
}
// RankArchiveLikeInfo archive like rank info
type RankArchiveLikeInfo struct {
RankDataBase
ArchiveID int64 `json:"archive_id"` // 稿件ID
ArchiveTitle string `json:"archive_title"`
Pic string `json:"pic"` // 封面
TidName string `json:"tid_name"`
LikesIncrease int64 `json:"likes_increase"`
LikesAccumulate int64 `json:"likes_accumulate"`
PlayIncrease int64 `json:"play_increase"`
Ctime time.Time `json:"ctime"`
Author arcgrpc.Author `json:"author"` // up主信息
Stat arcgrpc.Stat `json:"stat"` // 统计信息
}
// GetValue .
func (r *RankArchiveLikeInfo) GetValue() int64 {
return r.LikesIncrease
}
// CopyFromDB .
func (r *RankArchiveLikeInfo) CopyFromDB(v *McnRankArchiveLike) {
if v == nil {
return
}
r.ArchiveID = v.ArchiveID
r.LikesIncrease = v.LikeCount
r.Tid = v.Tid
r.DataType = v.DataType
r.PlayIncrease = v.PlayIncr
}
// CopyFromArchive copy from archive info from archive service
func (r *RankArchiveLikeInfo) CopyFromArchive(v *arcgrpc.Arc) {
if v == nil {
return
}
r.ArchiveTitle = v.Title
r.Pic = v.Pic
r.Ctime = v.Ctime
r.TidName = v.TypeName
r.Author = v.Author
r.Stat = v.Stat
r.Tid = int16(v.TypeID)
r.LikesAccumulate = int64(v.Stat.Like)
}
// TidnameInfo tid name
type TidnameInfo struct {
Tid int16 `json:"tid"`
Name string `json:"name"`
}
// McnGetRecommendPoolInfo recomend info
type McnGetRecommendPoolInfo struct {
UpMid int64 `json:"up_mid"`
FansCount int64 `json:"fans_count"`
FansCountIncreaseMonth int64 `json:"fans_count_increase_month"`
ArchiveCount int64 `json:"archive_count"`
ActiveTid int16 `json:"active_tid"`
UpName string `json:"up_name"`
TidName string `json:"tid_name"`
}
// Copy copy from db
func (m *McnGetRecommendPoolInfo) Copy(v *McnUpRecommendPool) {
if v == nil {
return
}
m.UpMid = v.UpMid
m.FansCount = v.FansCount
m.FansCountIncreaseMonth = v.FansCountIncreaseMonth
m.ArchiveCount = v.ArchiveCount
m.ActiveTid = v.ActiveTid
}
// McnGetRecommendPoolReply result
type McnGetRecommendPoolReply struct {
model.PageResult
Result []*McnGetRecommendPoolInfo `json:"result"`
}
// McnGetRecommendPoolTidListReply result
type McnGetRecommendPoolTidListReply struct {
Result []*TidnameInfo `json:"result"`
}
// --------------------------- 三期需求
// McnGetIndexIncReply 播放/弹幕/评论/分享/硬币/收藏/点赞数每日增量
type McnGetIndexIncReply struct {
Result []*datamodel.DmConMcnIndexIncD `json:"result"`
}
//McnGetIndexSourceReply 播放/弹幕/评论/分享/硬币/收藏/点赞来源分区
type McnGetIndexSourceReply struct {
Result []*datamodel.DmConMcnIndexSourceD `json:"result"`
}
//Sort sort
func (s *McnGetIndexSourceReply) Sort() {
sort.Slice(s.Result, func(i, j int) bool {
return s.Result[i].Value > s.Result[j].Value
})
}
//McnGetPlaySourceReply #mcn稿件播放来源占比
type McnGetPlaySourceReply struct {
datamodel.DmConMcnPlaySourceD
}
// McnGetMcnFansReply mcn粉丝基本数据
type McnGetMcnFansReply struct {
datamodel.DmConMcnFansD
}
//McnGetMcnFansIncReply mcn粉丝按天增量
type McnGetMcnFansIncReply struct {
Result []*datamodel.DmConMcnFansIncD `json:"result"`
}
//McnGetMcnFansDecReply mcn粉丝按天取关数
type McnGetMcnFansDecReply struct {
Result []*datamodel.DmConMcnFansDecD `json:"result"`
}
//McnGetMcnFansAttentionWayReply mcn粉丝关注渠道
type McnGetMcnFansAttentionWayReply struct {
datamodel.DmConMcnFansAttentionWayD
}
// McnGetBaseFansAttrReply # mcn 性别占比 + 观众年龄 + 观看途径
type McnGetBaseFansAttrReply struct {
FansSex *datamodel.DmConMcnFansSexW `json:"fans_sex"`
FansAge *datamodel.DmConMcnFansAgeW `json:"fans_age"`
FansPlayWay *datamodel.DmConMcnFansPlayWayW `json:"fans_play_way"`
}
// McnGetFansAreaReply 游客/粉丝地区分布
type McnGetFansAreaReply struct {
Result []*datamodel.DmConMcnFansAreaW `json:"result"`
}
//Sort sort.
func (s *McnGetFansAreaReply) Sort() {
sort.Slice(s.Result, func(i, j int) bool {
return s.Result[i].User > s.Result[j].User
})
}
// McnGetFansTypeReply 游客/粉丝倾向分布
type McnGetFansTypeReply struct {
Result []*datamodel.DmConMcnFansTypeW `json:"result"`
}
//Sort sort.
func (s *McnGetFansTypeReply) Sort() {
sort.Slice(s.Result, func(i, j int) bool {
return s.Result[i].Play > s.Result[j].Play
})
}
// McnGetFansTagReply 游客/粉丝标签地图分布
type McnGetFansTagReply struct {
Result []*datamodel.DmConMcnFansTagW `json:"result"`
}
// ----------------------------- 4期需求
//McnChangePermitReply .
type McnChangePermitReply = McnBindUpApplyReply
//McnGetUpPermitReply 4.2
type McnGetUpPermitReply struct {
Old *mcnadminmodel.Permits `json:"old"`
New *mcnadminmodel.Permits `json:"new"`
ContractLink string `json:"contract_link"`
}
// McnPublicationPriceChangeReply 4.4
type McnPublicationPriceChangeReply = CommonReply
// McnBaseInfoReply .
type McnBaseInfoReply struct {
ID int64 `json:"id"`
McnMid int64 `json:"mcn_mid"`
CompanyName string `json:"company_name"`
CompanyLicenseID string `json:"company_license_id"`
CompanyLicenseLink string `json:"company_license_link"`
ContractLink string `json:"contract_link"`
ContactName string `json:"contact_name"`
ContactTitle string `json:"contact_title"`
ContactIdcard string `json:"contact_idcard"`
ContactPhone string `json:"contact_phone"`
BeginDate time.Time `json:"begin_date"`
EndDate time.Time `json:"end_date"`
RejectReason string `json:"reject_reason"`
RejectTime time.Time `json:"reject_time"`
State model.MCNSignState `json:"state"`
Permission uint32 `json:"permission"`
Ctime time.Time `json:"ctime"`
Mtime time.Time `json:"mtime"`
SignPayInfo []*SignPayInfoReply `json:"sign_pay_info"`
Permits *mcnadminmodel.Permits `json:"permits"` // 权限集合
}
// SignPayInfoReply .
type SignPayInfoReply struct {
State mcnadminmodel.MCNPayState `json:"-"`
DueDate time.Time `json:"due_date"`
PayValue int64 `json:"pay_value"` // thousand bit
}
// AttrPermitVal get Permission all.
func (m *McnBaseInfoReply) AttrPermitVal() {
m.Permits = &mcnadminmodel.Permits{}
m.Permits.SetAttrPermitVal(m.Permission)
}
// CopyFromMcnInfo .
func (m *McnBaseInfoReply) CopyFromMcnInfo(v *McnSign) {
if v == nil {
return
}
m.ID = v.ID
m.McnMid = v.McnMid
m.CompanyName = v.CompanyName
m.CompanyLicenseID = v.CompanyLicenseID
m.CompanyLicenseLink = v.CompanyLicenseLink
m.ContractLink = v.ContractLink
m.ContactName = v.ContactName
m.ContactTitle = v.ContactTitle
m.ContactIdcard = v.ContactIdcard
m.ContactPhone = v.ContactPhone
m.BeginDate = v.BeginDate
m.EndDate = v.EndDate
m.RejectReason = v.RejectReason
m.RejectTime = v.RejectTime
m.State = v.State
m.Permission = v.Permission
m.Ctime = v.Ctime
m.Mtime = v.Mtime
m.AttrPermitVal()
}

View File

@@ -0,0 +1,50 @@
package mcnmodel
import (
"encoding/json"
"fmt"
model2 "go-common/app/admin/main/mcn/model"
"go-common/app/interface/main/mcn/model"
"testing"
)
type replyCommon struct {
Message string `json:"message"`
Code int `json:"code"`
Data interface{} `json:"data"`
}
func createReply(data interface{}) *replyCommon {
return &replyCommon{
Message: "",
Code: 0,
Data: data,
}
}
func printReply(data interface{}) {
var r = createReply(data)
var result, _ = json.MarshalIndent(r, "", " ")
fmt.Printf(string(result) + "\n")
}
// var now = xtime.Time(time.Now().Unix())
func TestPrintMcnUpDataInfo(t *testing.T) {
var r = McnGetUpListReply{
Result: []*McnUpDataInfo{{}},
PageResult: model.PageResult{},
}
defer func() {}()
printReply(r)
}
func TestPrintMcnGetUpPermitReply(t *testing.T) {
var r = McnGetUpPermitReply{
Old: &model2.Permits{},
New: &model2.Permits{},
ContractLink: "http://xxx.xx/adi.pdf",
}
defer func() {}()
printReply(r)
}

View File

@@ -0,0 +1,260 @@
package mcnmodel
import (
mcnadminmodel "go-common/app/admin/main/mcn/model"
"go-common/app/interface/main/mcn/model"
"go-common/app/interface/main/mcn/tool/validate"
"go-common/library/time"
)
//CookieMidInterface cookie set interface, set mid from cookie to arg
type CookieMidInterface interface {
SetMid(midFromCookie int64)
}
//McnCommonReq common mcn
type McnCommonReq struct {
McnCheatReq
SignID int64 `form:"sign_id"`
McnMid int64
}
//CheatInterface cheat interface
type CheatInterface interface {
// Cheat return true if cheated, false if not cheated
Cheat() bool
}
//McnCheatReq cheat
type McnCheatReq struct {
TMcnMid int64 `form:"t_mcn_mid"`
}
//Cheat .
func (m *McnCommonReq) Cheat() bool {
if m.TMcnMid == 0 {
return false
}
m.SetMid(m.TMcnMid)
return true
}
//SetMid set mid
func (m *McnCommonReq) SetMid(midFromCookie int64) {
m.McnMid = midFromCookie
}
//UpCommonReq common up
type UpCommonReq struct {
UpMid int64
}
//SetMid set mid
func (m *UpCommonReq) SetMid(midFromCookie int64) {
m.UpMid = midFromCookie
}
//GetStateReq get state
type GetStateReq struct {
McnCommonReq
}
//McnApplyReq apply req
type McnApplyReq struct {
McnCommonReq
CompanyName string `form:"company_name"`
CompanyLicenseID string `form:"company_license_id"`
ContactName string `form:"contact_name"`
ContactTitle string `form:"contact_title"`
ContactIdcard string `form:"contact_idcard" validate:"idcheck"`
ContactPhone string `form:"contact_phone" validate:"phonecheck"`
CompanyLicenseLink string `form:"company_license_link" validate:"httpcheck"`
ContractLink string `form:"contract_link" validate:"httpcheck"`
}
//CopyTo .
func (m *McnApplyReq) CopyTo(v *McnSign) {
if v == nil {
return
}
v.McnMid = m.McnMid
v.CompanyName = m.CompanyName
v.CompanyLicenseID = m.CompanyLicenseID
v.ContactName = m.ContactName
v.ContactTitle = m.ContactTitle
v.ContactIdcard = m.ContactIdcard
v.ContactPhone = m.ContactPhone
v.CompanyLicenseLink = m.CompanyLicenseLink
v.ContractLink = m.ContractLink
}
//McnBindUpApplyReq .
type McnBindUpApplyReq struct {
McnCommonReq
UpMid int64 `form:"up_mid"`
BeginDate time.Time `form:"begin_date"`
EndDate time.Time `form:"end_date"`
ContractLink string `form:"contract_link"` // 手动检查http格式
UpAuthLink string `form:"up_auth_link"` // 手动检查http格式
UpType int8 `form:"up_type"` // 用户类型0为站内1为站外
SiteLink string `form:"site_link"` //up主站外账号链接, 如果up type为1该项必填
mcnadminmodel.Permits
PublicationPrice int64 `form:"publication_price"` // 单位1/1000 元
}
//IsSiteInfoOk 检查站外up主信息是否OK如果不是站外Up主直接返回ok
func (m *McnBindUpApplyReq) IsSiteInfoOk() bool {
if m.UpType == 0 {
return true
}
return validate.RegHTTPCheck.MatchString(m.SiteLink)
}
//CopyTo .
func (m *McnBindUpApplyReq) CopyTo(v *McnUp) {
v.UpMid = m.UpMid
v.McnMid = m.McnMid
v.BeginDate = m.BeginDate
v.EndDate = m.EndDate
v.ContractLink = m.ContractLink
v.UpAuthLink = m.UpAuthLink
v.UpType = m.UpType
v.SiteLink = m.SiteLink
v.Permission = uint32(m.GetAttrPermitVal())
v.PublicationPrice = m.PublicationPrice
}
//McnUpConfirmReq .
type McnUpConfirmReq struct {
UpCommonReq
BindID int64 `form:"bind_id"`
Choice bool `form:"choice"`
}
//McnUpGetBindReq .
type McnUpGetBindReq struct {
UpCommonReq
BindID int64 `form:"bind_id"`
}
// McnGetDataSummaryReq req
type McnGetDataSummaryReq = McnCommonReq
//McnGetUpListReq req
type McnGetUpListReq struct {
McnCommonReq
UpMid int64 `form:"up_mid"`
model.PageArg
}
//McnGetAccountReq req
type McnGetAccountReq struct {
Mid int64 `form:"mid"`
}
// McnGetMcnOldInfoReq req
type McnGetMcnOldInfoReq struct {
McnCommonReq
}
// McnGetRankReq req to 获取排行
type McnGetRankReq struct {
McnCommonReq
Tid int16 `form:"tid"` // 分区
DataType DataType `form:"data_type"`
}
// McnGetRecommendPoolReq get recommend pool
type McnGetRecommendPoolReq struct {
McnCommonReq
model.PageArg
Tid int16 `form:"tid"`
OrderField string `form:"order_field"`
Sort string `form:"sort"`
}
// McnGetRecommendPoolTidListReq common req
type McnGetRecommendPoolTidListReq = McnCommonReq
// ------inner request
// McnGetRankAPIReq req to 获取排行
type McnGetRankAPIReq struct {
SignID int64 `form:"sign_id"`
Tid int16 `form:"tid"` // 分区
DataType DataType `form:"data_type"`
}
// 播放/弹幕/评论/分享/硬币/收藏/点赞数
const (
ActionTypePlay = "play" //播放
ActionTypeDanmu = "danmu" //弹幕
ActionTypeReply = "reply" //评论
ActionTypeShare = "share" //分享
ActionTypeCoin = "coin" //硬币
ActionTypeFav = "fav" //收藏
ActionTypeLike = "like" //点赞数
)
const (
// UserTypeGuest .
UserTypeGuest = "guest" // 游客
// UserTypeFans .
UserTypeFans = "fans" // 粉丝
)
//McnGetIndexIncReq 增量趋势
type McnGetIndexIncReq struct {
McnCommonReq
Type string `form:"type"`
}
//McnGetIndexSourceReq 来源分区
type McnGetIndexSourceReq = McnGetIndexIncReq
//McnGetPlaySourceReq 稿件播放来源占比
type McnGetPlaySourceReq struct {
McnCommonReq
}
//McnGetMcnFansReq mcn
type McnGetMcnFansReq = McnCommonReq
//McnGetMcnFansIncReq mcn粉丝按天关注数
type McnGetMcnFansIncReq = McnCommonReq
//McnGetMcnFansDecReq mcn粉丝按天取关数
type McnGetMcnFansDecReq = McnCommonReq
//McnGetMcnFansAttentionWayReq mcn粉丝关注渠道
type McnGetMcnFansAttentionWayReq = McnCommonReq
// McnGetBaseFansAttrReq mcn 游客和粉丝基本数据请求
type McnGetBaseFansAttrReq struct {
McnCommonReq
UserType string `form:"user_type"`
}
// McnGetFansAreaReq mcn 地区分布请求
type McnGetFansAreaReq = McnGetBaseFansAttrReq
// McnGetFansTypeReq mcn 游客/粉丝倾向分布请求
type McnGetFansTypeReq = McnGetBaseFansAttrReq
// McnGetFansTagReq mcn 游客/粉丝标签地图分布请求
type McnGetFansTagReq = McnGetBaseFansAttrReq
//McnChangePermitReq change permit
type McnChangePermitReq struct {
McnCommonReq
UpMid int64 `form:"up_mid"`
mcnadminmodel.Permits
UpAuthLink string `form:"up_auth_link" validate:"httpcheck"`
}
//McnPublicationPriceChangeReq change publication price
type McnPublicationPriceChangeReq struct {
McnCommonReq
Price int64 `form:"price"`
UpMid int64 `form:"up_mid"`
}

View File

@@ -0,0 +1,312 @@
package mcnmodel
import (
"go-common/app/interface/main/mcn/model"
"go-common/library/time"
)
// go get github.com/abice/go-enum
// go:generate go-enum -f=tables.go
// table names
const (
//TableNameMcnUp up
TableNameMcnUp = "mcn_up"
//TableNameMcnSign sign
TableNameMcnSign = "mcn_sign"
//TableNameMcnDataSummary data summary
TableNameMcnDataSummary = "mcn_data_summary"
//TableNameMcnDataUp data up
TableNameMcnDataUp = "mcn_data_up"
//TableNameUpBaseInfo up base info
TableNameUpBaseInfo = "up_base_info"
//TableNameMcnRankUpFan rank for up fans
TableNameMcnRankUpFan = "mcn_rank_up_fans"
//TableNameMcnRankArchiveLike rank for archive likes
TableNameMcnRankArchiveLike = "mcn_rank_archive_likes"
//TableNameMcnUpRecommendPool up recomment pool
TableNameMcnUpRecommendPool = "mcn_up_recommend_pool"
TableMcnUpPermissionApply = "mcn_up_permission_apply"
)
// DataType 数据类型1累计2昨日3上周4上月
/* ENUM(
Accumulate = 1
Day = 2
Week = 3
Month = 4
ActiveFans = 5
)*/
const (
// DataTypeAccumulate is a DataType of type Accumulate
DataTypeAccumulate DataType = 1
// DataTypeDay is a DataType of type Day
DataTypeDay DataType = 2
// DataTypeWeek is a DataType of type Week
DataTypeWeek DataType = 3
// DataTypeMonth is a DataType of type Month
DataTypeMonth DataType = 4
// DataTypeActiveFans active fans
DataTypeActiveFans DataType = 5
)
const (
// McnDataTypeDay is a McnDataType of type Day
McnDataTypeDay McnDataType = 1
// McnDataTypeMonth is a McnDataType of type Month
McnDataTypeMonth McnDataType = 2
)
// DataType .
type DataType int8
// McnUp up table
type McnUp struct {
ID int64 `json:"id" gorm:"column:id"`
SignID int64 `json:"sign_id" gorm:"column:sign_id"`
McnMid int64 `json:"mcn_mid" gorm:"column:mcn_mid"`
UpMid int64 `json:"up_mid" gorm:"column:up_mid"`
BeginDate time.Time `json:"begin_date" gorm:"column:begin_date"`
EndDate time.Time `json:"end_date" gorm:"column:end_date"`
ContractLink string `json:"contract_link" gorm:"column:contract_link"`
UpAuthLink string `json:"up_auth_link" gorm:"column:up_auth_link"`
RejectReason string `json:"reject_reason" gorm:"column:reject_reason"`
RejectTime string `json:"reject_time" gorm:"column:reject_time"`
State model.MCNUPState `json:"state" gorm:"column:state"`
UpType int8 `json:"up_type" gorm:"column:up_type"` // 用户类型0为站内1为站外
SiteLink string `json:"site_link" gorm:"column:site_link"` //up主站外账号链接, 如果up type为1该项必填
StateChangeTime time.Time `json:"state_change_time" gorm:"column:state_change_time"`
ConfirmTime time.Time `json:"confirm_time" gorm:"column:confirm_time"`
Ctime time.Time `json:"ctime" gorm:"column:ctime"`
Mtime time.Time `json:"mtime" gorm:"column:mtime"`
Permission uint32 `gorm:"column:permission" json:"permission"`
PublicationPrice int64 `gorm:"column:publication_price" json:"publication_price"` // 单位1/1000 元
}
// TableName .
func (s *McnUp) TableName() string {
return TableNameMcnUp
}
// IsBindable check if up canbe bind to other
func (s *McnUp) IsBindable() bool {
return isUpBindable(s.State)
}
// IsBeingBindedWithMcn check this up is in the middle of being binded with mcn,
func (s *McnUp) IsBeingBindedWithMcn(mcn *McnSign) bool {
if mcn == nil {
return false
}
if s.SignID == mcn.ID &&
(s.State == model.MCNUPStateOnReview || s.State == model.MCNUPStateNoAuthorize) {
return true
}
return false
}
// McnSign mcn sign table
type McnSign struct {
ID int64 `json:"id" gorm:"column:id"`
McnMid int64 `json:"mcn_mid" gorm:"column:mcn_mid"`
CompanyName string `json:"company_name" gorm:"column:company_name"`
CompanyLicenseID string `json:"company_license_id" gorm:"column:company_license_id"`
CompanyLicenseLink string `json:"company_license_link" gorm:"column:company_license_link"`
ContractLink string `json:"contract_link" gorm:"column:contract_link"`
ContactName string `json:"contact_name" gorm:"column:contact_name"`
ContactTitle string `json:"contact_title" gorm:"column:contact_title"`
ContactIdcard string `json:"contact_idcard" gorm:"column:contact_idcard"`
ContactPhone string `json:"contact_phone" gorm:"column:contact_phone"`
BeginDate time.Time `json:"begin_date" gorm:"column:begin_date"`
EndDate time.Time `json:"end_date" gorm:"column:end_date"`
RejectReason string `json:"reject_reason" gorm:"column:reject_reason"`
RejectTime time.Time `json:"reject_time" gorm:"column:reject_time"`
State model.MCNSignState `json:"state" gorm:"column:state"`
Ctime time.Time `json:"ctime" gorm:"column:ctime"`
Mtime time.Time `json:"mtime" gorm:"column:mtime"`
Permission uint32 `json:"permission" gorm:"column:permission"`
}
// TableName table name
func (s *McnSign) TableName() string {
return TableNameMcnSign
}
// McnDataType .
/* ENUM(
Day = 1
Month = 2
)*/
type McnDataType int8
// McnDataSummary table
type McnDataSummary struct {
ID int64 `json:"id" gorm:"column:id"`
McnMid int64 `json:"mcn_mid" gorm:"column:mcn_mid"`
SignID int64 `json:"sign_id" gorm:"column:sign_id"`
UpCount int64 `json:"up_count" gorm:"column:up_count"`
FansCountAccumulate int64 `json:"fans_count_accumulate" gorm:"column:fans_count_accumulate"`
FansCountOnline int64 `json:"fans_count_online" gorm:"column:fans_count_online"`
FansCountReal int64 `json:"fans_count_real" gorm:"column:fans_count_real"`
FansCountCheatAccumulate int64 `json:"fans_count_cheat_accumulate" gorm:"column:fans_count_cheat_accumulate"`
FansCountIncreaseDay int64 `json:"fans_count_increase_day" gorm:"column:fans_count_increase_day"`
PlayCountAccumulate int64 `json:"play_count_accumulate" gorm:"column:play_count_accumulate"`
PlayCountIncreaseDay int64 `json:"play_count_increase_day" gorm:"column:play_count_increase_day"`
ArchiveCountAccumulate int64 `json:"archive_count_accumulate" gorm:"column:archive_count_accumulate"`
ActiveTid int64 `json:"active_tid" gorm:"column:active_tid"`
GenerateDate time.Time `json:"generate_date" gorm:"column:generate_date"`
DataType McnDataType `json:"data_type" gorm:"column:data_type"`
Ctime time.Time `json:"ctime" gorm:"column:ctime"`
Mtime time.Time `json:"mtime" gorm:"column:mtime"`
}
// TableName table name
func (s *McnDataSummary) TableName() string {
return TableNameMcnDataSummary
}
// McnDataUp table name
type McnDataUp struct {
ID int64 `json:"id" gorm:"column:id"`
McnMid int64 `json:"mcn_mid" gorm:"column:mcn_mid"`
SignID int64 `json:"sign_id" gorm:"column:sign_id"`
UpMid int64 `json:"up_mid" gorm:"column:up_mid"`
DataType DataType `json:"data_type" gorm:"column:data_type"`
FansIncreaseAccumulate int32 `json:"fans_increase_accumulate" gorm:"column:fans_increase_accumulate"`
ArchiveCount int32 `json:"archive_count" gorm:"column:archive_count"`
PlayCount int64 `json:"play_count" gorm:"column:play_count"`
FansIncreaseMonth int64 `json:"fans_increase_month" gorm:"column:fans_increase_month"`
FansCount int64 `json:"fans_count" gorm:"column:fans_count"`
FansCountActive int64 `json:"fans_count_active" gorm:"column:fans_count_active"`
GenerateDate time.Time `json:"generate_date" gorm:"column:generate_date"`
Ctime time.Time `json:"ctime" gorm:"column:ctime"`
Mtime time.Time `json:"mtime" gorm:"column:mtime"`
}
// TableName table name
func (s *McnDataUp) TableName() string {
return TableNameMcnDataUp
}
// UpBaseInfo struct
type UpBaseInfo struct {
ID uint32 `gorm:"column:id"`
Mid int64 `gorm:"column:mid"`
ActiveTid int64 `gorm:"column:active_tid"`
ArticleCountAccumulate int `gorm:"column:article_count_accumulate"`
Activity int `gorm:"column:activity"`
FansCount int `gorm:"column:fans_count"`
}
// TableName .
func (s *UpBaseInfo) TableName() string {
return TableNameUpBaseInfo
}
// McnRankUpFan .
type McnRankUpFan struct {
ID int64 `json:"id" gorm:"column:id"`
McnMid int64 `json:"mcn_mid" gorm:"column:mcn_mid"`
SignID int64 `json:"sign_id" gorm:"column:sign_id"`
UpMid int64 `json:"up_mid" gorm:"column:up_mid"`
Value1 int64 `json:"value1" gorm:"column:value1"`
Value2 int64 `json:"value2" gorm:"column:value2"`
ActiveTid int16 `json:"active_tid" gorm:"column:active_tid"`
DataType DataType `json:"data_type" gorm:"column:data_type"`
GenerateDate time.Time `json:"generate_date" gorm:"column:generate_date"`
Ctime time.Time `json:"ctime" gorm:"column:ctime"`
Mtime time.Time `json:"mtime" gorm:"column:mtime"`
}
// TableName .
func (s *McnRankUpFan) TableName() string {
return TableNameMcnRankUpFan
}
// McnRankArchiveLike .
type McnRankArchiveLike struct {
ID int64 `json:"id" gorm:"column:id"`
McnMid int64 `json:"mcn_mid" gorm:"column:mcn_mid"`
SignID int64 `json:"sign_id" gorm:"column:sign_id"`
UpMid int64 `json:"up_mid" gorm:"column:up_mid"`
ArchiveID int64 `json:"archive_id" gorm:"column:avid"`
LikeCount int64 `json:"like_count" gorm:"column:like_count"`
PlayIncr int64 `json:"play_incr" gorm:"column:play_incr" `
DataType DataType `json:"data_type" gorm:"column:data_type"`
Tid int16 `json:"tid" gorm:"column:tid"`
GenerateDate time.Time `json:"generate_date" gorm:"column:generate_date"`
Ctime time.Time `json:"ctime" gorm:"column:ctime"`
Mtime time.Time `json:"mtime" gorm:"column:mtime"`
}
// TableName .
func (s *McnRankArchiveLike) TableName() string {
return TableNameMcnRankArchiveLike
}
// McnUpRecommendPool 推荐池 struct
type McnUpRecommendPool struct {
ID int64 `gorm:"column:id" json:"id"`
UpMid int64 `gorm:"column:up_mid" json:"up_mid"`
FansCount int64 `gorm:"column:fans_count" json:"fans_count"`
FansCountIncreaseMonth int64 `gorm:"column:fans_count_increase_month" json:"fans_count_increase_month"`
ArchiveCount int64 `gorm:"column:archive_count" json:"archive_count"`
PlayCountAccumulate int64 `gorm:"column:play_count_accumulate" json:"play_count_accumulate"`
PlayCountAverage int64 `gorm:"column:play_count_average" json:"play_count_average"`
ActiveTid int16 `gorm:"column:active_tid" json:"active_tid"`
LastArchiveTime time.Time `gorm:"column:last_archive_time" json:"last_archive_time"`
State uint8 `gorm:"column:state" json:"state"`
Source int64 `gorm:"column:source" json:"source"`
GenerateTime time.Time `gorm:"column:generate_time" json:"generate_time"`
Ctime time.Time `gorm:"column:ctime" json:"ctime"`
Mtime time.Time `gorm:"column:mtime" json:"mtime"`
}
// TableName table name.
func (s *McnUpRecommendPool) TableName() string {
return TableNameMcnUpRecommendPool
}
// MCNUPRecommendState 推荐状态
// MCNUPRecommendState .
type MCNUPRecommendState int8
// const .
const (
// MCNUPRecommendStateUnKnown 未知状态
MCNUPRecommendStateUnKnown MCNUPRecommendState = 0
// MCNUPRecommendStateOff 未推荐
MCNUPRecommendStateOff MCNUPRecommendState = 1
// MCNUPRecommendStateOn 推荐中
MCNUPRecommendStateOn MCNUPRecommendState = 2
// MCNUPRecommendStateBan 禁止推荐
MCNUPRecommendStateBan MCNUPRecommendState = 3
// MCNUPRecommendStateDel 移除中
MCNUPRecommendStateDel MCNUPRecommendState = 100
)
// MCNUPRecommendSource
// type MCNUPRecommendSource mcnadminmodel.MCNUPRecommendSource
//McnUpPermissionApply permission
type McnUpPermissionApply struct {
ID int64 `gorm:"column:id" json:"id"`
McnMid int64 `gorm:"column:mcn_mid" json:"mcn_mid"`
UpMid int64 `gorm:"column:up_mid" json:"up_mid"`
SignID int64 `gorm:"column:sign_id" json:"sign_id"`
NewPermission uint32 `gorm:"column:new_permission" json:"new_permission"`
OldPermission uint32 `gorm:"column:old_permission" json:"old_permission"`
RejectReason string `gorm:"-" json:"reject_reason"`
RejectTime time.Time `gorm:"-" json:"reject_time"`
State int8 `gorm:"column:state" json:"state"`
Ctime time.Time `gorm:"column:ctime" json:"ctime"`
Mtime time.Time `gorm:"column:mtime" json:"mtime"`
AdminID int64 `gorm:"-" json:"-"`
AdminName string `gorm:"-" json:"-"`
UpAuthLink string `gorm:"column:up_auth_link" json:"up_auth_link"`
}
// TableName table name.
func (s *McnUpPermissionApply) TableName() string {
return TableMcnUpPermissionApply
}

View File

@@ -0,0 +1,14 @@
package mcnmodel
import "go-common/app/interface/main/mcn/model"
//isUpBindable
// up主为未绑定已驳回已解除已申请的up主可被申请up主拒绝后可重复申请
// 审核中,已签约,已冻结不可被申请
func isUpBindable(state model.MCNUPState) bool {
switch state {
case model.MCNUPStateOnBlock, model.MCNUPStateOnCooling, model.MCNUPStateOnSign, model.MCNUPStateOnReview, model.MCNUPStateOnPreOpen:
return false
}
return true
}

View File

@@ -0,0 +1,57 @@
package model
// MCNSignState .
type MCNSignState int8
// const .
const (
// MCNSignStateNoApply 未申请
MCNSignStateNoApply MCNSignState = 0
// MCNSignStateOnReview 待审核
MCNSignStateOnReview MCNSignState = 1
// MCNSignStateOnReject 已驳回
MCNSignStateOnReject MCNSignState = 2
// MCNSignStateOnSign 已签约
MCNSignStateOnSign MCNSignState = 10
// MCNSignStateOnCooling 冷却中
MCNSignStateOnCooling MCNSignState = 11
// MCNSignStateOnExpire 已到期
MCNSignStateOnExpire MCNSignState = 12
// MCNSignStateOnBlock 封禁
MCNSignStateOnBlock MCNSignState = 13
// MCNSignStateOnClear 清退
MCNSignStateOnClear MCNSignState = 14
// MCNSignStateOnPreOpen 待开启
MCNSignStateOnPreOpen MCNSignState = 15
// MCNSignStateOnDelete 移除
MCNSignStateOnDelete MCNSignState = 100
)
// MCNUPState .
type MCNUPState int8
// const .
const (
// MCNUPStateNoAuthorize 未授权
MCNUPStateNoAuthorize MCNUPState = 0
// MCNUPStateOnRefuse 已拒绝
MCNUPStateOnRefuse MCNUPState = 1
// MCNUPStateOnReview 审核中
MCNUPStateOnReview MCNUPState = 2
// MCNUPStateOnReject 已驳回
MCNUPStateOnReject MCNUPState = 3
// MCNUPStateOnSign 已签约
MCNUPStateOnSign MCNUPState = 10
// MCNUPStateOnCooling 已冻结
MCNUPStateOnCooling MCNUPState = 11
// MCNUPStateOnExpire 已到期
MCNUPStateOnExpire MCNUPState = 12
// MCNUPStateOnBlock 封禁
MCNUPStateOnBlock MCNUPState = 13
// MCNUPStateOnClear 已解约
MCNUPStateOnClear MCNUPState = 14
// MCNUPStateOnPreOpen 待开启
MCNUPStateOnPreOpen MCNUPState = 15
// MCNUPStateOnDelete 删除
MCNUPStateOnDelete MCNUPState = 100
)

View File

@@ -0,0 +1,72 @@
package model
import (
"math"
)
const (
// dateFmt = "20060102"
// dateTimeFmt = "20060102_150405"
)
func round(num float64) int {
return int(num + math.Copysign(0.5, num))
}
//ToFixed fix float precision
func ToFixed(num float64, precision int) float64 {
output := math.Pow(10, float64(precision))
return float64(round(num*output)) / output // since go 1.9 doesn't have a math.Round function...
}
// floatFormat format float to string
// func floatFormat(f float64) string {
// return strconv.FormatFloat(f, 'f', 2, 64)
// }
// intFormat format int to string
// func intFormat(i int64) string {
// return strconv.Itoa(int(i))
// }
//PageArg page arg
type PageArg struct {
Page int `form:"page"`
Size int `form:"size"`
}
//PageResult page result
type PageResult struct {
Page int `json:"page"`
TotalCount int `json:"total_count"`
}
//CheckPageValidation check the page validte, return limit offset
func (arg *PageArg) CheckPageValidation() (limit, offset int) {
if arg.Page < 1 {
arg.Page = 1
}
if arg.Size > 1000 || arg.Size <= 0 {
arg.Size = 10
}
limit = arg.Size
offset = (arg.Page - 1) * limit
return
}
//ToPageResult cast to page result
func (arg *PageArg) ToPageResult(total int) (res PageResult) {
res.TotalCount = total
res.Page = arg.Page
return
}
//ExportArg export arg
type ExportArg struct {
Export string `form:"export"`
}
//ExportFormat export format
func (e *ExportArg) ExportFormat() string {
return e.Export
}

View File

@@ -0,0 +1,23 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/interface/main/mcn/server/http:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,60 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"api.go",
"creative.go",
"data.go",
"http.go",
"http_base.go",
"mcn.go",
"upload.go",
],
importpath = "go-common/app/interface/main/mcn/server/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/mcn/conf:go_default_library",
"//app/interface/main/mcn/model/mcnmodel:go_default_library",
"//app/interface/main/mcn/service:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/antispam:go_default_library",
"//library/net/http/blademaster/middleware/auth:go_default_library",
"//library/net/http/blademaster/middleware/verify: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"],
)
go_test(
name = "go_default_test",
srcs = ["http_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/mcn/model:go_default_library",
"//library/net/http/blademaster/binding:go_default_library",
],
)

View File

@@ -0,0 +1,177 @@
package http
import (
"context"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/library/net/http/blademaster"
)
func mcnGetRankArchiveLikesAPI(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetRankAPIReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.McnGetRankArchiveLikesAPI(context, arg.(*mcnmodel.McnGetRankAPIReq))
},
"McnGetRankArchiveLikesAPI",
nil,
nil,
)(c)
}
func getMcnSummaryAPI(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetDataSummaryReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetMcnSummaryAPI(context, arg.(*mcnmodel.McnGetDataSummaryReq))
},
"GetMcnSummaryAPI",
nil,
nil,
)(c)
}
func getIndexIncAPI(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetIndexIncReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetIndexIncAPI(context, arg.(*mcnmodel.McnGetIndexIncReq))
},
"GetIndexIncAPI",
nil,
nil,
)(c)
}
func getIndexSourceAPI(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetIndexSourceReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetIndexSourceAPI(context, arg.(*mcnmodel.McnGetIndexSourceReq))
},
"GetIndexSourceAPI",
nil,
nil,
)(c)
}
func getPlaySourceAPI(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetPlaySourceReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetPlaySourceAPI(context, arg.(*mcnmodel.McnGetPlaySourceReq))
},
"GetPlaySourceAPI",
nil,
nil,
)(c)
}
func getMcnFansAPI(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetMcnFansReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetMcnFansAPI(context, arg.(*mcnmodel.McnGetMcnFansReq))
},
"GetMcnFansAPI",
nil,
nil,
)(c)
}
func getMcnFansIncAPI(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetMcnFansIncReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetMcnFansIncAPI(context, arg.(*mcnmodel.McnGetMcnFansIncReq))
},
"GetMcnFansIncAPI",
nil,
nil,
)(c)
}
func getMcnFansDecAPI(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetMcnFansDecReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetMcnFansDecAPI(context, arg.(*mcnmodel.McnGetMcnFansDecReq))
},
"GetMcnFansDecAPI",
nil,
nil,
)(c)
}
func getMcnFansAttentionWayAPI(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetMcnFansAttentionWayReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetMcnFansAttentionWayAPI(context, arg.(*mcnmodel.McnGetMcnFansAttentionWayReq))
},
"GetMcnFansAttentionWayAPI",
nil,
nil,
)(c)
}
func getFansBaseFansAttrAPI(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetBaseFansAttrReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetFansBaseFansAttrAPI(context, arg.(*mcnmodel.McnGetBaseFansAttrReq))
},
"GetFansBaseFansAttrAPI",
nil,
nil,
)(c)
}
func getFansAreaAPI(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetFansAreaReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetFansAreaAPI(context, arg.(*mcnmodel.McnGetFansAreaReq))
},
"GetFansAreaAPI",
nil,
nil,
)(c)
}
func getFansTypeAPI(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetFansTypeReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetFansTypeAPI(context, arg.(*mcnmodel.McnGetFansTypeReq))
},
"GetFansTypeAPI",
nil,
nil,
)(c)
}
func getFansTagAPI(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetFansTagReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetFansTagAPI(context, arg.(*mcnmodel.McnGetFansTagReq))
},
"GetFansTagAPI",
nil,
nil,
)(c)
}

View File

@@ -0,0 +1,231 @@
package http
import (
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/library/net/http/blademaster"
)
// archives handler
func archives(c *blademaster.Context) {
var err error
v := new(mcnmodel.ArchivesReq)
if err = c.Bind(v); err != nil {
return
}
mcnMid, _ := c.Get("mid")
common := &mcnmodel.CreativeCommonReq{
UpMid: v.UpMid,
McnMid: mcnMid.(int64),
}
c.JSON(srv.CreativeHandle(c, common, c.Request.Form, "archives"))
}
// archiveHistoryList handler
func archiveHistoryList(c *blademaster.Context) {
var err error
v := new(mcnmodel.ArchiveHistoryListReq)
if err = c.Bind(v); err != nil {
return
}
mcnMid, _ := c.Get("mid")
common := &mcnmodel.CreativeCommonReq{
UpMid: v.UpMid,
McnMid: mcnMid.(int64),
}
c.JSON(srv.CreativeHandle(c, common, c.Request.Form, "archiveHistoryList"))
}
// archiveVideos handler
func archiveVideos(c *blademaster.Context) {
var err error
v := new(mcnmodel.ArchiveVideosReq)
if err = c.Bind(v); err != nil {
return
}
mcnMid, _ := c.Get("mid")
common := &mcnmodel.CreativeCommonReq{
UpMid: v.UpMid,
McnMid: mcnMid.(int64),
}
c.JSON(srv.CreativeHandle(c, common, c.Request.Form, "archiveVideos"))
}
// dataArchive handler
func dataArchive(c *blademaster.Context) {
var err error
v := new(mcnmodel.DataArchiveReq)
if err = c.Bind(v); err != nil {
return
}
mcnMid, _ := c.Get("mid")
common := &mcnmodel.CreativeCommonReq{
UpMid: v.UpMid,
McnMid: mcnMid.(int64),
}
c.JSON(srv.CreativeHandle(c, common, c.Request.Form, "dataArchive"))
}
// dataVideoQuit handler
func dataVideoQuit(c *blademaster.Context) {
var err error
v := new(mcnmodel.DataVideoQuitReq)
if err = c.Bind(v); err != nil {
return
}
mcnMid, _ := c.Get("mid")
common := &mcnmodel.CreativeCommonReq{
UpMid: v.UpMid,
McnMid: mcnMid.(int64),
}
c.JSON(srv.CreativeHandle(c, common, c.Request.Form, "dataVideoQuit"))
}
// danmuDistri handler
func danmuDistri(c *blademaster.Context) {
var err error
v := new(mcnmodel.DanmuDistriReq)
if err = c.Bind(v); err != nil {
return
}
mcnMid, _ := c.Get("mid")
common := &mcnmodel.CreativeCommonReq{
UpMid: v.UpMid,
McnMid: mcnMid.(int64),
}
c.JSON(srv.CreativeHandle(c, common, c.Request.Form, "danmuDistri"))
}
// dataBase handler
func dataBase(c *blademaster.Context) {
var err error
v := new(mcnmodel.DataBaseReq)
if err = c.Bind(v); err != nil {
return
}
mcnMid, _ := c.Get("mid")
common := &mcnmodel.CreativeCommonReq{
UpMid: v.UpMid,
McnMid: mcnMid.(int64),
}
c.JSON(srv.CreativeHandle(c, common, c.Request.Form, "dataBase"))
}
// dataTrend handler
func dataTrend(c *blademaster.Context) {
var err error
v := new(mcnmodel.DataTrendReq)
if err = c.Bind(v); err != nil {
return
}
mcnMid, _ := c.Get("mid")
common := &mcnmodel.CreativeCommonReq{
UpMid: v.UpMid,
McnMid: mcnMid.(int64),
}
c.JSON(srv.CreativeHandle(c, common, c.Request.Form, "dataTrend"))
}
// dataAction handler
func dataAction(c *blademaster.Context) {
var err error
v := new(mcnmodel.DataActionReq)
if err = c.Bind(v); err != nil {
return
}
mcnMid, _ := c.Get("mid")
common := &mcnmodel.CreativeCommonReq{
UpMid: v.UpMid,
McnMid: mcnMid.(int64),
}
c.JSON(srv.CreativeHandle(c, common, c.Request.Form, "dataAction"))
}
// dataFan handler
func dataFan(c *blademaster.Context) {
var err error
v := new(mcnmodel.DataFanReq)
if err = c.Bind(v); err != nil {
return
}
mcnMid, _ := c.Get("mid")
common := &mcnmodel.CreativeCommonReq{
UpMid: v.UpMid,
McnMid: mcnMid.(int64),
}
c.JSON(srv.CreativeHandle(c, common, c.Request.Form, "dataFan"))
}
// dataPandect handler
func dataPandect(c *blademaster.Context) {
var err error
v := new(mcnmodel.DataPandectReq)
if err = c.Bind(v); err != nil {
return
}
mcnMid, _ := c.Get("mid")
common := &mcnmodel.CreativeCommonReq{
UpMid: v.UpMid,
McnMid: mcnMid.(int64),
}
c.JSON(srv.CreativeHandle(c, common, c.Request.Form, "dataPandect"))
}
// dataSurvey handler
func dataSurvey(c *blademaster.Context) {
var err error
v := new(mcnmodel.DataSurveyReq)
if err = c.Bind(v); err != nil {
return
}
mcnMid, _ := c.Get("mid")
common := &mcnmodel.CreativeCommonReq{
UpMid: v.UpMid,
McnMid: mcnMid.(int64),
}
c.JSON(srv.CreativeHandle(c, common, c.Request.Form, "dataSurvey"))
}
// dataPlaySource handler
func dataPlaySource(c *blademaster.Context) {
var err error
v := new(mcnmodel.DataPlaySourceReq)
if err = c.Bind(v); err != nil {
return
}
mcnMid, _ := c.Get("mid")
common := &mcnmodel.CreativeCommonReq{
UpMid: v.UpMid,
McnMid: mcnMid.(int64),
}
c.JSON(srv.CreativeHandle(c, common, c.Request.Form, "dataPlaySource"))
}
// dataPlayAnalysis handler
func dataPlayAnalysis(c *blademaster.Context) {
var err error
v := new(mcnmodel.DataPlayAnalysisReq)
if err = c.Bind(v); err != nil {
return
}
mcnMid, _ := c.Get("mid")
common := &mcnmodel.CreativeCommonReq{
UpMid: v.UpMid,
McnMid: mcnMid.(int64),
}
c.JSON(srv.CreativeHandle(c, common, c.Request.Form, "dataPlayAnalysis"))
}
// dataArticleRank handler
func dataArticleRank(c *blademaster.Context) {
var err error
v := new(mcnmodel.DataArticleRankReq)
if err = c.Bind(v); err != nil {
return
}
mcnMid, _ := c.Get("mid")
common := &mcnmodel.CreativeCommonReq{
UpMid: v.UpMid,
McnMid: mcnMid.(int64),
}
c.JSON(srv.CreativeHandle(c, common, c.Request.Form, "dataArticleRank"))
}

View File

@@ -0,0 +1,150 @@
package http
import (
"context"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/library/net/http/blademaster"
)
func mcnGetMcnGetIndexInc(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetIndexIncReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetMcnGetIndexInc(context, arg.(*mcnmodel.McnGetIndexIncReq))
},
"GetMcnGetIndexInc",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnGetMcnGetIndexSource(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetIndexSourceReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetMcnGetIndexSource(context, arg.(*mcnmodel.McnGetIndexSourceReq))
},
"GetMcnGetIndexSource",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnGetPlaySource(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetPlaySourceReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetPlaySource(context, arg.(*mcnmodel.McnGetPlaySourceReq))
},
"GetPlaySource",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnGetMcnFans(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetMcnFansReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetMcnFans(context, arg.(*mcnmodel.McnGetMcnFansReq))
},
"GetMcnFans",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnGetMcnFansInc(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetMcnFansIncReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetMcnFansInc(context, arg.(*mcnmodel.McnGetMcnFansIncReq))
},
"GetMcnFansInc",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnGetMcnFansDec(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetMcnFansDecReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetMcnFansDec(context, arg.(*mcnmodel.McnGetMcnFansDecReq))
},
"GetMcnFansDec",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnGetMcnFansAttentionWay(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetMcnFansAttentionWayReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetMcnFansAttentionWay(context, arg.(*mcnmodel.McnGetMcnFansAttentionWayReq))
},
"GetMcnFansAttentionWay",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnGetBaseFansAttrReq(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetBaseFansAttrReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetBaseFansAttrReq(context, arg.(*mcnmodel.McnGetBaseFansAttrReq))
},
"GetBaseFansAttrReq",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnGetFansArea(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetFansAreaReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetFansArea(context, arg.(*mcnmodel.McnGetFansAreaReq))
},
"GetFansArea",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnGetFansType(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetFansTypeReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetFansType(context, arg.(*mcnmodel.McnGetFansTypeReq))
},
"GetFansType",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnGetFansTag(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetFansTagReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetFansTag(context, arg.(*mcnmodel.McnGetFansTagReq))
},
"GetFansTag",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}

View File

@@ -0,0 +1,142 @@
package http
import (
"net/http"
"go-common/app/interface/main/mcn/conf"
"go-common/app/interface/main/mcn/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/antispam"
"go-common/library/net/http/blademaster/middleware/auth"
"go-common/library/net/http/blademaster/middleware/verify"
)
var (
srv *service.Service
authSvc *auth.Auth
uploadAnti *antispam.Antispam
verifySvc *verify.Verify
)
// Init init
func Init(c *conf.Config) {
initService(c)
engine := bm.DefaultServer(c.BM)
route(engine)
if err := engine.Start(); err != nil {
log.Error("bm Start error(%v)", err)
panic(err)
}
}
func initService(c *conf.Config) {
srv = service.New(c)
authSvc = auth.New(nil)
uploadAnti = antispam.New(c.UploadAntispam)
verifySvc = verify.New(nil)
}
func route(e *bm.Engine) {
e.Ping(ping)
e.Register(register)
// 以下接口在 api.bilibili.com对外使用
g := e.Group("/x/mcn")
{
//g.GET("/start", vfy.Verify, howToStart)
g.GET("/state", authSvc.User, mcnState)
g.GET("/exist", authSvc.User, mcnExist)
g.POST("/file/upload", multipartForm, authSvc.User, uploadAnti.ServeHTTP, upload)
g.GET("/account/info", authSvc.User, mcnGetAccountInfo)
g.GET("/base/info", authSvc.User, mcnBaseInfo)
g.POST("/apply", authSvc.User, mcnApply)
g.POST("/mcn/bindup", authSvc.User, mcnBindUpApply)
g.GET("/mcn/get_data_summary", authSvc.User, mcnGetDataSummary)
g.GET("/mcn/get_data_up_list", authSvc.User, mcnGetDataUpList)
g.GET("/mcn/get_old_info", authSvc.User, mcnGetOldInfo)
g.POST("/mcn/permit/change", authSvc.User, mcnGetChangePermit)
g.POST("/mcn/publication/change-price", authSvc.User, mcnPublicationPriceChange)
g.POST("/up/confirm", authSvc.User, mcnUpConfirm)
g.GET("/up/get_bind", authSvc.User, mcnUpGetBind)
g.POST("/up/permit/confirm-reauth", authSvc.User, mcnUpPermitApplyConfirm)
g.GET("/up/permit/get-reauth", authSvc.User, mcnPermitApplyGetBind)
g.GET("/rank/up_fans", authSvc.User, mcnGetRankUpFans)
g.GET("/rank/archive_likes", authSvc.User, mcnGetRankArchiveLikesOuter)
g.GET("/recommend/list", authSvc.User, mcnGetRecommendPool)
g.GET("/recommend/list_tids", authSvc.User, mcnGetRecommendPoolTidList)
g.GET("/data/index/inc", authSvc.User, mcnGetMcnGetIndexInc)
g.GET("/data/index/source", authSvc.User, mcnGetMcnGetIndexSource)
g.GET("/data/play/source", authSvc.User, mcnGetPlaySource)
g.GET("/data/fans", authSvc.User, mcnGetMcnFans)
g.GET("/data/fans/inc", authSvc.User, mcnGetMcnFansInc)
g.GET("/data/fans/dec", authSvc.User, mcnGetMcnFansDec)
g.GET("/data/fans/attention/way", authSvc.User, mcnGetMcnFansAttentionWay)
// mcn粉丝和游客的粉丝分析
g.GET("/data/fans/base/attr", authSvc.User, mcnGetBaseFansAttrReq)
g.GET("/data/fans/area", authSvc.User, mcnGetFansArea)
g.GET("/data/fans/type", authSvc.User, mcnGetFansType)
g.GET("/data/fans/tag", authSvc.User, mcnGetFansTag)
// mcn创作中心数据分析
g.GET("/creative/archives", authSvc.User, archives)
g.GET("/creative/archive/history/list", authSvc.User, archiveHistoryList)
g.GET("/creative/archive/videos", authSvc.User, archiveVideos)
g.GET("/creative/data/archive", authSvc.User, dataArchive)
g.GET("/creative/data/videoquit", authSvc.User, dataVideoQuit)
g.GET("/creative/danmu/distri", authSvc.User, danmuDistri)
g.GET("/creative/data/base", authSvc.User, dataBase)
g.GET("/creative/data/trend", authSvc.User, dataTrend)
g.GET("/creative/data/action", authSvc.User, dataAction)
g.GET("/creative/data/fan", authSvc.User, dataFan)
g.GET("/creative/data/pandect", authSvc.User, dataPandect)
g.GET("/creative/data/survey", authSvc.User, dataSurvey)
g.GET("/creative/data/playsource", authSvc.User, dataPlaySource)
g.GET("/creative/data/playanalysis", authSvc.User, dataPlayAnalysis)
g.GET("/creative/data/article/rank", authSvc.User, dataArticleRank)
}
cmd := e.Group("/cmd")
{
cmd.GET("/reload_rank", cmdReloadRank)
}
// 以下接口在 api.bilibili.co内部使用
internal := e.Group("/x/internal/mcn")
{
internal.GET("/rank/archive_likes", verifySvc.Verify, mcnGetRankArchiveLikesAPI)
// mcn 数据概况
internal.GET("/data/mcn/summary", verifySvc.Verify, getMcnSummaryAPI)
internal.GET("/data/index/inc", verifySvc.Verify, getIndexIncAPI)
internal.GET("/data/index/source", verifySvc.Verify, getIndexSourceAPI)
internal.GET("/data/play/source", verifySvc.Verify, getPlaySourceAPI)
internal.GET("/data/fans", verifySvc.Verify, getMcnFansAPI)
internal.GET("/data/fans/inc", verifySvc.Verify, getMcnFansIncAPI)
internal.GET("/data/fans/dec", verifySvc.Verify, getMcnFansDecAPI)
internal.GET("/data/fans/attention/way", verifySvc.Verify, getMcnFansAttentionWayAPI)
// mcn粉丝和游客的粉丝分析
internal.GET("/data/fans/base/attr", verifySvc.Verify, getFansBaseFansAttrAPI)
internal.GET("/data/fans/area", verifySvc.Verify, getFansAreaAPI)
internal.GET("/data/fans/type", verifySvc.Verify, getFansTypeAPI)
internal.GET("/data/fans/tag", verifySvc.Verify, getFansTagAPI)
}
}
func ping(c *bm.Context) {
if err := srv.Ping(c); err != nil {
log.Error("ping error(%v)", err)
c.AbortWithStatus(http.StatusServiceUnavailable)
}
}
func register(c *bm.Context) {
c.JSON(map[string]interface{}{}, nil)
}
func multipartForm(c *bm.Context) {
c.Request.ParseMultipartForm(maxFileSize)
}

View File

@@ -0,0 +1,199 @@
package http
import (
"context"
"go-common/app/interface/main/mcn/conf"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/http/blademaster"
)
// func bmHTTPErrorWithMsg(c *blademaster.Context, err error, msg string) {
// if c.IsAborted() {
// return
// }
// c.Error = err
// bcode := ecode.Cause(err)
// if msg == "" {
// msg = err.Error()
// }
// c.Render(http.StatusOK, render.JSON{
// Code: bcode.Code(),
// Message: msg,
// Data: nil,
// })
// }
// service的函数原型
type serviceFunc func(context context.Context, arg interface{}) (res interface{}, err error)
// response writer
type responseWriter func(c *blademaster.Context, arg interface{}, res interface{}, err error)
type argParser func(c *blademaster.Context, arg interface{}) (err error)
func argGetParser(c *blademaster.Context, arg interface{}) (err error) {
err = c.Bind(arg)
return
}
// argPostJSONParser .
// func argPostJSONParser(c *blademaster.Context, arg interface{}) (err error) {
// respBody, _ := ioutil.ReadAll(c.Request.Body)
// if err = json.Unmarshal(respBody, arg); err != nil {
// log.Error("json unmarshal fail, err=%v", err)
// return
// }
// if err = binding.Validator.ValidateStruct(arg); err != nil {
// log.Error("binding.Validator.ValidateStruct(%+v) error(%+v)", arg, err)
// }
// return
// }
func jsonWriter(c *blademaster.Context, arg interface{}, res interface{}, err error) {
c.JSON(res, err)
}
// func csvWriter(c *blademaster.Context, arg interface{}, res interface{}, err error) {
// formater, ok := res.(model.CsvFormatter)
// if !ok {
// log.Error("res cannot convert CsvFommater, res type=%s", reflect.TypeOf(res).Name())
// c.String(ecode.ServerErr.Code(), "res cannot convert CsvFommater")
// return
// }
// c.Writer.Header().Set("Content-Type", "application/csv")
// c.Writer.Header().Set("Content-Disposition", fmt.Sprintf("attachment;filename=\"%s\"", formater.GetFileName()))
// var buf = &bytes.Buffer{}
// var csvWriter = csv.NewWriter(buf)
// formater.ToCsv(csvWriter)
// csvWriter.Flush()
// c.Writer.Write(buf.Bytes())
// }
// func decideWriter(c *blademaster.Context, arg interface{}, res interface{}, err error) {
// var writer responseWriter
// var decider, ok = arg.(model.ExportArgInterface)
// if ok {
// switch decider.ExportFormat() {
// case "json":
// writer = jsonWriter
// case "csv":
// writer = csvWriter
// }
// }
// if writer != nil {
// writer(c, arg, res, err)
// } else {
// jsonWriter(c, arg, res, err)
// }
// }
type preBindFuncType func(*blademaster.Context) error
type preHandleFuncType func(*blademaster.Context, interface{}) error
func httpGenerateFunc(arg interface{}, sfunc serviceFunc, description string, parser argParser, writer responseWriter, preBindFuncs []preBindFuncType, preHandleFuncs []preHandleFuncType) func(*blademaster.Context) {
return func(c *blademaster.Context) {
var res interface{}
var err error
//var errMsg string
exitswitch:
switch {
default:
for _, f := range preBindFuncs {
err = f(c)
if err != nil {
break exitswitch
}
}
if err = parser(c, arg); err != nil {
log.Error("%s, request argument bind fail, err=%v", description, err)
//errMsg = fmt.Sprintf("wrong argument, %s", err.Error())
err = ecode.RequestErr
break
}
for _, f := range preHandleFuncs {
err = f(c, arg)
if err != nil {
break exitswitch
}
}
var scoreRes, e = sfunc(c, arg)
err = e
if e != nil {
//errMsg = err.Error()
log.Error("%s query fail, req=%+v, err=%+v", description, arg, err)
break
}
log.Info("%s query ok, req=%+v, result=%+v", description, arg, scoreRes)
res = scoreRes
}
if err != nil {
//bmHTTPErrorWithMsg(c, err, errMsg)
if c.IsAborted() {
return
}
c.JSON(nil, err)
} else {
writer(c, arg, res, err)
}
}
}
func httpGetFunc(arg interface{}, sfunc serviceFunc, description string, preBindFuncs []preBindFuncType, preHandleFunc []preHandleFuncType) func(*blademaster.Context) {
return httpGetFuncWithWriter(arg, sfunc, description, jsonWriter, preBindFuncs, preHandleFunc)
}
func httpGetFuncWithWriter(arg interface{}, sfunc serviceFunc, description string, writer responseWriter, preBindFuncs []preBindFuncType, preHandleFunc []preHandleFuncType) func(*blademaster.Context) {
return httpGenerateFunc(arg, sfunc, description, argGetParser, writer, preBindFuncs, preHandleFunc)
}
func getMid(bc *blademaster.Context) int64 {
mid, exists := bc.Get("mid")
if !exists {
return 0
}
realmid, ok := mid.(int64)
if !ok {
return 0
}
return realmid
}
// 根据cookie中的mid来设置请求中的mid请求的arg必需是mcnmodel.CookieMidInterface
func getCookieMid(c *blademaster.Context, arg interface{}) preBindFuncType {
return func(c *blademaster.Context) (err error) {
var cookieInterface, ok = arg.(mcnmodel.CookieMidInterface)
if !ok || cookieInterface == nil {
return nil
}
var mid = getMid(c)
if mid == 0 {
err = ecode.AccessDenied
return
}
cookieInterface.SetMid(mid)
return
}
}
func cheatReq(c *blademaster.Context, arg interface{}) (err error) {
var mid = getMid(c)
if mid == 0 {
return
}
if conf.Conf.Other.IsWhiteList(mid) {
var cheatInterface, ok = arg.(mcnmodel.CheatInterface)
if ok && cheatInterface != nil {
if cheatInterface.Cheat() {
log.Warn("cheat happend, uri=%s, req=%+v", c.Request.RequestURI, arg)
}
}
}
return
}

View File

@@ -0,0 +1,22 @@
package http
import (
"testing"
"go-common/app/admin/main/mcn/model"
"go-common/library/net/http/blademaster/binding"
)
func TestValidater(t *testing.T) {
var req = model.MCNSignEntryReq{
MCNMID: 1,
BeginDate: "2018-01-01",
EndDate: "2018-01-01",
}
var err = binding.Validator.ValidateStruct(&req)
if err == nil {
t.FailNow()
} else {
t.Logf("err=%s", err)
}
}

View File

@@ -0,0 +1,269 @@
package http
import (
"context"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/library/net/http/blademaster"
)
func mcnState(c *blademaster.Context) {
oarg := new(mcnmodel.GetStateReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.McnGetState(context, arg.(*mcnmodel.GetStateReq))
},
"mcnState",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnExist(c *blademaster.Context) {
oarg := new(mcnmodel.GetStateReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.McnExist(context, arg.(*mcnmodel.GetStateReq))
},
"mcnExist",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnBaseInfo(c *blademaster.Context) {
oarg := new(mcnmodel.GetStateReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.McnBaseInfo(context, arg.(*mcnmodel.GetStateReq))
},
"mcnBaseInfo",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnApply(c *blademaster.Context) {
oarg := new(mcnmodel.McnApplyReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.McnApply(context, arg.(*mcnmodel.McnApplyReq))
},
"mcnApply",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnBindUpApply(c *blademaster.Context) {
oarg := new(mcnmodel.McnBindUpApplyReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.McnBindUpApply(context, arg.(*mcnmodel.McnBindUpApplyReq))
},
"mcnBindUpApply",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnUpConfirm(c *blademaster.Context) {
oarg := new(mcnmodel.McnUpConfirmReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.McnUpConfirm(context, arg.(*mcnmodel.McnUpConfirmReq))
},
"mcnBindUpApply",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnUpGetBind(c *blademaster.Context) {
oarg := new(mcnmodel.McnUpGetBindReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.McnUpGetBind(context, arg.(*mcnmodel.McnUpGetBindReq))
},
"mcnUpGetBind",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnGetDataSummary(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetDataSummaryReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.McnDataSummary(context, arg.(*mcnmodel.McnGetDataSummaryReq))
},
"mcnGetDataSummary",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnGetDataUpList(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetUpListReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.McnDataUpList(context, arg.(*mcnmodel.McnGetUpListReq))
},
"mcnGetDataUpList",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnGetAccountInfo(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetAccountReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetUpAccountInfo(context, arg.(*mcnmodel.McnGetAccountReq))
},
"mcnGetAccountInfo",
nil,
nil,
)(c)
}
func mcnGetOldInfo(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetMcnOldInfoReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.McnGetOldInfo(context, arg.(*mcnmodel.McnGetMcnOldInfoReq))
},
"McnGetOldInfo",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnGetRankUpFans(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetRankReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.McnGetRankUpFans(context, arg.(*mcnmodel.McnGetRankReq))
},
"McnGetRankUpFans",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnGetRankArchiveLikesOuter(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetRankReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.McnGetRankArchiveLikes(context, arg.(*mcnmodel.McnGetRankReq))
},
"mcnGetRankArchiveLikesOuter",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnGetRecommendPool(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetRecommendPoolReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetRecommendPool(context, arg.(*mcnmodel.McnGetRecommendPoolReq))
},
"GetRecommendPool",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnGetRecommendPoolTidList(c *blademaster.Context) {
oarg := new(mcnmodel.McnGetRecommendPoolTidListReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.GetRecommendPoolTidList(context, arg.(*mcnmodel.McnGetRecommendPoolTidListReq))
},
"GetRecommendPoolTidList",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnGetChangePermit(c *blademaster.Context) {
oarg := new(mcnmodel.McnChangePermitReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.McnChangePermit(context, arg.(*mcnmodel.McnChangePermitReq))
},
"McnChangePermit",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnPermitApplyGetBind(c *blademaster.Context) {
oarg := new(mcnmodel.McnUpGetBindReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.McnPermitApplyGetBind(context, arg.(*mcnmodel.McnUpGetBindReq))
},
"McnPermitApplyGetBind",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnUpPermitApplyConfirm(c *blademaster.Context) {
oarg := new(mcnmodel.McnUpConfirmReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.McnUpPermitApplyConfirm(context, arg.(*mcnmodel.McnUpConfirmReq))
},
"McnUpPermitApplyConfirm",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
func mcnPublicationPriceChange(c *blademaster.Context) {
oarg := new(mcnmodel.McnPublicationPriceChangeReq)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.McnPublicationPriceChange(context, arg.(*mcnmodel.McnPublicationPriceChangeReq))
},
"McnPublicationPriceChange",
[]preBindFuncType{getCookieMid(c, oarg)},
[]preHandleFuncType{cheatReq},
)(c)
}
// -------------- command ------------------
func cmdReloadRank(c *blademaster.Context) {
oarg := new(mcnmodel.CmdReloadRank)
httpGetFunc(
oarg,
func(context context.Context, arg interface{}) (res interface{}, err error) {
return srv.CmdReloadRankCache(context, arg.(*mcnmodel.CmdReloadRank))
},
"CmdReloadRank",
nil,
nil,
)(c)
}

View File

@@ -0,0 +1,69 @@
package http
import (
"bytes"
"io/ioutil"
"net/http"
"path"
"time"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
const (
maxFileSize = 20 << 20
)
func upload(c *bm.Context) {
c.Request.ParseMultipartForm(maxFileSize)
imageFile, header, err := c.Request.FormFile("file")
if err != nil {
log.Error("upload fail, no field file")
c.JSON(nil, err)
return
}
if header.Size > maxFileSize {
c.JSON(nil, ecode.MCNContractFileSize)
return
}
fileExt := path.Ext(header.Filename)
if fileExt == "" {
c.JSON(nil, ecode.MCNUnknownFileExt)
return
}
defer imageFile.Close()
bs, err := ioutil.ReadAll(imageFile)
if err != nil {
c.JSON(nil, err)
return
}
filetype := http.DetectContentType(bs)
switch filetype {
case
"image/jpeg",
"image/jpg",
"image/png",
"application/pdf":
case "application/octet-stream", "application/zip":
switch fileExt[1:] {
case "doc":
filetype = "application/doc"
case "docx":
filetype = "application/docx"
case "docm":
filetype = "application/docm"
}
case "application/msword":
filetype = "application/doc"
case "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
filetype = "application/docx"
case "application/vnd.ms-word.document.macroEnabled.12":
filetype = "application/docm"
default:
c.JSON(nil, ecode.MCNUnknownFileTypeErr)
return
}
c.JSON(srv.Upload(c, "", filetype, time.Now().Unix(), bytes.NewReader(bs)))
}

View File

@@ -0,0 +1,89 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"account.go",
"api.go",
"cmd.go",
"creative.go",
"data.go",
"mcn.go",
"msg.go",
"rank.go",
"service.go",
"uniquecheck.go",
"upload.go",
],
importpath = "go-common/app/interface/main/mcn/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/mcn/model:go_default_library",
"//app/interface/main/mcn/conf:go_default_library",
"//app/interface/main/mcn/dao/bfs:go_default_library",
"//app/interface/main/mcn/dao/cache:go_default_library",
"//app/interface/main/mcn/dao/datadao:go_default_library",
"//app/interface/main/mcn/dao/global:go_default_library",
"//app/interface/main/mcn/dao/mcndao:go_default_library",
"//app/interface/main/mcn/dao/msg:go_default_library",
"//app/interface/main/mcn/model:go_default_library",
"//app/interface/main/mcn/model/datamodel:go_default_library",
"//app/interface/main/mcn/model/mcnmodel:go_default_library",
"//app/interface/main/mcn/tool/worker:go_default_library",
"//app/service/main/account/api:go_default_library",
"//app/service/main/member/api:go_default_library",
"//app/service/main/member/model:go_default_library",
"//app/service/main/member/model/block:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/metadata:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/bluele/gcache:go_default_library",
"//vendor/github.com/jinzhu/gorm: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"],
)
go_test(
name = "go_default_test",
srcs = [
"account_test.go",
"cmd_test.go",
"mcn_test.go",
"msg_test.go",
"rank_test.go",
"service_test.go",
"uniquecheck_test.go",
"upload_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/mcn/model:go_default_library",
"//app/interface/main/mcn/conf:go_default_library",
"//app/interface/main/mcn/model:go_default_library",
"//app/interface/main/mcn/model/mcnmodel:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,25 @@
package service
import (
"context"
"go-common/app/interface/main/mcn/dao/global"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/library/log"
)
//GetUpAccountInfo get account info
func (s *Service) GetUpAccountInfo(c context.Context, arg *mcnmodel.McnGetAccountReq) (result *mcnmodel.McnGetAccountReply, err error) {
var data, e = global.GetInfo(c, arg.Mid)
err = e
if err != nil || data == nil {
log.Error("get info fail, req=%+v, err=%+v", arg, err)
return
}
result = new(mcnmodel.McnGetAccountReply)
result.Mid = data.Mid
result.Name = data.Name
log.Info("query acount info ok, req=%+v, result=%+v", arg, result)
return
}

View File

@@ -0,0 +1,26 @@
package service
import (
"context"
"testing"
"go-common/app/interface/main/mcn/model/mcnmodel"
"github.com/smartystreets/goconvey/convey"
)
func TestServiceGetUpAccountInfo(t *testing.T) {
convey.Convey("GetUpAccountInfo", t, func(ctx convey.C) {
var (
c = context.Background()
arg = &mcnmodel.McnGetAccountReq{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.GetUpAccountInfo(c, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,89 @@
package service
import (
"context"
"go-common/app/interface/main/mcn/dao/mcndao"
"go-common/app/interface/main/mcn/model/datamodel"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/library/log"
)
// McnGetRankArchiveLikesAPI get rank archive likes
func (s *Service) McnGetRankArchiveLikesAPI(c context.Context, arg *mcnmodel.McnGetRankAPIReq) (res *mcnmodel.McnGetRankUpFansReply, err error) {
res, err = s.getRankResultAPI(c, arg, s.mcndao.GetRankArchiveLikes)
return
}
func (s *Service) getRankResultAPI(c context.Context, arg *mcnmodel.McnGetRankAPIReq, rankFunc mcndao.RankFunc) (res *mcnmodel.McnGetRankUpFansReply, err error) {
v, err := rankFunc(arg.SignID)
if err != nil || v == nil {
log.Error("get rank fail, sign id=%d, err=%s", arg.SignID, err)
return
}
res = new(mcnmodel.McnGetRankUpFansReply)
res.Result = v.GetList(arg.Tid, arg.DataType)
res.TypeList = v.GetTypeList(arg.DataType)
return
}
// GetMcnSummaryAPI .
func (s *Service) GetMcnSummaryAPI(c context.Context, arg *mcnmodel.McnGetDataSummaryReq) (res *mcnmodel.McnGetDataSummaryReply, err error) {
return s.datadao.GetMcnSummaryCache(c, arg.SignID, datamodel.GetLastDay())
}
// GetIndexIncAPI .
func (s *Service) GetIndexIncAPI(c context.Context, arg *mcnmodel.McnGetIndexIncReq) (res *mcnmodel.McnGetIndexIncReply, err error) {
return s.datadao.GetIndexIncCache(c, arg.SignID, datamodel.GetLastDay(), arg.Type)
}
// GetIndexSourceAPI .
func (s *Service) GetIndexSourceAPI(c context.Context, arg *mcnmodel.McnGetIndexSourceReq) (res *mcnmodel.McnGetIndexSourceReply, err error) {
return s.datadao.GetIndexSourceCache(c, arg.SignID, datamodel.GetLastDay(), arg.Type)
}
// GetPlaySourceAPI .
func (s *Service) GetPlaySourceAPI(c context.Context, arg *mcnmodel.McnGetPlaySourceReq) (res *mcnmodel.McnGetPlaySourceReply, err error) {
return s.datadao.GetPlaySourceCache(c, arg.SignID, datamodel.GetLastDay())
}
// GetMcnFansAPI .
func (s *Service) GetMcnFansAPI(c context.Context, arg *mcnmodel.McnGetMcnFansReq) (res *mcnmodel.McnGetMcnFansReply, err error) {
return s.datadao.GetMcnFansCache(c, arg.SignID, datamodel.GetLastDay())
}
// GetMcnFansIncAPI .
func (s *Service) GetMcnFansIncAPI(c context.Context, arg *mcnmodel.McnGetMcnFansIncReq) (res *mcnmodel.McnGetMcnFansIncReply, err error) {
return s.datadao.GetMcnFansIncCache(c, arg.SignID, datamodel.GetLastDay())
}
// GetMcnFansDecAPI .
func (s *Service) GetMcnFansDecAPI(c context.Context, arg *mcnmodel.McnGetMcnFansDecReq) (res *mcnmodel.McnGetMcnFansDecReply, err error) {
return s.datadao.GetMcnFansDecCache(c, arg.SignID, datamodel.GetLastDay())
}
// GetMcnFansAttentionWayAPI .
func (s *Service) GetMcnFansAttentionWayAPI(c context.Context, arg *mcnmodel.McnGetMcnFansAttentionWayReq) (res *mcnmodel.McnGetMcnFansAttentionWayReply, err error) {
return s.datadao.GetMcnFansAttentionWayCache(c, arg.SignID, datamodel.GetLastDay())
}
// GetFansBaseFansAttrAPI .
func (s *Service) GetFansBaseFansAttrAPI(c context.Context, arg *mcnmodel.McnGetBaseFansAttrReq) (res *mcnmodel.McnGetBaseFansAttrReply, err error) {
return s.datadao.GetFansBaseFansAttrCache(c, arg.SignID, datamodel.GetLastWeek(), arg.UserType)
}
// GetFansAreaAPI .
func (s *Service) GetFansAreaAPI(c context.Context, arg *mcnmodel.McnGetFansAreaReq) (res *mcnmodel.McnGetFansAreaReply, err error) {
return s.datadao.GetFansAreaCache(c, arg.SignID, datamodel.GetLastWeek(), arg.UserType)
}
// GetFansTypeAPI .
func (s *Service) GetFansTypeAPI(c context.Context, arg *mcnmodel.McnGetFansTypeReq) (res *mcnmodel.McnGetFansTypeReply, err error) {
return s.datadao.GetFansTypeCache(c, arg.SignID, datamodel.GetLastWeek(), arg.UserType)
}
// GetFansTagAPI .
func (s *Service) GetFansTagAPI(c context.Context, arg *mcnmodel.McnGetFansTagReq) (res *mcnmodel.McnGetFansTagReply, err error) {
return s.datadao.GetFansTagCache(c, arg.SignID, datamodel.GetLastWeek(), arg.UserType)
}

View File

@@ -0,0 +1,13 @@
package service
import (
"context"
"go-common/app/interface/main/mcn/model/mcnmodel"
)
//CmdReloadRankCache reload cache
func (s *Service) CmdReloadRankCache(c context.Context, arg *mcnmodel.CmdReloadRank) (res *mcnmodel.CommonReply, err error) {
err = s.mcndao.ReloadRank(arg.SignID)
return
}

View File

@@ -0,0 +1,26 @@
package service
import (
"context"
"testing"
"go-common/app/interface/main/mcn/model/mcnmodel"
"github.com/smartystreets/goconvey/convey"
)
func TestServiceCmdReloadRankCache(t *testing.T) {
convey.Convey("CmdReloadRankCache", t, func(ctx convey.C) {
var (
c = context.Background()
arg = &mcnmodel.CmdReloadRank{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := s.CmdReloadRankCache(c, arg)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,21 @@
package service
import (
"context"
"net/url"
adminmodel "go-common/app/admin/main/mcn/model"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/library/ecode"
"go-common/library/log"
)
// CreativeHandle .
func (s *Service) CreativeHandle(c context.Context, arg *mcnmodel.CreativeCommonReq, params url.Values, key string) (res interface{}, err error) {
if !s.checkPermission(c, arg.McnMid, arg.UpMid, adminmodel.AttrDataPermitBit) {
log.Warn("mcn permission insufficient, upmid=%d, mcnmid=%d", arg.UpMid, arg.McnMid)
err = ecode.MCNPermissionInsufficient
return
}
return s.datadao.HTTPDataHandle(c, params, key)
}

View File

@@ -0,0 +1,198 @@
package service
import (
"context"
"go-common/app/interface/main/mcn/model"
"go-common/app/interface/main/mcn/model/datamodel"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/library/ecode"
"go-common/library/log"
)
//GetMcnGetIndexInc .
func (s *Service) GetMcnGetIndexInc(c context.Context, arg *mcnmodel.McnGetIndexIncReq) (res *mcnmodel.McnGetIndexIncReply, err error) {
mcnSign, err := s.getMcnWithState(c, arg.McnMid, model.MCNSignStateOnSign)
if err != nil {
if err != ecode.NothingFound {
log.Error("error get state, err=%s", err)
}
return
}
if res, err = s.datadao.GetIndexIncCache(c, mcnSign.ID, datamodel.GetLastDay(), arg.Type); err != nil {
log.Error("get data fail, err=%v", err)
return
}
return
}
// GetMcnGetIndexSource .
func (s *Service) GetMcnGetIndexSource(c context.Context, arg *mcnmodel.McnGetIndexSourceReq) (res *mcnmodel.McnGetIndexSourceReply, err error) {
mcnSign, err := s.getMcnWithState(c, arg.McnMid, model.MCNSignStateOnSign)
if err != nil {
if err != ecode.NothingFound {
log.Error("error get state, err=%s", err)
}
return
}
if res, err = s.datadao.GetIndexSourceCache(c, mcnSign.ID, datamodel.GetLastDay(), arg.Type); err != nil {
log.Error("get data fail, err=%v", err)
return
}
return
}
// GetPlaySource .
func (s *Service) GetPlaySource(c context.Context, arg *mcnmodel.McnGetPlaySourceReq) (res *mcnmodel.McnGetPlaySourceReply, err error) {
mcnSign, err := s.getMcnWithState(c, arg.McnMid, model.MCNSignStateOnSign)
if err != nil {
if err != ecode.NothingFound {
log.Error("error get state, err=%s", err)
}
return
}
if res, err = s.datadao.GetPlaySourceCache(c, mcnSign.ID, datamodel.GetLastDay()); err != nil {
log.Error("get data fail, err=%v", err)
}
return
}
// GetMcnFans .
func (s *Service) GetMcnFans(c context.Context, arg *mcnmodel.McnGetMcnFansReq) (res *mcnmodel.McnGetMcnFansReply, err error) {
mcnSign, err := s.getMcnWithState(c, arg.McnMid, model.MCNSignStateOnSign)
if err != nil {
if err != ecode.NothingFound {
log.Error("error get state, err=%s", err)
}
return
}
if res, err = s.datadao.GetMcnFansCache(c, mcnSign.ID, datamodel.GetLastDay()); err != nil {
log.Error("get data fail, err=%v", err)
}
return
}
// GetMcnFansInc .
func (s *Service) GetMcnFansInc(c context.Context, arg *mcnmodel.McnGetMcnFansIncReq) (res *mcnmodel.McnGetMcnFansIncReply, err error) {
mcnSign, err := s.getMcnWithState(c, arg.McnMid, model.MCNSignStateOnSign)
if err != nil {
if err != ecode.NothingFound {
log.Error("error get state, err=%s", err)
}
return
}
if res, err = s.datadao.GetMcnFansIncCache(c, mcnSign.ID, datamodel.GetLastDay()); err != nil {
log.Error("get data fail, err=%v", err)
}
return
}
// GetMcnFansDec .
func (s *Service) GetMcnFansDec(c context.Context, arg *mcnmodel.McnGetMcnFansDecReq) (res *mcnmodel.McnGetMcnFansDecReply, err error) {
mcnSign, err := s.getMcnWithState(c, arg.McnMid, model.MCNSignStateOnSign)
if err != nil {
if err != ecode.NothingFound {
log.Error("error get state, err=%s", err)
}
return
}
if res, err = s.datadao.GetMcnFansDecCache(c, mcnSign.ID, datamodel.GetLastDay()); err != nil {
log.Error("get data fail, err=%v", err)
}
return
}
// GetMcnFansAttentionWay .
func (s *Service) GetMcnFansAttentionWay(c context.Context, arg *mcnmodel.McnGetMcnFansAttentionWayReq) (res *mcnmodel.McnGetMcnFansAttentionWayReply, err error) {
mcnSign, err := s.getMcnWithState(c, arg.McnMid, model.MCNSignStateOnSign)
if err != nil {
if err != ecode.NothingFound {
log.Error("error get state, err=%s", err)
}
return
}
if res, err = s.datadao.GetMcnFansAttentionWayCache(c, mcnSign.ID, datamodel.GetLastDay()); err != nil {
log.Error("get data fail, err=%v", err)
}
return
}
// GetBaseFansAttrReq .
func (s *Service) GetBaseFansAttrReq(c context.Context, arg *mcnmodel.McnGetBaseFansAttrReq) (res *mcnmodel.McnGetBaseFansAttrReply, err error) {
mcnSign, err := s.getMcnWithState(c, arg.McnMid, model.MCNSignStateOnSign)
if err != nil {
if err != ecode.NothingFound {
log.Error("error get state, err=%s", err)
}
return
}
if res, err = s.datadao.GetFansBaseFansAttrCache(c, mcnSign.ID, datamodel.GetLastWeek(), arg.UserType); err != nil {
log.Error("get data fail, err=%v", err)
}
return
}
// GetFansArea .
func (s *Service) GetFansArea(c context.Context, arg *mcnmodel.McnGetFansAreaReq) (res *mcnmodel.McnGetFansAreaReply, err error) {
mcnSign, err := s.getMcnWithState(c, arg.McnMid, model.MCNSignStateOnSign)
if err != nil {
if err != ecode.NothingFound {
log.Error("error get state, err=%s", err)
}
return
}
if res, err = s.datadao.GetFansAreaCache(c, mcnSign.ID, datamodel.GetLastWeek(), arg.UserType); err != nil {
log.Error("get data fail, err=%v", err)
}
return
}
// GetFansType .
func (s *Service) GetFansType(c context.Context, arg *mcnmodel.McnGetFansTypeReq) (res *mcnmodel.McnGetFansTypeReply, err error) {
mcnSign, err := s.getMcnWithState(c, arg.McnMid, model.MCNSignStateOnSign)
if err != nil {
if err != ecode.NothingFound {
log.Error("error get state, err=%s", err)
}
return
}
if res, err = s.datadao.GetFansTypeCache(c, mcnSign.ID, datamodel.GetLastWeek(), arg.UserType); err != nil {
log.Error("get data fail, err=%v", err)
}
return
}
// GetFansTag .
func (s *Service) GetFansTag(c context.Context, arg *mcnmodel.McnGetFansTagReq) (res *mcnmodel.McnGetFansTagReply, err error) {
mcnSign, err := s.getMcnWithState(c, arg.McnMid, model.MCNSignStateOnSign)
if err != nil {
if err != ecode.NothingFound {
log.Error("error get state, err=%s", err)
}
return
}
if res, err = s.datadao.GetFansTagCache(c, mcnSign.ID, datamodel.GetLastWeek(), arg.UserType); err != nil {
log.Error("get data fail, err=%v", err)
}
return
}

View File

@@ -0,0 +1,799 @@
package service
import (
"context"
"time"
adminmodel "go-common/app/admin/main/mcn/model"
"go-common/app/interface/main/mcn/dao/cache"
"go-common/app/interface/main/mcn/dao/global"
"go-common/app/interface/main/mcn/model"
"go-common/app/interface/main/mcn/model/mcnmodel"
accgrpc "go-common/app/service/main/account/api"
memgrpc "go-common/app/service/main/member/api"
memmdl "go-common/app/service/main/member/model"
"go-common/app/service/main/member/model/block"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
"go-common/app/interface/main/mcn/conf"
"go-common/app/interface/main/mcn/dao/mcndao"
"strings"
"github.com/jinzhu/gorm"
)
// getMcnWithState
// if state is nil, state is not checked
func (s *Service) getMcnWithState(c context.Context, mcnmid int64, state ...model.MCNSignState) (mcnSign *mcnmodel.McnSign, err error) {
mcnSign, err = s.mcndao.McnSign(c, mcnmid)
if err != nil {
if err != ecode.NothingFound {
log.Error("error get state, err=%s", err)
}
return
}
if mcnSign == nil {
err = ecode.NothingFound
return
}
var ok = false
if state == nil {
ok = true
} else {
for _, s := range state {
if mcnSign.State == s {
ok = true
break
}
}
}
if !ok {
log.Info("mcnmid=%d, mcn is in %d, should in (%v)", mcnmid, mcnSign.State, state)
err = ecode.MCNNotAllowed
return
}
return
}
func (s *Service) checkPermission(c context.Context, mcnMid, upMid int64, permissions ...adminmodel.AttrBasePermit) (res bool) {
var permLen = len(permissions)
if permLen == 0 {
return
} else if permLen == 1 {
// 基础权限直接放过
if permissions[0] == adminmodel.AttrBasePermitBit {
return true
}
}
mcnSign, err := s.getMcnWithState(c, mcnMid, model.MCNSignStateOnSign)
if err != nil {
log.Error("get mcn fail, mcnmid=%d, err=%v", mcnMid, err)
return
}
permForUp, err := s.mcndao.UpPermission(c, mcnSign.ID, upMid)
if err != nil || permForUp == nil {
log.Error("get up permission fail, signID=%d, upmid=%d, err=%v or up not found", mcnSign.ID, upMid, err)
return
}
// 比较mcn与up的权限
var wantPermission uint32
for _, v := range permissions {
wantPermission = wantPermission | (1 << v)
}
var resultPermission = wantPermission & mcnSign.Permission & permForUp.Permission
if resultPermission != wantPermission {
log.Warn("mcn doesnt have permission, mcn perm=0x%x, up perm=0x%x, want=0x%x, lack=0x%x", mcnSign.Permission, permForUp.Permission, wantPermission, resultPermission^wantPermission)
return
}
res = true
return
}
//McnGetState mcn state
func (s *Service) McnGetState(c context.Context, arg *mcnmodel.GetStateReq) (res *mcnmodel.McnGetStateReply, err error) {
mcnSign, err := s.getMcnWithState(c, arg.McnMid)
if err != nil {
if err != ecode.NothingFound {
log.Error("error get state, err=%s", err)
}
return
}
res = new(mcnmodel.McnGetStateReply)
res.State = int8(mcnSign.State)
if mcnSign.State == model.MCNSignStateOnReject {
res.RejectReason = mcnSign.RejectReason
}
log.Info("mcn_state=%d, mcn_id=%d", res.State, arg.McnMid)
return
}
//McnExist .
func (s *Service) McnExist(c context.Context, arg *mcnmodel.GetStateReq) (res *mcnmodel.McnExistReply, err error) {
res = new(mcnmodel.McnExistReply)
_, err = s.getMcnWithState(c, arg.McnMid)
if err == ecode.NothingFound {
res.Exist = 0
return
} else if err != nil {
log.Error("error get state, err=%s", err)
return
}
res.Exist = 1
return
}
// McnBaseInfo .
func (s *Service) McnBaseInfo(c context.Context, arg *mcnmodel.GetStateReq) (res *mcnmodel.McnBaseInfoReply, err error) {
res = new(mcnmodel.McnBaseInfoReply)
mcnSign, err := s.getMcnWithState(c, arg.McnMid)
if err != nil {
if err != ecode.NothingFound {
log.Error("error get state, err=%s", err)
}
return
}
res.CopyFromMcnInfo(mcnSign)
return
}
//McnApply .
func (s *Service) McnApply(c context.Context, arg *mcnmodel.McnApplyReq) (res *mcnmodel.CommonReply, err error) {
mcnSign, err := s.getMcnWithState(c, arg.McnMid, model.MCNSignStateOnReject, model.MCNSignStateNoApply)
if err != nil {
if err != ecode.NothingFound {
log.Error("error get state, err=%s", err)
}
return
}
var sign mcnmodel.McnSign
if err = s.uniqueChecker.CheckIsUniqe(arg); err != nil {
log.Info("check unique fail, err=%s, arg=%v", err, arg)
return
}
arg.CopyTo(&sign)
sign.ID = mcnSign.ID
sign.State = model.MCNSignStateOnReview
var db = s.mcndao.GetMcnDB()
if err = db.Table(sign.TableName()).Where("id=?", sign.ID).Updates(map[string]interface{}{
"company_name": sign.CompanyName,
"company_license_id": sign.CompanyLicenseID,
"contact_name": sign.ContactName,
"contact_title": sign.ContactTitle,
"contact_idcard": sign.ContactIdcard,
"contact_phone": sign.ContactPhone,
"company_license_link": sign.CompanyLicenseLink,
"contract_link": sign.ContractLink,
"state": sign.State,
}).Error; err != nil {
log.Error("save mcn fail, mcn mid=%d, row id=%d", sign.McnMid, sign.ID)
err = ecode.ServerErr
return
}
s.mcndao.DelCacheMcnSign(c, arg.McnMid)
s.worker.Add(func() {
s.loadMcnUniqueCache()
})
return
}
//McnBindUpApply .
func (s *Service) McnBindUpApply(c context.Context, arg *mcnmodel.McnBindUpApplyReq) (res *mcnmodel.McnBindUpApplyReply, err error) {
if arg.BeginDate > arg.EndDate {
err = ecode.MCNUpBindUpSTimeLtETime
return
}
// 查询mcn状态
mcnSign, err := s.getMcnWithState(c, arg.McnMid, model.MCNSignStateOnSign)
if err != nil {
if err != ecode.NothingFound {
log.Error("error get state, err=%s", err)
}
return
}
// 0.检查是否封禁
var blockArg = memgrpc.MemberMidReq{Mid: arg.UpMid, RemoteIP: metadata.String(c, metadata.RemoteIP)}
var blockInfo, e = global.GetMemGRPC().BlockInfo(c, &blockArg)
if e == nil {
if blockInfo.BlockStatus > int32(block.BlockStatusFalse) {
log.Info("up is blocked, mid=%d, blockstatus=%d", arg.UpMid, blockInfo.BlockStatus)
err = ecode.MCNUpBindUpIsBlocked
return
}
} else {
log.Error("get block info error, err=%s", e)
}
// 1.检查是否是蓝V用户
var (
memberInfo *memgrpc.MemberInfoReply
memberArg = memgrpc.MemberMidReq{Mid: arg.UpMid, RemoteIP: metadata.String(c, metadata.RemoteIP)}
)
if memberInfo, err = global.GetMemGRPC().Member(c, &memberArg); err != nil {
log.Error("get member info error, err=%s", err)
} else {
if memberInfo.OfficialInfo != nil &&
(memberInfo.OfficialInfo.Role == memmdl.OfficialRoleBusiness ||
memberInfo.OfficialInfo.Role == memmdl.OfficialRoleGov ||
memberInfo.OfficialInfo.Role == memmdl.OfficialRoleMedia ||
memberInfo.OfficialInfo.Role == memmdl.OfficialRoleOther) {
err = ecode.MCNUpBindUpIsBlueUser
return
}
}
// 2.查询当前up状态
upList, err := s.mcndao.GetUpBind("up_mid=?", arg.UpMid)
if err != nil {
log.Error("get up bind fail, err=%s", err)
err = ecode.ServerErr
return
}
// 3.可以申请绑定的up主才能绑定
var mcnUp *mcnmodel.McnUp
for _, v := range upList {
if !v.IsBindable() {
log.Info("up is in state(%d), cannot be bind again. id=%d, upmid=%d, signid=%d, mcnSign=%d", v.State, v.ID, v.UpMid, v.SignID, v.McnMid)
err = ecode.MCNUpCannotBind
return
}
if v.IsBeingBindedWithMcn(mcnSign) {
log.Info("up is being binded with mcnSign, state=%d, id=%d, signid=%d, mcnSign=%d, mcn_mid=%d", v.State, v.State, v.ID, v.SignID, v.McnMid)
err = ecode.MCNUpBindUpAlreadyInProgress
return
}
if v.SignID == mcnSign.ID {
mcnUp = v
}
}
if arg.UpType == 1 {
// 站外up主需要满足条件
// 1.粉丝数≤100 或 2. 投稿数2及90天内未投稿 12并列关系满足其一即可申请
baseInfoMap, e := s.mcndao.GetUpBaseInfo("article_count_accumulate, activity, fans_count, mid", []int64{arg.UpMid})
if e == nil {
var upInfo, ok = baseInfoMap[arg.UpMid]
if ok && upInfo != nil {
//upInfo.Activity 1高2中3低4流失
//高=30天内有投稿
//中=31~90天内有投稿
//低=91~180天内有投稿
//流失=180内以上未投稿
if !(upInfo.FansCount <= 100 || (upInfo.ArticleCountAccumulate < 2 && upInfo.Activity > 2)) {
err = ecode.MCNUpOutSiteIsNotQualified
log.Error("outsite cannot bind, up fans count(%d) > 100", upInfo.FansCount)
return
}
} else {
log.Warn("up info is not found in up base info, up=%d", arg.UpMid)
}
}
}
// 站外信息是否OK
if !arg.IsSiteInfoOk() {
err = ecode.MCNUpBindInvalidURL
log.Warn("arg error, up is out site up, but site url is not valid, arg=%v", arg)
return
}
// 只能设置mcn自己有的权限如果要设置其他权限返回错误。
// 只有mcn有的权限才可以申请up主的权限
_, err = mcnShouldContainUpPermission(mcnSign.Permission, arg.GetAttrPermitVal())
if err != nil {
return
}
// 3.绑定Up主如果已有记录则更新记录
bindup, affectedRow, err := s.mcndao.BindUp(mcnUp, mcnSign, arg)
if err != nil {
log.Error("fail to bind up, mcnmid=%d, upmid=%d err=%s", arg.McnMid, arg.UpMid, err)
return
}
res = new(mcnmodel.McnBindUpApplyReply)
res.BindID = bindup.ID
// 4.发送站内信息
if arg.UpMid != arg.McnMid {
var nickname = global.GetName(c, arg.McnMid)
var msg = adminmodel.ArgMsg{
MSGType: adminmodel.McnUpBindAuthApply,
MIDs: []int64{arg.UpMid},
McnName: nickname,
McnMid: arg.McnMid,
CompanyName: mcnSign.CompanyName,
SignUpID: bindup.ID,
}
s.sendMsg(&msg)
}
log.Info("bind up apply success, mcn=%d, upmid=%d, rowaffected=%d", arg.McnMid, arg.UpMid, affectedRow)
return
}
//McnUpConfirm .
func (s *Service) McnUpConfirm(c context.Context, arg *mcnmodel.McnUpConfirmReq) (res *mcnmodel.CommonReply, err error) {
// 1.查询当前up状态
upList, err := s.mcndao.GetUpBind("id=? and up_mid=? and state=?", arg.BindID, arg.UpMid, model.MCNUPStateNoAuthorize)
if err != nil {
log.Error("get up bind fail, err=%s", err)
err = ecode.ServerErr
return
}
// 不存在
if len(upList) == 0 {
log.Info("bind id not found, id=%d", arg.BindID)
err = ecode.MCNNotAllowed
return
}
var upBind = upList[0]
// 查询mcn状态
mcnSign, err := s.getMcnWithState(c, upBind.McnMid, model.MCNSignStateOnSign)
if err != nil {
if err != ecode.MCNStateInvalid {
log.Error("error get state, err=%s", err)
}
return
}
if mcnSign.ID != upBind.SignID {
log.Error("bind id not same with mcn signid, bind id=%d, signid=%d", upBind.ID, upBind.SignID)
err = ecode.MCNUpBindInvalid
return
}
var state = model.MCNUPStateOnRefuse
if arg.Choice {
state = model.MCNUPStateOnReview
}
// 更新状态
err = s.mcndao.UpConfirm(arg, state)
if err != nil {
log.Error("fail to update up bind, bind id=%d, upmid=%d, err=%s", arg.BindID, arg.UpMid, err)
err = ecode.ServerErr
return
}
// 同意
if arg.Choice {
var mcnName = global.GetName(c, mcnSign.McnMid)
var msg = adminmodel.ArgMsg{
MSGType: adminmodel.McnUpBindAuthReview,
MIDs: []int64{arg.UpMid},
McnName: mcnName,
McnMid: mcnSign.McnMid,
CompanyName: mcnSign.CompanyName,
}
s.sendMsg(&msg)
} else {
var upName = global.GetName(c, arg.UpMid)
var msg = adminmodel.ArgMsg{
MSGType: adminmodel.McnUpBindAuthApplyRefuse,
MIDs: []int64{mcnSign.McnMid},
UpMid: arg.UpMid,
UpName: upName,
}
s.sendMsg(&msg)
}
log.Info("up bind change, bind id=%d, upmid=%d, isaccept=%t", arg.BindID, arg.UpMid, arg.Choice)
return
}
//McnUpGetBind .
func (s *Service) McnUpGetBind(c context.Context, arg *mcnmodel.McnUpGetBindReq) (res *mcnmodel.McnGetBindReply, err error) {
res, err = s.mcndao.GetBindInfo(arg)
if err != nil {
log.Error("fail to get bind info, err=%s", err)
return
}
accInfo, err := global.GetInfo(c, int64(res.McnMid))
if err == nil && accInfo != nil {
res.McnName = accInfo.Name
}
res.Finish()
res.UpAuthLink = model.BuildBfsURL(res.UpAuthLink, s.c.BFS.Key, s.c.BFS.Secret, s.c.BFS.Bucket, model.BfsEasyPath)
return
}
//McnDataSummary .
func (s *Service) McnDataSummary(c context.Context, arg *mcnmodel.McnGetDataSummaryReq) (res *mcnmodel.McnGetDataSummaryReply, err error) {
mcnSign, err := s.getMcnWithState(c, arg.McnMid, model.MCNSignStateOnSign)
if err != nil {
if err != ecode.NothingFound {
log.Error("error get state, err=%s", err)
}
return
}
var today = time.Now().Add(-12 * time.Hour)
res, err = s.datadao.GetMcnSummaryCache(c, mcnSign.ID, today)
if err != nil {
log.Error("fail to get mcn data, sign id=%d, mcnmid=%d, err=%s", mcnSign.ID, mcnSign.McnMid, err)
return
}
// today is not found, try yesterday
if res == nil {
res, err = s.mcndao.McnDataSummary(c, mcnSign.ID, today.AddDate(0, 0, -1))
if err != nil {
log.Error("fail to get mcn data, sign id=%d, mcnmid=%d, err=%s", mcnSign.ID, mcnSign.McnMid, err)
return
}
}
if res == nil {
log.Error("fail to get mcn data, res = nil, sign id=%d", mcnSign.ID)
res = new(mcnmodel.McnGetDataSummaryReply)
}
return
}
//McnDataUpList .
func (s *Service) McnDataUpList(c context.Context, arg *mcnmodel.McnGetUpListReq) (res *mcnmodel.McnGetUpListReply, err error) {
mcnSign, err := s.getMcnWithState(c, arg.McnMid, model.MCNSignStateOnSign)
if err != nil {
if err != ecode.NothingFound {
log.Error("error get state, err=%s", err)
}
return
}
generateDate, err := s.mcndao.GetDataUpLatestDate(mcnmodel.DataTypeAccumulate, mcnSign.ID)
if err != nil {
if err == gorm.ErrRecordNotFound {
err = nil
log.Warn("no data list found for mcn=%d, sign id=%d", mcnSign.McnMid, mcnSign.ID)
var now = time.Now()
generateDate = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local)
} else {
log.Error("fail to get latest generate up date, err=%s", err)
return
}
}
// 获取数据
upData, err := s.mcndao.GetAllUpData(int64(mcnSign.ID), arg.UpMid, generateDate)
// 在正式数据出来之前,临时使用
//upData, err := s.mcndao.GetAllUpDataTemp(int64(mcnSign.ID), arg.UpMid, time.Now())
var mids []int64
for _, v := range upData {
mids = append(mids, v.UpMid)
v.Permission = v.Permission & mcnSign.Permission
}
var infosReply *accgrpc.InfosReply
var midtidmap map[int64]int64
var accInfos map[int64]*accgrpc.Info
if len(mids) > 0 {
var e error
infosReply, e = global.GetAccGRPC().Infos3(c, &accgrpc.MidsReq{Mids: mids})
if e != nil {
log.Warn("fail to get info, err=%s", e)
} else {
accInfos = infosReply.Infos
}
midtidmap, e = s.mcndao.GetActiveTid(mids)
if e != nil {
log.Warn("fail to get activit, err=%s", e)
}
}
res = new(mcnmodel.McnGetUpListReply)
for _, v := range upData {
var info, ok = accInfos[v.UpMid]
if ok {
v.Name = info.Name
}
if v.State != int8(model.MCNUPStateOnSign) {
// MCNUPStateOnSign 与 MCNUPStateOnPreOpen 状态下 不隐藏时间
v.HideData(!(v.State == int8(model.MCNUPStateOnSign) ||
v.State == int8(model.MCNUPStateOnPreOpen)))
}
tid, ok := midtidmap[v.UpMid]
if ok {
v.TidName = cache.GetTidName(tid)
v.ActiveTid = int16(tid)
}
res.Result = append(res.Result, v)
}
res.Finish()
return
}
//McnGetOldInfo .
func (s *Service) McnGetOldInfo(c context.Context, arg *mcnmodel.McnGetMcnOldInfoReq) (res *mcnmodel.McnGetMcnOldInfoReply, err error) {
mcnSign, err := s.getMcnWithState(c, arg.McnMid, model.MCNSignStateNoApply)
if err != nil {
if err != ecode.NothingFound {
log.Error("error get state, err=%s", err)
}
return
}
info, err := s.mcndao.GetMcnOldInfo(mcnSign.McnMid)
if err != nil {
if err == ecode.NothingFound {
err = nil
} else {
log.Error("fail get mcn old info err=%s", err)
return
}
}
res = new(mcnmodel.McnGetMcnOldInfoReply)
res.Copy(info)
return
}
func getUpPermitString(permission uint32) (ps []string) {
for permit := range adminmodel.PermitMap {
var p = adminmodel.AttrVal(permission, uint(permit))
if p <= 0 {
continue
}
ps = append(ps, permit.String())
}
return
}
// 检查up主权限是否是mcn的子集
// mcnPermission mcn自己的permission
// upPermission up的permission
// return finalPermission = mcnPermission &upPermission
func mcnShouldContainUpPermission(mcnPermission, upPermission uint32) (finalPermission uint32, err error) {
// 3.只能设置mcn自己有的权限如果要设置其他权限返回错误。
// 只有mcn有的权限才可以申请up主的权限
finalPermission = mcnPermission & upPermission
if finalPermission != upPermission {
log.Error("mcn has no permission to change, mcn=0x%x, wantup=0x%x, notallowd=0x%x", mcnPermission, upPermission, finalPermission^upPermission)
err = ecode.MCNChangePermissionLackPermission
return
}
return
}
//McnChangePermit change up's permission
func (s *Service) McnChangePermit(c context.Context, arg *mcnmodel.McnChangePermitReq) (res *mcnmodel.McnChangePermitReply, err error) {
mcnSign, err := s.getMcnWithState(c, arg.McnMid, model.MCNSignStateOnSign)
if err != nil {
if err != ecode.NothingFound {
log.Error("error get state, err=%s", err)
}
return
}
// 1.检查Up主关系只有“已签约”,“待开启”状态的Up主可以修改
// 2.查询当前up状态
upList, err := s.mcndao.GetUpBind("up_mid=? and sign_id=? and state in (?)", arg.UpMid, mcnSign.ID, mcndao.UpSignedStates)
if err != nil {
log.Error("get up bind fail, err=%v", err)
err = ecode.ServerErr
return
}
if len(upList) == 0 {
log.Error("up is not in signed state with mcn, up_mid=%d and sign_id=%d , need state in (%v)", arg.UpMid, mcnSign.ID, mcndao.UpSignedStates)
err = ecode.MCNUpSignStateInvalid
return
}
var oldUp = upList[0]
var newPermission = arg.GetAttrPermitVal()
if oldUp.Permission == uint32(newPermission) {
log.Error("permission not changed, arg=%+v", arg)
err = ecode.MCNChangePermissionSamePermission
return
}
// 2.只能设置mcn自己有的权限如果要设置其他权限返回错误。
// 只有mcn有的权限才可以申请up主的权限
maskedPermission, err := mcnShouldContainUpPermission(mcnSign.Permission, newPermission)
if err != nil {
return
}
// 如果是自己,则直接进行修改
if arg.UpMid == mcnSign.McnMid {
var _, e = s.mcndao.UpdateBindUp(map[string]interface{}{
"permission": maskedPermission,
}, "up_mid=? and sign_id=?", arg.UpMid, mcnSign.ID)
if e != nil {
err = e
log.Error("fail to change up permission, err=%v, arg=%v", err, arg)
return
}
return
}
// 3.检查是否有对应up主的修改请求,如果有就拒绝这次修改
existedApply, _ := s.mcndao.GetUpPermissionApply("id", "sign_id=? and up_mid=? and state in (?)", mcnSign.ID, arg.UpMid, mcndao.UpPermissionApplyCannotApplyStates)
if len(existedApply) > 0 {
log.Error("apply already exist, id=%d, sign id=%d, mid=%d", existedApply[0].ID, existedApply[0].SignID, existedApply[0].UpMid)
err = ecode.MCNChangePermissionAlreadyInProgress
return
}
// 真的去增加permission
var permissionApply = mcnmodel.McnUpPermissionApply{
SignID: mcnSign.ID,
McnMid: mcnSign.McnMid,
UpMid: arg.UpMid,
NewPermission: maskedPermission,
OldPermission: oldUp.Permission,
UpAuthLink: arg.UpAuthLink,
}
var db = s.mcndao.GetMcnDB()
err = db.Create(&permissionApply).Error
if err != nil {
log.Error("create permission apply fail, err=%v, arg=%+v", err, arg)
return
}
// 返回bind_id
res = &mcnmodel.McnChangePermitReply{BindID: permissionApply.ID}
// 4.发送站内信息
if arg.UpMid != arg.McnMid {
var nickname = global.GetName(c, arg.McnMid)
var msg = adminmodel.ArgMsg{
MSGType: adminmodel.McnApplyUpChangePermit,
MIDs: []int64{arg.UpMid},
McnName: nickname,
McnMid: arg.McnMid,
CompanyName: mcnSign.CompanyName,
SignUpID: permissionApply.ID,
Permission: strings.Join(getUpPermitString(maskedPermission), "、"),
}
s.sendMsg(&msg)
}
return
}
//McnPermitApplyGetBind get permit apply bind
func (s *Service) McnPermitApplyGetBind(c context.Context, arg *mcnmodel.McnUpGetBindReq) (res *mcnmodel.McnGetBindReply, err error) {
res, err = s.mcndao.GetUpPermissionBindInfo(arg)
if err != nil {
log.Error("fail to get bind info, err=%s", err)
return
}
accInfo, err := global.GetInfo(c, int64(res.McnMid))
if err == nil && accInfo != nil {
res.McnName = accInfo.Name
}
res.Finish()
res.UpAuthLink = model.BuildBfsURL(res.UpAuthLink, s.c.BFS.Key, s.c.BFS.Secret, s.c.BFS.Bucket, model.BfsEasyPath)
return
}
//McnUpPermitApplyConfirm permit apply confirm
func (s *Service) McnUpPermitApplyConfirm(c context.Context, arg *mcnmodel.McnUpConfirmReq) (res *mcnmodel.CommonReply, err error) {
// 1.查询当前up状态
upList, err := s.mcndao.GetUpPermissionApply("*", "id=? and up_mid=? and state=?", arg.BindID, arg.UpMid, adminmodel.MCNUPPermissionStateNoAuthorize)
if err != nil {
log.Error("get up bind fail, err=%s", err)
err = ecode.ServerErr
return
}
// 不存在
if len(upList) == 0 {
log.Info("bind id not found, id=%d", arg.BindID)
err = ecode.MCNNotAllowed
return
}
var upBind = upList[0]
// 查询mcn状态
mcnSign, err := s.getMcnWithState(c, upBind.McnMid, model.MCNSignStateOnSign)
if err != nil {
if err != ecode.MCNStateInvalid {
log.Error("error get state, err=%s", err)
}
return
}
if mcnSign.ID != upBind.SignID {
log.Error("bind id not same with mcn signid, bind id=%d, signid=%d", upBind.ID, upBind.SignID)
err = ecode.MCNUpBindInvalid
return
}
var state = adminmodel.MCNUPPermissionStateOnRefuse
if arg.Choice {
state = adminmodel.MCNUPPermissionStateReview
}
// 更新状态
err = s.mcndao.UpPermissionConfirm(arg, state)
if err != nil {
log.Error("fail to update up bind, bind id=%d, upmid=%d, err=%s", arg.BindID, arg.UpMid, err)
err = ecode.ServerErr
return
}
// 同意
if arg.Choice {
// do nothing.
} else {
var upName = global.GetName(c, arg.UpMid)
var msg = adminmodel.ArgMsg{
MSGType: adminmodel.McnUpNotAgreeChangePermit,
MIDs: []int64{mcnSign.McnMid},
UpMid: arg.UpMid,
UpName: upName,
}
s.sendMsg(&msg)
}
log.Info("up permission bind change, bind id=%d, upmid=%d, isaccept=%t", arg.BindID, arg.UpMid, arg.Choice)
return
}
//McnPublicationPriceChange .
func (s *Service) McnPublicationPriceChange(c context.Context, arg *mcnmodel.McnPublicationPriceChangeReq) (res *mcnmodel.McnPublicationPriceChangeReply, err error) {
mcnSign, err := s.getMcnWithState(c, arg.McnMid, model.MCNSignStateOnSign)
if err != nil {
if err != ecode.NothingFound {
log.Error("error get state, err=%s", err)
}
return
}
// 1.检查上次刊例价修改时间,如果时间内不能修改返回错误
publicationPriceCache, e := s.mcndao.CachePublicationPrice(c, mcnSign.ID, arg.UpMid)
if e != nil {
log.Warn("get modify time from cache fail, arg=%+v, err=%v", arg, err)
}
if publicationPriceCache == nil {
// 初始化为0值
publicationPriceCache = &mcnmodel.PublicationPriceCache{}
}
var lastModifyTime = publicationPriceCache.ModifyTime // 从缓存中获取
var now = time.Now()
if now.Before(lastModifyTime.Add(time.Duration(conf.Conf.Other.PublicationPriceChangeLimit))) {
log.Error("publication change fail, last modify time=%s, timelimit=%+v, arg=%+v", lastModifyTime, conf.Conf.Other.PublicationPriceChangeLimit, arg)
err = ecode.MCNPublicationFailTimeLimit
return
}
// 2.检查Up主关系只有“已签约”,“待开启”状态的Up主可以修改
upList, err := s.mcndao.GetUpBind("up_mid=? and sign_id=? and state in (?)", arg.UpMid, mcnSign.ID, mcndao.UpSignedStates)
if err != nil {
log.Error("get up bind fail, err=%v", err)
err = ecode.ServerErr
return
}
if len(upList) == 0 {
log.Error("up is not in signed state with mcn, up_mid=%d and sign_id=%d , need state in (%v)", arg.UpMid, mcnSign.ID, mcndao.UpSignedStates)
err = ecode.MCNUpSignStateInvalid
return
}
var up = upList[0]
// 3.修改刊例价,更新上次修改时间
var db = s.mcndao.GetMcnDB()
err = db.Table(mcnmodel.TableNameMcnUp).Where("id=?", up.ID).Update("publication_price", arg.Price).Error
if err != nil {
log.Error("change publication price fail, err=%v, arg=%+v", err, arg)
return
}
publicationPriceCache.ModifyTime = now
e = s.mcndao.AddCachePublicationPrice(c, mcnSign.ID, publicationPriceCache, arg.UpMid)
if e != nil {
log.Warn("fail to add cache, arg=%+v, err=%v", arg, e)
}
return
}

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