Create & Init Project...

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

View File

@@ -0,0 +1,97 @@
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/interface/main/creative/api:all-srcs",
"//app/interface/main/creative/cmd:all-srcs",
"//app/interface/main/creative/conf:all-srcs",
"//app/interface/main/creative/dao/academy:all-srcs",
"//app/interface/main/creative/dao/account:all-srcs",
"//app/interface/main/creative/dao/activity:all-srcs",
"//app/interface/main/creative/dao/app:all-srcs",
"//app/interface/main/creative/dao/appeal:all-srcs",
"//app/interface/main/creative/dao/archive:all-srcs",
"//app/interface/main/creative/dao/article:all-srcs",
"//app/interface/main/creative/dao/assist:all-srcs",
"//app/interface/main/creative/dao/bfs:all-srcs",
"//app/interface/main/creative/dao/coin:all-srcs",
"//app/interface/main/creative/dao/creative:all-srcs",
"//app/interface/main/creative/dao/danmu:all-srcs",
"//app/interface/main/creative/dao/data:all-srcs",
"//app/interface/main/creative/dao/drawimg:all-srcs",
"//app/interface/main/creative/dao/elec:all-srcs",
"//app/interface/main/creative/dao/faq:all-srcs",
"//app/interface/main/creative/dao/feedback:all-srcs",
"//app/interface/main/creative/dao/game:all-srcs",
"//app/interface/main/creative/dao/geetest:all-srcs",
"//app/interface/main/creative/dao/growup:all-srcs",
"//app/interface/main/creative/dao/lottery:all-srcs",
"//app/interface/main/creative/dao/material:all-srcs",
"//app/interface/main/creative/dao/medal:all-srcs",
"//app/interface/main/creative/dao/message:all-srcs",
"//app/interface/main/creative/dao/monitor:all-srcs",
"//app/interface/main/creative/dao/music:all-srcs",
"//app/interface/main/creative/dao/newcomer:all-srcs",
"//app/interface/main/creative/dao/order:all-srcs",
"//app/interface/main/creative/dao/pay:all-srcs",
"//app/interface/main/creative/dao/porder:all-srcs",
"//app/interface/main/creative/dao/reply:all-srcs",
"//app/interface/main/creative/dao/resource:all-srcs",
"//app/interface/main/creative/dao/search:all-srcs",
"//app/interface/main/creative/dao/subtitle:all-srcs",
"//app/interface/main/creative/dao/tag:all-srcs",
"//app/interface/main/creative/dao/template:all-srcs",
"//app/interface/main/creative/dao/tool:all-srcs",
"//app/interface/main/creative/dao/up:all-srcs",
"//app/interface/main/creative/dao/watermark:all-srcs",
"//app/interface/main/creative/dao/weeklyhonor:all-srcs",
"//app/interface/main/creative/dao/whitelist:all-srcs",
"//app/interface/main/creative/http:all-srcs",
"//app/interface/main/creative/model/academy:all-srcs",
"//app/interface/main/creative/model/account:all-srcs",
"//app/interface/main/creative/model/activity:all-srcs",
"//app/interface/main/creative/model/app:all-srcs",
"//app/interface/main/creative/model/appeal:all-srcs",
"//app/interface/main/creative/model/archive:all-srcs",
"//app/interface/main/creative/model/article:all-srcs",
"//app/interface/main/creative/model/assist:all-srcs",
"//app/interface/main/creative/model/danmu:all-srcs",
"//app/interface/main/creative/model/data:all-srcs",
"//app/interface/main/creative/model/elec:all-srcs",
"//app/interface/main/creative/model/faq:all-srcs",
"//app/interface/main/creative/model/feedback:all-srcs",
"//app/interface/main/creative/model/game:all-srcs",
"//app/interface/main/creative/model/geetest:all-srcs",
"//app/interface/main/creative/model/growup:all-srcs",
"//app/interface/main/creative/model/lottery:all-srcs",
"//app/interface/main/creative/model/medal:all-srcs",
"//app/interface/main/creative/model/message:all-srcs",
"//app/interface/main/creative/model/monitor:all-srcs",
"//app/interface/main/creative/model/music:all-srcs",
"//app/interface/main/creative/model/newcomer:all-srcs",
"//app/interface/main/creative/model/operation:all-srcs",
"//app/interface/main/creative/model/order:all-srcs",
"//app/interface/main/creative/model/porder:all-srcs",
"//app/interface/main/creative/model/relation:all-srcs",
"//app/interface/main/creative/model/reply:all-srcs",
"//app/interface/main/creative/model/resource:all-srcs",
"//app/interface/main/creative/model/search:all-srcs",
"//app/interface/main/creative/model/tag:all-srcs",
"//app/interface/main/creative/model/template:all-srcs",
"//app/interface/main/creative/model/up:all-srcs",
"//app/interface/main/creative/model/version:all-srcs",
"//app/interface/main/creative/model/watermark:all-srcs",
"//app/interface/main/creative/model/weeklyhonor:all-srcs",
"//app/interface/main/creative/server/grpc:all-srcs",
"//app/interface/main/creative/service:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
# Owner
shencen
wangzhe01
# Author
shencen
shaojiatong
fengpengfei
# Reviewer
shencen
shaojiatong
fengpengfei

View File

@@ -0,0 +1,17 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- fengpengfei
- shaojiatong
- shencen
- wangzhe01
labels:
- interface
- interface/main/creative
- main
options:
no_parent_owners: true
reviewers:
- fengpengfei
- shaojiatong
- shencen

View File

@@ -0,0 +1,13 @@
#### creative-interface
##### 项目简介
> 1.creative-interface, 创作中心相关
##### 编译环境
> 请只用golang v1.7.x以上版本编译执行。
##### 依赖包
> 1.公共包go-common
##### 特别说明
> 1.model目录可能会被其他项目引用请谨慎请改并通知各方。

View File

@@ -0,0 +1,74 @@
load(
"@io_bazel_rules_go//proto:def.bzl",
"go_proto_library",
)
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
proto_library(
name = "v1_proto",
srcs = ["api.proto"],
tags = ["automanaged"],
deps = ["@gogo_special_proto//github.com/gogo/protobuf/gogoproto"],
)
go_proto_library(
name = "v1_go_proto",
compilers = ["@io_bazel_rules_go//proto:gogofast_grpc"],
importpath = "go-common/app/interface/main/creative/api",
proto = ":v1_proto",
tags = ["automanaged"],
deps = ["@com_github_gogo_protobuf//gogoproto:go_default_library"],
)
go_test(
name = "go_default_test",
srcs = ["client_test.go"],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//library/log:go_default_library",
"//library/naming/discovery:go_default_library",
"//library/net/netutil/breaker:go_default_library",
"//library/net/rpc/warden:go_default_library",
"//library/net/rpc/warden/resolver:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["client.go"],
embed = [":v1_go_proto"],
importpath = "go-common/app/interface/main/creative/api",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/net/rpc/warden:go_default_library",
"@com_github_gogo_protobuf//gogoproto:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_x_net//context:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,42 @@
syntax = "proto3";
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
package main.archive.creative;
option go_package = "v1";
// Creative grpc
service Creative {
// FlowJudge 查询flow情况
rpc FlowJudge(FlowRequest) returns(FlowResponse);
// Sends a greeting
rpc CheckTaskState (TaskRequest) returns (TaskReply) {}
// Ping Service
rpc Ping(Empty) returns(Empty);
// Close Service
rpc Close(Empty) returns(Empty);
}
message FlowRequest {
int64 gid = 1;
int64 business = 2;
repeated int64 oids = 3;
}
message FlowResponse {
repeated int64 oids = 1;
}
// The request message containing the user's name.
message TaskRequest {
int64 mid = 1;
int64 task_id = 2;
}
// The response message containing the greetings
message TaskReply {
bool finish_state = 1;
}
message Empty{}

View File

@@ -0,0 +1,24 @@
package v1
import (
"context"
"fmt"
"go-common/library/net/rpc/warden"
"google.golang.org/grpc"
)
// DiscoveryAppID .
const DiscoveryAppID = "main.archive.creative"
// NewClient new grpc client
func NewClient(cfg *warden.ClientConfig, opts ...grpc.DialOption) (CreativeClient, error) {
client := warden.NewClient(cfg, opts...)
// cc, err := client.Dial(context.Background(), "127.0.0.1:9000")
cc, err := client.Dial(context.Background(), fmt.Sprintf("discovery://default/%s", DiscoveryAppID))
if err != nil {
return nil, err
}
return NewCreativeClient(cc), nil
}

View File

@@ -0,0 +1,66 @@
package v1
import (
"context"
"testing"
"time"
"go-common/library/log"
"go-common/library/naming/discovery"
"go-common/library/net/netutil/breaker"
"go-common/library/net/rpc/warden"
"go-common/library/net/rpc/warden/resolver"
xtime "go-common/library/time"
"github.com/smartystreets/goconvey/convey"
)
func testInit() CreativeClient {
log.Init(nil)
conf := &warden.ClientConfig{
Dial: xtime.Duration(time.Second * 10),
Timeout: xtime.Duration(time.Second * 10),
Breaker: &breaker.Config{
Window: xtime.Duration(3 * time.Second),
Sleep: xtime.Duration(3 * time.Second),
Bucket: 10,
Ratio: 0.3,
Request: 20,
},
}
wc := warden.NewClient(conf)
resolver.Register(discovery.New(nil))
conn, err := wc.Dial(context.TODO(), "127.0.0.1:9000")
if err != nil {
panic(err)
}
return NewCreativeClient(conn)
}
//var client CreativeClient
//
//func init() {
// var err error
// client, err = NewClient(nil)
// if err != nil {
// panic(err)
// }
//}
func TestFlowJudge(t *testing.T) {
client := testInit()
convey.Convey("TestFlowJudge", t, func(ctx convey.C) {
ctx.Convey("When everything is correct", func(ctx convey.C) {
oids, err := client.FlowJudge(context.TODO(), &FlowRequest{Business: int64(4), Gid: int64(24), Oids: []int64{22, 333, 10110208, 10110119}})
ctx.So(err, convey.ShouldBeNil)
ctx.Printf("%+v\n", oids.Oids)
})
//ctx.Convey("When error", func(ctx convey.C) {
//})
})
}
func TestCheckTaskState(t *testing.T) {
client := testInit()
client.CheckTaskState(context.TODO(), &TaskRequest{Mid: int64(1), TaskId: int64(1)})
}

View File

@@ -0,0 +1,44 @@
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 = ["creative.toml"],
importpath = "go-common/app/interface/main/creative/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/http:go_default_library",
"//library/ecode/tip:go_default_library",
"//library/log:go_default_library",
"//library/net/trace:go_default_library",
"//library/queue/databus/report: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,90 @@
{
"course":{
"id":0,
"rank":1,
"shoot":{
"key":[1],
"val":[1,2,3]
},
"scene":{
"key":[1],
"val":[1,2,3]
},
"edit":{
"key":[1],
"val":[1,2,3]
},
"mmd":{
"key":[1],
"val":[1,2,3]
},
"sing":{
"key":[1],
"val":[1,2,3]
},
"bang":{
"key":[1],
"val":[1,2,3]
},
"other":{
"key":[1],
"val":[1]
}
},
"drawn":{
"id":22,
"rank":2,
"mobile_plan":{
"key":[1],
"val":[1,2,3]
},
"screen_plan":{
"key":[1,2],
"val":[1,2,3]
},
"mobile_camera":{
"key":[1,2],
"val":[1,2,3]
},
"record_plan":{
"key":[1,2],
"val":[1,2,3]
},
"other":{
"key":[23],
"val":[1,2,3]
}
},
"video":{
"id":11,
"rank":3,
"mobile_make":{
"key":[1],
"val":[1,2,3]
},
"audio_edit":{
"key":[1,2],
"val":[1,2,3]
},
"edit_compose":{
"key":[1,2],
"val":[1,2,3]
},
"mobile_image":{
"key":[1,2],
"val":[1,2,3]
},
"other":{
"key":[12,13],
"val":[1,2,3]
}
},
"person":{
"id":9,
"rank":4,
"other":{
"key":[4],
"val":[]
}
}
}

View File

@@ -0,0 +1,21 @@
{
"0": "t开放浏览",
"-1": "t复核中",
"-2": "t已退回",
"-3": "t已锁定",
"-4": "t已锁定",
"-5": "t已锁定",
"-6": "t修改内容待审核…",
"-7": "t转码完成等待审核…",
"-8": "t转码完成等待审核…",
"-9": "t转码中",
"-10": "t复核中",
"-11": "t视频源待修",
"-12": "t上传失败",
"-13": "t复核中",
"-14": "t已退回",
"-15": "t分发中",
"-16": "t转码失败",
"-30": "t审核中",
"-40": "t通过审核等待发布"
}

View File

@@ -0,0 +1,446 @@
# This is a TOML document. Boom.
TplMaxCnt = 5
LimitCntFans = 1000
AppealTag = 91
HonorDegradeSwitch = false
[academy]
OfficialID = 1
EditorChoiceID = 6
NewbCourseID = 1
[host]
search = "http://172.18.33.135:12999"
api = "http://uat-api.bilibili.co"
data="http://data.bilibili.co"
member = "http://uat-member.bilibili.com"
act = "http://act.bilibili.com"
activity = "http://uat-www.bilibili.com"
videoup = "http://uat-archive.api.bilibili.co"
passport = "http://uat-passport.bilibili.com"
tag = "http://dl-test.bilibili.com"
upMng = "http://uat-cm.bilibili.co"
elec = "http://uat-elec.bilibili.com"
geetest = "http://api.geetest.com"
account = "http://uat-account.bilibili.co"
platform = "http://uat-api.bilibili.co"
live = "http://api.live.bilibili.co"
matsuri = "http://uat-matsuri.bilibili.co"
growup = "http://uat-up-profit.bilibili.co"
message = "http://uat-message.bilibili.com"
mainsearch = "http://uat-manager.bilibili.co"
dynamic = "http://uat-api.vc.bilibili.co"
mall = "http://uat-mall.bilibili.co"
bpay = "http://uat-pay.bilibili.co"
pendant= "http://uat-api.bilibili.co"
bigmember = "http://uat-api.bilibili.co"
profit = "http://up-profit.bilibili.co"
notify = "http://message.bilibili.co"
chaodian = "http://chaodian.bilibili.co"
[UgcPay]
ProtocolID = "e28a5cb06a594ae79961485d3112f0e9"
AllowDeleteDays = 30
AllowEditDays = 60
[H5Page]
FAQVideoEditor = "https://member.bilibili.com/studio/videoup-faq/index.html"
HotAct = "https://www.bilibili.com/blackboard/x/activity-tougao-h5/all"
CreativeCollege = "https://member.bilibili.com/college"
Draft = "https://member.bilibili.com/creative/app/article_drafts"
Passport = "https://passport.bilibili.com/mobile/index.html"
Mission = "https://member.bilibili.com/studio/gabriel/mission-system"
Cooperate = "https://member.bilibili.com/studio/annyroal/bgm-detail"
[AppIcon]
[AppIcon.CameraInput]
name = "手摄拍摄入口红点"
state = true
url = ""
[AppIcon.CameraCoo]
name = "合拍入口红点"
state = true
url = "http://uat-www.bilibili.com/blackboard/x/activity-tougao-h5/cowork"
[Coefficient]
ActHeat = 100.0
[log]
dir = "/data/log/creative/"
stdout = false
[xlog.syslog]
project = "creative"
chanSize = 10240
[app]
key = "b8f239ca38a53308"
secret = "5460ef72fe13c10dfb53442b9111427e"
[geetest]
captchaId = "6c49e5671cfccdfd8ddc5b2808e2711d"
privateKey = "1d4790b20490207866b0be53b23cc692"
mcaptchaId = "422a6f52459f01953ca806f4f2fb68cd"
mprivateKey = "51c53ec7fc53d72b312572d2952fb35d"
[httpClient]
[httpClient.UpMng]
key = "creative"
secret = "8c34f29cb765f4f353d785f63156e26e"
dial = "1s"
timeout = "3s"
keepAlive = "60s"
timer = 1000
[httpClient.UpMng.breaker]
window = "10s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[httpClient.normal]
key = "b8f239ca38a53308"
secret = "5460ef72fe13c10dfb53442b9111427e"
dial = "500ms"
timeout = "1s"
keepAlive = "60s"
timer = 10
[httpClient.normal.breaker]
window = "10s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[httpClient.slow]
key = "b8f239ca38a53308"
secret = "5460ef72fe13c10dfb53442b9111427e"
dial = "1s"
timeout = "10s"
keepAlive = "60s"
timer = 10
[httpClient.slow.breaker]
window = "10s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[httpClient.fast]
key = "b8f239ca38a53308"
secret = "5460ef72fe13c10dfb53442b9111427e"
dial = "50ms"
timeout = "100ms"
keepAlive = "60s"
timer = 128
[httpClient.fast.breaker]
window = "10s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[httpClient.chaodian]
key = "chaodian_20190117tangseng"
secret = "chaodian_20190117tangseng"
dial = "1s"
timeout = "3s"
keepAlive = "60s"
timer = 1000
[httpClient.chaodian.breaker]
window = "10s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[bm]
[bm.outer]
addr = "0.0.0.0:6341"
maxListen = 1000
timeout = "2s"
[db]
[db.archive]
name = "[archive]tcp@172.16.33.205:3308"
dsn = "test:test@tcp(172.16.33.205:3308)/bilibili_archive?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8"
active = 5
idle = 5
idleTimeout ="4h"
queryTimeout = "5s"
execTimeout = "5s"
tranTimeout = "5s"
[db.archive.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[db.oper]
name = "[archive]tcp@172.16.33.205:3308"
dsn = "test:test@tcp(172.16.33.205:3308)/bilibili_operation?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 5
idleTimeout ="4h"
queryTimeout = "5s"
execTimeout = "5s"
tranTimeout = "5s"
[db.oper.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[db.creative]
name = "[archive]tcp@172.16.33.205:3308"
dsn = "test:test@tcp(172.16.33.205:3308)/bilibili_creative?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 5
idleTimeout ="4h"
queryTimeout = "5s"
execTimeout = "5s"
tranTimeout = "5s"
[db.creative.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[db.manager]
name = "[archive]tcp@172.16.33.205:3308"
dsn = "test:test@tcp(172.16.33.205:3308)/bilibili_manager?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 5
idleTimeout ="4h"
queryTimeout = "5s"
execTimeout = "5s"
tranTimeout = "5s"
[db.manager.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[whitelist]
dataMids = [207526951,15555180, 191407, 18352698, 27515256, 31168827,644370]
arcMids = [15555180, 191407, 18352698, 27515256, 31168827,644370, 27515317]
forbidVideoupMids = [91513044]
[memcache]
[memcache.archive]
name = "creative/archive"
proto = "tcp"
addr = "172.16.33.54:11213"
active = 10
idle = 5
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
tplExpire = "60s"
[memcache.data]
name = "creative/archive"
proto = "tcp"
addr = "172.16.33.54:11213"
idle = 5
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
dataExpire = "60s"
indexExpire = "1h"
centerExpire = "1h"
[memcache.article]
name = "creative/article"
proto = "tcp"
addr = "172.16.33.54:11213"
idle = 5
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
submitExpire = "2m"
[memcache.honor]
name = "creative/article"
proto = "tcp"
addr = "172.16.33.54:11213"
idle = 5
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
honorExpire = "200h"
clickExpire = "1m"
[hbase]
master = ""
meta = ""
dialTimeout = "1s"
readTimeout = "150ms"
readsTimeout = "600ms"
writeTimeout = "200ms"
writesTimeout = "600ms"
[hbase.zookeeper]
root = ""
addrs = ["10.23.58.154:2181","10.23.58.141:2181","10.23.58.20:2181"]
timeout = "30s"
[hbaseOld]
master = ""
meta = ""
dialTimeout = "1s"
readTimeout = "150ms"
readsTimeout = "600ms"
writeTimeout = "200ms"
writesTimeout = "600ms"
[hbaseOld.zookeeper]
root = ""
addrs = ["10.23.58.154:2181","10.23.58.141:2181","10.23.58.20:2181"]
timeout = "30s"
[bfs]
timeout="5s"
maxFileSize=5242880
bucket="article"
url="http://bfs.bilibili.co/bfs/article/"
method="PUT"
key="4d08035f0b341509"
secret="ed4161d96c7612b670f75fa4be4e15"
[userInfoSub]
key = "0QHEzXlXE9Ijewj8V4zu"
secret = "0QHEzXlXE9Ijewj8V4zv"
group = "PassportPurgeCache-UserInfo-S"
topic = "PassportPurgeCache-T"
action = "sub"
offset = "old"
buffer = 128
name = "creative/userInfo"
proto = "tcp"
addr = "172.16.33.158:6205"
idle = 100
active = 100
dialTimeout = "1s"
readTimeout = "60s"
writeTimeout = "1s"
idleTimeout = "10s"
[watermark]
unamemark = "/data/watermark/mark.png"
uidmark = "/data/watermark/uid_mark.png"
saveimg = "/data/watermark/"
fontfile = "/data/watermark/SourceHanSansSC-Bold.ttf"
fontsize = 32
consume = true
[redis]
[redis.cover]
name = "creative"
proto = "tcp"
addr = "172.18.33.61:6820"
active = 100
idle = 2
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
[RouterAntispam]
on=true
second=3
n=100
hour=12
m=1000
[RouterAntispam.redis]
name = "creative"
proto = "tcp"
addr = "172.16.33.54:6379"
idle = 10
active = 100
dialTimeout = "500ms"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
expire = "10m"
[DmAntispam]
on=true
second=10
n=20
hour=12
m=1000
[DmAntispam.redis]
name = "creative"
proto = "tcp"
addr = "172.18.21.251:36385"
active = 1024
idle = 128
dialTimeout = "30ms"
readTimeout = "50ms"
writeTimeout = "50ms"
idleTimeout = "80s"
expire = "32h"
[Growup]
LimitFanCnt = 3
LimitTotalClick = 500000
[game]
OpenHost = "http://line1-game-open-api.biligame.net"
[game.app]
key = "EeOpM531WqQnBvu4"
secret = "gHtKtXTHZJDqGP1tg9ORFs0YWV3kW12V"
[rpcServer2]
discoverOff = true
token = "123456"
[[rpcServer2.servers]]
proto = "tcp"
addr = "0.0.0.0:6079"
weight = 10
group = "test"
[rpcServer2.zookeeper]
root = "/microservice/creative/"
addrs = ["172.18.33.50:2199","172.18.33.51:2199","172.18.33.52:2199"]
timeout = "1s"
[taskPub]
key = "4c76cbb7a985ac90"
secret = "43bb22ce34a6b13e7814f09cb8116522"
group = "CreativeTask-MainArchive-P"
topic = "CreativeTask-T"
action = "pub"
offset = "old"
buffer = 128
name = "creative/pub/task"
proto = "tcp"
addr = "172.18.33.50:6205"
idle = 100
active = 100
dialTimeout = "1s"
readTimeout = "60s"
writeTimeout = "1s"
idleTimeout = "10s"
[taskCondition]
fans = 100
receiveMsg = "领取成功"
receiveMsgPendant = "奖励会在12月1日起陆续发送至你的个人中心—我的头像中"
whiteSwitch = false
appIndexSwitch = false
[staffConf]
isGray = true
[[staffConf.typeList]]
typeId = 0
maxStaff = 6
[[staffConf.typeList]]
typeId = 22
maxStaff = 10
[CoinClient]
Timeout = "60s"

View File

@@ -0,0 +1,51 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"time"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/http"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
"go-common/library/net/trace"
"go-common/library/queue/databus/report"
)
func main() {
flag.Parse()
if err := conf.Init(); err != nil {
log.Error("conf.Init() error(%v)", err)
panic(err)
}
log.Init(conf.Conf.Log)
defer log.Close()
trace.Init(conf.Conf.Tracer)
defer trace.Close()
report.InitUser(nil)
log.Info("creative-center start")
// service init
ecode.Init(conf.Conf.Ecode)
http.Init(conf.Conf)
// signal handler
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("creative-center get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGSTOP, syscall.SIGINT:
time.Sleep(time.Second * 2)
http.Close()
log.Info("creative-center exit")
return
case syscall.SIGHUP:
// TODO reload
default:
return
}
}
}

View File

@@ -0,0 +1,6 @@
#!/bin/bash
command -v goconvey >/dev/null 2>&1 || { echo >&2 "required goconvey but it's not installed."; echo "Aborting."; echo "Please run commond: go get github.com/smartystreets/goconvey"; exit 1; }
cd ../creative
goconvey -excludedDirs "vendor,node_modules,rpc" -packages 1

View File

@@ -0,0 +1,47 @@
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/creative/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/model/academy:go_default_library",
"//app/interface/main/creative/model/app:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/cache/redis:go_default_library",
"//library/conf:go_default_library",
"//library/database/hbase.v2:go_default_library",
"//library/database/sql: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:go_default_library",
"//library/net/rpc/warden:go_default_library",
"//library/net/trace:go_default_library",
"//library/queue/databus: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,411 @@
package conf
import (
"encoding/json"
"errors"
"flag"
"strconv"
"go-common/app/interface/main/creative/model/academy"
appMdl "go-common/app/interface/main/creative/model/app"
"go-common/library/cache/memcache"
"go-common/library/cache/redis"
"go-common/library/conf"
"go-common/library/database/sql"
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"
"go-common/library/net/trace"
"go-common/library/queue/databus"
"go-common/library/time"
"go-common/library/net/rpc/warden"
"github.com/BurntSushi/toml"
"go-common/library/database/hbase.v2"
)
// Conf info.
var (
ConfPath string
Conf = &Config{}
client *conf.Client
)
// Config struct.
type Config struct {
// db
DB *DB
// base
// ecode
Ecode *ecode.Config
// log
Log *log.Config
// app
App *bm.App
// HTTPClient
HTTPClient *HTTPClient
// BM
BM *HTTPServers
// rpc client2
ArchiveRPC *rpc.ClientConfig
ArticleRPC *rpc.ClientConfig
ResourceRPC *rpc.ClientConfig
RelationRPC *rpc.ClientConfig
UPRPC *rpc.ClientConfig
SubRPC *rpc.ClientConfig
// mc
Memcache *Memcache
// redis
Redis *Redis
// tracer
Tracer *trace.Config
//nhbase
HBase *HBaseConfig
HBaseOld *HBaseConfig
// white list
WhiteAccessKey string
WhiteMid int64
// host
Host *Host
H5Page *H5Page
// geetest
Geetest *Geetest
// whitelist
Whitelist *Whitelist
// ArchStatus
ArchStatus map[string]string
RouterAntispam *antispam.Config
DmAntispam *antispam.Config
// BFS
BFS *BFS
AppealTag int64
// databus sub
UserInfoSub *databus.Config
TaskPub *databus.Config
// WaterMark
WaterMark *WaterMark
Game *Game
Growup *Growup
StatCacheOn bool
AppIcon *AppIcon
UgcPay *UgcPay
//academy
Coefficient *Coefficient
// academy
Academy *Academy
AcaRecommend *AcaRecommend
//ManagerReport 行为日志平台
ManagerReport *databus.Config
// rpc server
WardenServer *warden.ServerConfig
WardenClient *warden.ClientConfig
CoinClient *warden.ClientConfig
AccClient *warden.ClientConfig
UpClient *warden.ClientConfig
// task condition
TaskCondition *TaskCondition
//联合投稿配置
StaffConf *StaffConf
// honor weekly degrade switch
HonorDegradeSwitch bool
}
// TaskCondition task condition
type TaskCondition struct {
Fans int64
ReceiveMsg string
ReceiveMsgPendant string
WhiteSwitch bool
AppIndexSwitch bool
}
// StaffConf 联合投稿配置
type StaffConf struct {
IsGray bool `json:"is_gray"`
TypeList []*StaffTypeConf `json:"typelist"`
}
// StaffTypeConf 联合投稿的分区配置
type StaffTypeConf struct {
TypeID int16 `json:"typeid"`
MaxStaff int `json:"max_staff"`
}
// UgcPay str
type UgcPay struct {
ProtocolID string
AllowDeleteDays int
AllowEditDays int
}
// Coefficient str
type Coefficient struct {
ActHeat float64
}
// AppIcon str
type AppIcon struct {
CameraInput *appMdl.Icon `json:"camera_input"`
CameraCoo *appMdl.Icon `json:"camera_coo"`
}
// Game str Conf
type Game struct {
OpenHost string
App *bm.App
}
// Growup str
type Growup struct {
LimitFanCnt int64 // LimitFanCnt 一万粉
LimitTotalClick int64 // LimitTotalClick 五十万点击量
}
// DB conf.
type DB struct {
// archive db
Creative *sql.Config
Archive *sql.Config
}
// Thrift conf.
type Thrift struct {
Addr string
Idle int
DialTimeout, ReadTimeout time.Duration
}
// HTTPServers Http Servers
type HTTPServers struct {
Outer *bm.ServerConfig
Local *bm.ServerConfig
}
// HTTPClient conf.
type HTTPClient struct {
Normal *bm.ClientConfig
Slow *bm.ClientConfig
UpMng *bm.ClientConfig
Fast *bm.ClientConfig
Chaodian *bm.ClientConfig
}
// Memcache conf.
type Memcache struct {
Data struct {
*memcache.Config
DataExpire time.Duration
IndexExpire time.Duration
}
Archive struct {
*memcache.Config
TplExpire time.Duration
}
Honor struct {
*memcache.Config
HonorExpire time.Duration
ClickExpire time.Duration
}
}
// Redis conf.
type Redis struct {
Antispam *struct {
*redis.Config
Expire time.Duration
}
Cover *struct {
*redis.Config
Expire time.Duration
}
}
// Host conf.
type Host struct {
Passport string
Archive string
Search string
API string
Data string
Member string
Act string
Activity string
Videoup string
Tag string
Geetest string
Account string
UpMng string
Elec string
Live string
Monitor string
Coverrec string
Growup string
Matsuri string
ArcTip string
Message string
HelpAPI string
MainSearch string
Dynamic string
Mall string //会员购
BPay string //B币券
Pendant string //挂件
BigMember string //大会员
Profit string //激励计划
Notify string //消息通知
Chaodian string //超电
}
// H5Page conf.
type H5Page struct {
FAQVideoEditor string
CreativeCollege string
HotAct string
Draft string
Passport string
Mission string
Cooperate string
}
// Geetest geetest id & key
type Geetest struct {
CaptchaID string
MCaptchaID string
PrivateKEY string
MPrivateKEY string
}
// Whitelist str
type Whitelist struct {
DataMids []int64
ArcMids []int64
ForbidVideoupMids []int64
}
// BFS bfs config
type BFS struct {
Timeout time.Duration
MaxFileSize int
Bucket string
URL string
Method string
Key string
Secret string
}
// WaterMark config
type WaterMark struct {
UnameMark string
UIDMark string
SaveImg string
FontFile string
FontSize int
Consume bool
}
// HBaseConfig for new hbase client.
type HBaseConfig struct {
*hbase.Config
WriteTimeout time.Duration
ReadTimeout time.Duration
}
//Academy for academy h5 conf
type Academy struct {
academy.H5Conf
}
//AcaRecommend for h5 rec conf
type AcaRecommend struct {
academy.Recommend
}
func init() {
flag.StringVar(&ConfPath, "conf", "", "default config path")
}
// Init conf.
func Init() (err error) {
if ConfPath != "" {
return local()
}
return remote()
}
func local() (err error) {
_, err = toml.DecodeFile(ConfPath, &Conf)
//bs, err := ioutil.ReadFile("academy.json")
//if err != nil {
// return err
//}
//if err = json.Unmarshal([]byte(bs), &Conf.AcaRecommend); err != nil {
// return errors.New("could not decode json config")
//}
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 (
tomlStr string
jsonStr, acaStr string
ok bool
tmpConf *Config
archStatus map[string]string
)
if tomlStr, ok = client.Toml2(); !ok {
return errors.New("load config center error")
}
if _, err = toml.Decode(tomlStr, &tmpConf); err != nil {
return errors.New("could not decode toml config")
}
if jsonStr, ok = client.Value("archStatus.json"); !ok {
return errors.New("load config center error")
}
if err = json.Unmarshal([]byte(jsonStr), &archStatus); err != nil {
return errors.New("could not decode json config")
}
if acaStr, ok = client.Value("academy.json"); !ok {
return errors.New("load config center error")
}
if err = json.Unmarshal([]byte(acaStr), &tmpConf.AcaRecommend); err != nil {
return errors.New("could not decode json config")
}
tmpConf.ArchStatus = archStatus
*Conf = *tmpConf
return
}
// StatDesc define
func (c *Config) StatDesc(state int) (desc string) {
statusStr := strconv.Itoa(state)
if v, ok := c.ArchStatus[statusStr]; !ok {
desc = statusStr
} else {
desc = v
}
return
}

View File

@@ -0,0 +1,66 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"archive_test.go",
"dao_test.go",
"feedback_test.go",
"search_test.go",
"skill_test.go",
"tag_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/academy:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"archive.go",
"dao.go",
"feedback.go",
"search.go",
"skill.go",
"tag.go",
],
importpath = "go-common/app/interface/main/creative/dao/academy",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/dao/tool:go_default_library",
"//app/interface/main/creative/model/academy:go_default_library",
"//library/database/elastic:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/xstr:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,135 @@
package academy
import (
"context"
"fmt"
"database/sql"
sqlx "go-common/library/database/sql"
"go-common/library/xstr"
"go-common/app/interface/main/creative/dao/tool"
"go-common/app/interface/main/creative/model/academy"
"go-common/library/log"
)
const (
// select
_getArcByOIDAndBusSQL = "SELECT id, oid, business, state, ctime, mtime FROM academy_archive WHERE oid=? AND business=?"
_getSearByBusSQL = "SELECT a.oid, a.business, GROUP_CONCAT(t.tid SEPARATOR ',') AS tidstr FROM academy_archive AS a LEFT JOIN academy_archive_tag as t on t.oid = a.oid"
_getArcCountSQL = "SELECT count(DISTINCT a.oid) FROM (SELECT oid FROM academy_archive WHERE state=0 AND business=?) AS a LEFT JOIN academy_archive_tag as t on t.oid=a.oid"
_getTagByOidsSQL = "SELECT oid, tid FROM academy_archive_tag WHERE state=0 AND oid IN (%s)"
)
//Archive get one achive.
func (d *Dao) Archive(c context.Context, oid int64, bs int) (a *academy.Archive, err error) {
row := d.db.QueryRow(c, _getArcByOIDAndBusSQL, oid, bs)
a = &academy.Archive{}
if err = row.Scan(&a.ID, &a.OID, &a.Business, &a.State, &a.CTime, &a.MTime); err != nil {
if err == sql.ErrNoRows {
err = nil
return
}
log.Error("row.Scan error(%v)", err)
}
return
}
//ArchiveCount get all achive count.
func (d *Dao) ArchiveCount(c context.Context, tids []int64, bs int) (count int, err error) {
sqlStr := _getArcCountSQL
if len(tids) > 0 {
sqlStr += fmt.Sprintf(" WHERE t.tid IN (%s)", xstr.JoinInts(tids))
}
if err = d.db.QueryRow(c, sqlStr, bs).Scan(&count); err != nil {
if err == sql.ErrNoRows {
err = nil
return
}
log.Error("d.db.QueryRow error(%v)", err)
}
return
}
//SearchArchive get all oid & tid.
func (d *Dao) SearchArchive(c context.Context, tidsMap map[int][]int64, bs int) (res []*academy.Archive, err error) {
var (
rows *sqlx.Rows
tids []int64
)
for _, v := range tidsMap {
tids = append(tids, v...)
}
total := len(tids)
sqlStr := _getSearByBusSQL
if total > 0 {
sqlStr += fmt.Sprintf(" WHERE a.state=0 AND a.business=? AND t.tid IN (%s) GROUP BY a.oid ORDER BY a.mtime DESC", xstr.JoinInts(tids))
} else {
sqlStr += " WHERE a.state=0 AND a.business=? GROUP BY a.oid ORDER BY a.mtime DESC"
}
rows, err = d.db.Query(c, sqlStr, bs)
if err != nil {
log.Error("d.db.Query error(%v)", err)
return
}
defer rows.Close()
res = make([]*academy.Archive, 0)
origin := make([]*academy.Archive, 0)
var tidStr string
for rows.Next() {
a := &academy.Archive{}
if err = rows.Scan(&a.OID, &a.Business, &tidStr); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
a.TIDs, _ = xstr.SplitInts(tidStr)
origin = append(origin, a)
}
if total > 0 {
var cts, ots, clts, acts []int64
if v, ok := tidsMap[academy.Course]; ok {
cts = v
}
if v, ok := tidsMap[academy.Operation]; ok {
ots = v
}
if v, ok := tidsMap[academy.Classify]; ok {
clts = v
}
if v, ok := tidsMap[academy.ArticleClass]; ok {
acts = v
}
for _, v := range origin {
log.Info("search tag 课程级别(%+v)|运营标签(%+v)|分类标签(%+v)|专栏分类(%+v)|当前稿件标签(%+v)", cts, ots, clts, acts, v.TIDs)
if tool.ContainAtLeastOne(cts, v.TIDs) &&
tool.ContainAtLeastOne(ots, v.TIDs) &&
tool.ContainAtLeastOne(clts, v.TIDs) &&
tool.ContainAtLeastOne(acts, v.TIDs) {
res = append(res, v)
}
}
} else {
res = origin
}
return
}
//ArchiveTagsByOids get all tids by oids.
func (d *Dao) ArchiveTagsByOids(c context.Context, oids []int64) (res map[int64][]int64, err error) {
rows, err := d.db.Query(c, fmt.Sprintf(_getTagByOidsSQL, xstr.JoinInts(oids)))
if err != nil {
log.Error("d.db.Query error(%v)", err)
return
}
defer rows.Close()
res = make(map[int64][]int64)
for rows.Next() {
a := &academy.ArchiveTag{}
if err = rows.Scan(&a.OID, &a.TID); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
res[a.OID] = append(res[a.OID], a.TID)
}
return
}

View File

@@ -0,0 +1,75 @@
package academy
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestAcademyArchive(t *testing.T) {
convey.Convey("Archive", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
bs = int(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
a, err := d.Archive(c, oid, bs)
ctx.Convey("Then err should be nil.a should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(a, convey.ShouldNotBeNil)
})
})
})
}
func TestAcademyArchiveCount(t *testing.T) {
convey.Convey("ArchiveCount", t, func(ctx convey.C) {
var (
c = context.Background()
tids = []int64{}
bs = int(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
count, err := d.ArchiveCount(c, tids, bs)
ctx.Convey("Then err should be nil.count should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(count, convey.ShouldNotBeNil)
})
})
})
}
func TestAcademySearchArchive(t *testing.T) {
convey.Convey("SearchArchive", t, func(ctx convey.C) {
var (
c = context.Background()
tidsMap map[int][]int64
bs = int(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.SearchArchive(c, tidsMap, bs)
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 TestAcademyArchiveTagsByOids(t *testing.T) {
convey.Convey("ArchiveTagsByOids", t, func(ctx convey.C) {
var (
c = context.Background()
oids = []int64{1, 2}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.ArchiveTagsByOids(c, oids)
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,36 @@
package academy
import (
"context"
"go-common/app/interface/main/creative/conf"
"go-common/library/database/elastic"
"go-common/library/database/sql"
)
// Dao define
type Dao struct {
c *conf.Config
db *sql.DB
es *elastic.Elastic
}
// New init dao
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
db: sql.NewMySQL(c.DB.Creative),
es: elastic.NewElastic(nil),
}
return
}
// Ping db
func (d *Dao) Ping(c context.Context) (err error) {
return d.db.Ping(c)
}
// Close db
func (d *Dao) Close() (err error) {
return d.db.Close()
}

View File

@@ -0,0 +1,36 @@
package academy
import (
"flag"
"os"
"testing"
"go-common/app/interface/main/creative/conf"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.creative")
flag.Set("conf_token", "96b6a6c10bb311e894c14a552f48fef8")
flag.Set("tree_id", "2305")
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/creative.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
m.Run()
os.Exit(0)
}

View File

@@ -0,0 +1,24 @@
package academy
import (
"context"
"go-common/app/interface/main/creative/model/academy"
"go-common/library/log"
)
const (
// insert
_inFbSQL = "INSERT IGNORE INTO academy_feedback (category, course, suggest, ctime, mtime, mid) VALUES (?,?,?,?,?,?)"
)
// AddFeedBack add academy_feedback.
func (d *Dao) AddFeedBack(c context.Context, f *academy.FeedBack, mid int64) (id int64, err error) {
res, err := d.db.Exec(c, _inFbSQL, f.Category, f.Course, f.Suggest, f.CTime, f.MTime, mid)
if err != nil {
log.Error("d.db.Exec error(%v)", err)
return
}
id, err = res.LastInsertId()
return
}

View File

@@ -0,0 +1,27 @@
package academy
import (
"context"
"testing"
"go-common/app/interface/main/creative/model/academy"
"github.com/smartystreets/goconvey/convey"
)
func TestAcademyAddFeedBack(t *testing.T) {
convey.Convey("AddFeedBack", t, func(ctx convey.C) {
var (
c = context.Background()
f = &academy.FeedBack{}
mid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
id, err := d.AddFeedBack(c, f, mid)
ctx.Convey("Then err should be nil.id should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(id, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,96 @@
package academy
import (
"context"
"time"
"go-common/app/interface/main/creative/model/academy"
"go-common/library/database/elastic"
"go-common/library/ecode"
"go-common/library/log"
)
// ArchivesWithES search archives by es.
func (d *Dao) ArchivesWithES(c context.Context, aca *academy.EsParam) (res *academy.SearchResult, err error) {
r := d.es.NewRequest("academy_archive").Index("academy_archive").Fields("oid", "tid", "business")
if aca.Business > 0 {
r.WhereEq("business", aca.Business)
}
r.WhereEq("state", 0).Pn(aca.Pn).Ps(aca.Ps) //state 创作学院稿件状态
r.WhereEq("arc_state", 0) //arc_state 原始稿件状态(视频、专栏)
r.WhereEq("deleted_time", 0) //过滤删除的专栏
if aca.Seed > 0 {
r.OrderRandomSeed(time.Unix(aca.Seed, 0).Format("2006-01-02 15:04:05")) //随机推荐
}
if aca.Keyword != "" {
r.WhereLike([]string{"title", "tid_name"}, []string{aca.Keyword}, true, "low").Highlight(true)
}
if aca.Order != "" {
r.Order(aca.Order, "desc").OrderScoreFirst(false) //order: click (最多点击数), fav(最多收藏数), pubtime(最新发布时间), hot(最热值)
}
if aca.Duration > 0 { //h5 时长筛选 1(1-10分钟 ) 2(10-30分钟) 3(30-60分钟) 4(60分钟+)
switch aca.Duration {
case 1:
r.WhereRange("duration", 1*60, 10*60, elastic.RangeScopeLcRc)
case 2:
r.WhereRange("duration", 10*60, 30*60, elastic.RangeScopeLcRc)
case 3:
r.WhereRange("duration", 30*60, 60*60, elastic.RangeScopeLcRc)
case 4:
r.WhereRange("duration", 60*60, nil, elastic.RangeScopeLcRo)
}
if aca.Order == "" {
r.Order("duration", "desc")
}
}
if len(aca.TidsMap) > 0 {
for _, v := range aca.TidsMap {
cmb := &elastic.Combo{}
tids := make([]interface{}, 0, len(v))
for _, tid := range v {
tids = append(tids, tid)
}
cmb.ComboIn([]map[string][]interface{}{
{"tid": tids},
}).MinIn(1).MinAll(1)
r.WhereCombo(cmb)
}
}
res = &academy.SearchResult{}
log.Info("ArchivesWithES r.Scan params(%s)", r.Params())
if err = r.Scan(c, res); err != nil {
log.Error("ArchivesWithES r.Scan|error(%v)", err)
err = ecode.CreativeSearchErr
return
}
return
}
//Keywords get all keywords.
func (d *Dao) Keywords(c context.Context) (res []*academy.SearchKeywords, err error) {
_getKWSQL := "SELECT id, rank, parent_id, state, name, comment FROM academy_search_keywords WHERE state=0 ORDER BY rank ASC"
rows, err := d.db.Query(c, _getKWSQL)
if err != nil {
log.Error("Keywords d.db.Query error(%v)", err)
return
}
defer rows.Close()
res = make([]*academy.SearchKeywords, 0)
for rows.Next() {
o := &academy.SearchKeywords{}
if err = rows.Scan(&o.ID, &o.Rank, &o.ParentID, &o.State, &o.Name, &o.Comment); err != nil {
log.Error("Keywords rows.Scan error(%v)", err)
return
}
if o.Name == "" {
continue
}
res = append(res, o)
}
return
}

View File

@@ -0,0 +1,50 @@
package academy
import (
"context"
"testing"
"go-common/app/interface/main/creative/model/academy"
"github.com/smartystreets/goconvey/convey"
)
func TestAcademyArchivesWithES(t *testing.T) {
convey.Convey("ArchivesWithES", t, func(ctx convey.C) {
var (
c = context.Background()
aca = &academy.EsParam{
OID: int64(1),
Tid: []int64{1, 2},
Business: 1,
Pn: 10,
Ps: 20,
Keyword: "string",
Order: "",
IP: "",
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.ArchivesWithES(c, aca)
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 TestAcademyKeywords(t *testing.T) {
convey.Convey("Keywords", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.Keywords(c)
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,201 @@
package academy
import (
"context"
"fmt"
"go-common/app/interface/main/creative/model/academy"
"go-common/library/database/sql"
"go-common/library/log"
"go-common/library/xstr"
)
const (
// select
_getOccSQL = "SELECT id, rank, name, `desc`, main_step, main_software, logo FROM academy_occupation ORDER BY rank ASC"
_getSkillSQL = "SELECT id, oid, name, `desc` FROM academy_skill ORDER BY id ASC"
_getSkillArcSQL = "SELECT id, aid, type, pid, skid, sid FROM academy_arc_skill WHERE state=0"
_getSkillArcCntSQL = "SELECT count(*) FROM academy_arc_skill WHERE state=0"
)
//Occupations get all occupation.
func (d *Dao) Occupations(c context.Context) (res []*academy.Occupation, err error) {
rows, err := d.db.Query(c, _getOccSQL)
if err != nil {
log.Error("Occupations d.db.Query error(%v)", err)
return
}
defer rows.Close()
res = make([]*academy.Occupation, 0)
for rows.Next() {
o := &academy.Occupation{}
if err = rows.Scan(&o.ID, &o.Rank, &o.Name, &o.Desc, &o.MainStep, &o.MainSoftWare, &o.Logo); err != nil {
log.Error("Occupations rows.Scan error(%v)", err)
return
}
res = append(res, o)
}
return
}
//Skills get all Skill.
func (d *Dao) Skills(c context.Context) (res []*academy.Skill, err error) {
rows, err := d.db.Query(c, _getSkillSQL)
if err != nil {
log.Error("Skills d.db.Query error(%v)", err)
return
}
defer rows.Close()
res = make([]*academy.Skill, 0)
for rows.Next() {
o := &academy.Skill{}
if err = rows.Scan(&o.ID, &o.OID, &o.Name, &o.Desc); err != nil {
log.Error("Skills rows.Scan error(%v)", err)
return
}
res = append(res, o)
}
return
}
//SkillArcs get all SkillArc.
func (d *Dao) SkillArcs(c context.Context, pids, skids, sids []int64, offset, limit int) (res []*academy.SkillArc, err error) {
var (
whereStr = _getSkillArcSQL
limiStr = " ORDER BY id ASC LIMIT ?,?"
rows *sql.Rows
)
if len(pids) > 0 {
whereStr += fmt.Sprintf(" AND pid IN (%s)"+limiStr, xstr.JoinInts(pids))
} else if len(skids) > 0 {
whereStr += fmt.Sprintf(" AND skid IN (%s)"+limiStr, xstr.JoinInts(skids))
} else if len(sids) > 0 {
whereStr += fmt.Sprintf(" AND sid IN (%s)"+limiStr, xstr.JoinInts(sids))
} else {
whereStr += limiStr
}
rows, err = d.db.Query(c, whereStr, offset, limit)
if err != nil {
log.Error("SkillArcs d.db.Query error(%v)", err)
return
}
defer rows.Close()
res = make([]*academy.SkillArc, 0)
for rows.Next() {
o := &academy.SkillArc{}
if err = rows.Scan(&o.ID, &o.AID, &o.Type, &o.PID, &o.SkID, &o.SID); err != nil {
log.Error("SkillArcs rows.Scan error(%v)", err)
return
}
res = append(res, o)
}
return
}
//SkillArcCount get all skill achive count.
func (d *Dao) SkillArcCount(c context.Context, pids, skids, sids []int64) (count int, err error) {
var (
whereStr = _getSkillArcCntSQL
)
if len(pids) > 0 {
whereStr += fmt.Sprintf(" AND pid IN (%s)", xstr.JoinInts(pids))
} else if len(skids) > 0 {
whereStr += fmt.Sprintf(" AND skid IN (%s)", xstr.JoinInts(skids))
} else if len(sids) > 0 {
whereStr += fmt.Sprintf(" AND sid IN (%s)", xstr.JoinInts(sids))
}
if err = d.db.QueryRow(c, whereStr).Scan(&count); err != nil {
if err == sql.ErrNoRows {
err = nil
return
}
log.Error("d.db.QueryRow error(%v)", err)
}
return
}
// PlayAdd add play archive.
func (d *Dao) PlayAdd(c context.Context, p *academy.Play) (id int64, err error) {
_inPlaySQL := "INSERT INTO academy_playlist (mid, aid, business, watch, ctime, mtime) VALUES (?, ?, ?, ?, ?,?) ON DUPLICATE KEY UPDATE state=0,watch=?,business=?,mtime=?"
res, err := d.db.Exec(c, _inPlaySQL, p.MID, p.AID, p.Business, p.Watch, p.CTime, p.MTime, p.Watch, p.Business, p.MTime)
if err != nil {
log.Error("PlayAdd d.db.Exec error(%v)", err)
return
}
id, err = res.RowsAffected()
return
}
// PlayDel add play archive.
func (d *Dao) PlayDel(c context.Context, p *academy.Play) (id int64, err error) {
_upPlaySQL := "UPDATE academy_playlist SET state=? WHERE mid=? AND aid=? AND business=?"
res, err := d.db.Exec(c, _upPlaySQL, -1, p.MID, p.AID, p.Business) //-1 删除
if err != nil {
log.Error("PlayDel d.db.Exec error(%v)", err)
return
}
id, err = res.RowsAffected()
return
}
//Plays get all play by mid.
func (d *Dao) Plays(c context.Context, mid int64, offset, limit int) (res []*academy.Play, err error) {
_getPlaySSQL := "SELECT mid, aid, business, watch, ctime, mtime FROM academy_playlist WHERE state=0 AND mid=? ORDER BY mtime DESC LIMIT ?,?"
rows, err := d.db.Query(c, _getPlaySSQL, mid, offset, limit)
if err != nil {
log.Error("Plays d.db.Query error(%v)", err)
return
}
defer rows.Close()
res = make([]*academy.Play, 0)
for rows.Next() {
o := &academy.Play{}
if err = rows.Scan(&o.MID, &o.AID, &o.Business, &o.Watch, &o.CTime, &o.MTime); err != nil {
log.Error("Plays rows.Scan error(%v)", err)
return
}
res = append(res, o)
}
return
}
//PlayCount get all play achive count.
func (d *Dao) PlayCount(c context.Context, mid int64) (count int, err error) {
_getPlayCntSQL := "SELECT count(*) FROM academy_playlist WHERE state=0 AND mid=?"
if err = d.db.QueryRow(c, _getPlayCntSQL, mid).Scan(&count); err != nil {
if err == sql.ErrNoRows {
err = nil
return
}
log.Error("d.db.QueryRow error(%v)", err)
}
return
}
//Play get play achive info.
func (d *Dao) Play(c context.Context, p *academy.Play) (res *academy.Play, err error) {
_getPlaySQL := "SELECT mid, aid, business, watch, ctime, mtime FROM academy_playlist WHERE mid=? AND aid=? AND business=? "
res = &academy.Play{}
if err = d.db.QueryRow(c, _getPlaySQL, p.MID, p.AID, p.Business).Scan(&res.MID, &res.AID, &res.Business, &res.Watch, &res.CTime, &res.MTime); err != nil {
if err == sql.ErrNoRows {
err = nil
return
}
log.Error("d.db.QueryRow error(%v)", err)
}
return
}

View File

@@ -0,0 +1,127 @@
package academy
import (
"context"
"go-common/app/interface/main/creative/model/academy"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestAcademyOccupations(t *testing.T) {
convey.Convey("Occupations", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.Occupations(c)
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 TestAcademySkills(t *testing.T) {
convey.Convey("Skills", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.Skills(c)
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 TestAcademySkillArcs(t *testing.T) {
convey.Convey("SkillArcs", t, func(ctx convey.C) {
var (
c = context.Background()
pids = []int64{}
skids = []int64{}
sids = []int64{}
offset = int(0)
limit = int(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.SkillArcs(c, pids, skids, sids, offset, limit)
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 TestAcademySkillArcCount(t *testing.T) {
convey.Convey("SkillArcCount", t, func(ctx convey.C) {
var (
c = context.Background()
pids = []int64{}
skids = []int64{}
sids = []int64{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
count, err := d.SkillArcCount(c, pids, skids, sids)
ctx.Convey("Then err should be nil.count should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(count, convey.ShouldNotBeNil)
})
})
})
}
func TestAcademyPlayAdd(t *testing.T) {
convey.Convey("PlayAdd", t, func(ctx convey.C) {
var (
c = context.Background()
p = &academy.Play{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
id, err := d.PlayAdd(c, p)
ctx.Convey("Then err should be nil.id should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(id, convey.ShouldNotBeNil)
})
})
})
}
func TestAcademyPlays(t *testing.T) {
convey.Convey("Plays", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
offset = int(0)
limit = int(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.Plays(c, mid, offset, limit)
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 TestAcademyPlayCount(t *testing.T) {
convey.Convey("PlayCount", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
count, err := d.PlayCount(c, mid)
ctx.Convey("Then err should be nil.count should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(count, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,116 @@
package academy
import (
"context"
"fmt"
"go-common/app/interface/main/creative/model/academy"
"go-common/library/database/sql"
"go-common/library/log"
"go-common/library/xstr"
)
const (
// select
_getTagListSQL = "SELECT id, parent_id, type, business, name, `desc`, state, ctime,mtime FROM academy_tag WHERE state=0 ORDER BY rank asc"
_getTagByIDSQL = "SELECT id, parent_id, type, business, name, `desc`, state, ctime,mtime FROM academy_tag WHERE state=0 AND id=?"
_getTagInIDsSQL = "SELECT id, parent_id, type, business, name, `desc`, state, ctime,mtime FROM academy_tag WHERE state=0 AND id in (%s)"
_getTagLinkSQL = "SELECT id, tid, link_id FROM academy_tag_link WHERE tid in (%s)"
)
// TagList get all tag from academy_tag.
func (d *Dao) TagList(c context.Context) (res map[string][]*academy.Tag, tagMap, parentChildMap map[int64]*academy.Tag, err error) {
rows, err := d.db.Query(c, _getTagListSQL)
if err != nil {
log.Error("d.db.Query error(%v)", err)
return
}
defer rows.Close()
res = make(map[string][]*academy.Tag) //最终返回标签列表
all := make(map[int8]map[int64]*academy.Tag) //含有分类的一二级标签
top := make(map[int64]*academy.Tag)
tagMap = make(map[int64]*academy.Tag) //不包含二级标签
parentChildMap = make(map[int64]*academy.Tag) //包含一二级标签
allTag := make([]*academy.Tag, 0)
for rows.Next() {
t := &academy.Tag{}
if err = rows.Scan(&t.ID, &t.ParentID, &t.Type, &t.Business, &t.Name, &t.Desc, &t.State, &t.CTime, &t.MTime); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
nt := &academy.Tag{}
*nt = *t
tagMap[t.ID] = nt //nt对象 不会被修改
parentChildMap[t.ID] = t //t对象 会被修改
allTag = append(allTag, t)
}
for _, t := range allTag {
if t.ParentID == 0 {
top[t.ID] = t
all[t.Type] = top
tyName := academy.TagClassMap(int(t.Type))
res[tyName] = append(res[tyName], t)
}
}
for _, t := range allTag {
a, ok := all[t.Type][t.ParentID]
if ok && a != nil && a.Type == t.Type {
a.Children = append(a.Children, t)
}
}
return
}
//Tag get one tag.
func (d *Dao) Tag(c context.Context, id int64) (t *academy.Tag, err error) {
row := d.db.QueryRow(c, _getTagByIDSQL, id)
t = &academy.Tag{}
if err = row.Scan(&t.ID, &t.ParentID, &t.Type, &t.Business, &t.Name, &t.Desc, &t.State, &t.CTime, &t.MTime); err != nil {
if err == sql.ErrNoRows {
err = nil
return
}
log.Error("row.Scan error(%v)", err)
}
return
}
//Tags get some tags by ids.
func (d *Dao) Tags(c context.Context, ids []int64) (res []*academy.Tag, err error) {
rows, err := d.db.Query(c, fmt.Sprintf(_getTagInIDsSQL, xstr.JoinInts(ids)))
if err != nil {
log.Error("d.db.Query error(%v)", err)
return
}
defer rows.Close()
res = make([]*academy.Tag, 0)
for rows.Next() {
t := &academy.Tag{}
if err = rows.Scan(&t.ID, &t.ParentID, &t.Type, &t.Business, &t.Name, &t.Desc, &t.State, &t.CTime, &t.MTime); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
res = append(res, t)
}
return
}
//LinkTags get link tags by h5 tids.
func (d *Dao) LinkTags(c context.Context, ids []int64) (res []*academy.LinkTag, err error) {
rows, err := d.db.Query(c, fmt.Sprintf(_getTagLinkSQL, xstr.JoinInts(ids)))
if err != nil {
log.Error("d.db.Query error(%v)", err)
return
}
defer rows.Close()
res = make([]*academy.LinkTag, 0)
for rows.Next() {
t := &academy.LinkTag{}
if err = rows.Scan(&t.ID, &t.TID, &t.LinkID); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
res = append(res, t)
}
return
}

View File

@@ -0,0 +1,73 @@
package academy
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestAcademyTagList(t *testing.T) {
convey.Convey("TagList", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, tagMap, parentChildMap, err := d.TagList(c)
ctx.Convey("Then err should be nil.res,tagMap,parentChildMap should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(parentChildMap, convey.ShouldNotBeNil)
ctx.So(tagMap, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestAcademyTag(t *testing.T) {
convey.Convey("Tag", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
no, err := d.Tag(c, id)
ctx.Convey("Then err should be nil.no should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(no, convey.ShouldNotBeNil)
})
})
})
}
func TestAcademyTags(t *testing.T) {
convey.Convey("Tags", t, func(ctx convey.C) {
var (
c = context.Background()
ids = []int64{1, 2}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.Tags(c, ids)
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 TestAcademyLinkTags(t *testing.T) {
convey.Convey("LinkTags", t, func(ctx convey.C) {
var (
c = context.Background()
ids = []int64{1}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.LinkTags(c, ids)
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,70 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"dao_test.go",
"memcache_test.go",
"up_test.go",
],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/account:go_default_library",
"//app/service/main/account/api:go_default_library",
"//app/service/main/relation/model:go_default_library",
"//app/service/main/relation/rpc/client:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/ecode:go_default_library",
"//vendor/github.com/bouk/monkey:go_default_library",
"//vendor/github.com/golang/mock/gomock: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 = [
"dao.go",
"memcache.go",
"up.go",
],
importpath = "go-common/app/interface/main/creative/dao/account",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/account:go_default_library",
"//app/interface/main/creative/model/appeal:go_default_library",
"//app/service/main/account/api:go_default_library",
"//app/service/main/relation/model:go_default_library",
"//app/service/main/relation/rpc/client: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/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,390 @@
package account
import (
"context"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/model/appeal"
accapi "go-common/app/service/main/account/api"
relaMdl "go-common/app/service/main/relation/model"
relation "go-common/app/service/main/relation/rpc/client"
"go-common/library/cache/memcache"
"go-common/library/ecode"
"go-common/library/log"
httpx "go-common/library/net/http/blademaster"
"go-common/library/sync/errgroup"
"net/http"
"net/url"
"time"
)
const (
_pass = "/web/site/userInfo"
_richRelation = "/x/account/relation/rich"
_relation = "/x/internal/relation"
)
// Dao is account dao.
type Dao struct {
c *conf.Config
// rpc
acc accapi.AccountClient
rela *relation.Service
// http client
client *httpx.Client
fastClient *httpx.Client
mc *memcache.Pool
mcExpire int32
// user
passURI string
relationURI string
richRelationURI string
picUpInfoURL string
blinkUpInfoURL string
upInfoURL string
}
// New new a dao.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
rela: relation.New(c.RelationRPC),
// http client
client: httpx.NewClient(c.HTTPClient.Normal),
fastClient: httpx.NewClient(c.HTTPClient.Fast),
passURI: c.Host.Passport + _pass,
relationURI: c.Host.API + _relation,
richRelationURI: c.Host.API + _richRelation,
picUpInfoURL: c.Host.Live + _picUpInfoURL,
blinkUpInfoURL: c.Host.Live + _blinkUpInfoURL,
upInfoURL: c.Host.API + _upInfoURL,
mc: memcache.NewPool(c.Memcache.Archive.Config),
mcExpire: int32(time.Duration(c.Memcache.Archive.TplExpire) / time.Second),
}
var err error
if d.acc, err = accapi.NewClient(c.AccClient); err != nil {
panic(err)
}
return
}
// Profile get account.
func (d *Dao) Profile(c context.Context, mid int64, ip string) (res *accapi.Profile, err error) {
var (
arg = &accapi.MidReq{
Mid: mid,
}
rpcRes *accapi.ProfileReply
)
if rpcRes, err = d.acc.Profile3(c, arg); err != nil {
log.Error("d.acc.Profile3 error(%v)", err)
err = ecode.CreativeAccServiceErr
}
if rpcRes != nil {
res = rpcRes.Profile
}
return
}
// ProfileWithStat get account.
func (d *Dao) ProfileWithStat(c context.Context, mid int64) (res *accapi.ProfileStatReply, err error) {
var (
arg = &accapi.MidReq{
Mid: mid,
}
)
if res, err = d.acc.ProfileWithStat3(c, arg); err != nil {
log.Error("d.acc.ProfileWithStat3() error(%v)", err)
err = ecode.CreativeAccServiceErr
}
return
}
// Card get account.
func (d *Dao) Card(c context.Context, mid int64, ip string) (res *accapi.Card, err error) {
var (
rpcRes *accapi.CardReply
arg = &accapi.MidReq{
Mid: mid,
}
)
if rpcRes, err = d.acc.Card3(c, arg); err != nil {
log.Error("d.acc.Card3() error(%v)", err)
err = ecode.CreativeAccServiceErr
}
if rpcRes != nil {
res = rpcRes.Card
}
return
}
// Cards get cards from rpc
func (d *Dao) Cards(c context.Context, mids []int64, ip string) (cards map[int64]*accapi.Card, err error) {
if len(mids) == 0 {
return
}
arg := &accapi.MidsReq{
Mids: mids,
}
var reply *accapi.CardsReply
if reply, err = d.acc.Cards3(c, arg); err != nil {
log.Error("d.acc.Cards3 error(%v) | mids(%v) ip(%s) arg(%v)", err, mids, ip, arg)
err = ecode.CreativeAccServiceErr
return
}
cards = reply.Cards
return
}
// PhoneEmail get user email & phone
func (d *Dao) PhoneEmail(c context.Context, ck, ip string) (ct *appeal.Contact, err error) {
params := url.Values{}
params.Set("Cookie", ck)
// init req set cookie
req, err := http.NewRequest("GET", d.passURI, nil)
if err != nil {
log.Error("passport url(%s) error(%v)", d.passURI, err)
return
}
req.Header.Set("Cookie", ck)
req.Header.Set("X-BACKEND-BILI-REAL-IP", ip)
var res struct {
Code int `json:"code"`
Data *appeal.Contact `json:"data"`
}
if err = d.client.Do(c, req, &res); err != nil {
log.Error("passport url(%s) response(%+v) error(%v)", d.passURI+"?"+params.Encode(), res, err)
err = ecode.CreativeAccServiceErr
return
}
if res.Code != 0 {
log.Error("passport url(%s) res(%v)", d.passURI, res)
err = ecode.CreativeAccServiceErr
return
}
ct = res.Data
return
}
// RichRelation get multi user relations
func (d *Dao) RichRelation(c context.Context, owner int64, mids []int64, ip string) (richRel map[int64]int32, err error) {
var rpcRes *accapi.RichRelationsReply
if rpcRes, err = d.acc.RichRelations3(c, &accapi.RichRelationReq{Owner: owner, Mids: mids}); err != nil {
log.Error("d.acc.RichRelations3(%d, %v) error(%v)", owner, mids, err)
err = ecode.CreativeAccServiceErr
}
if rpcRes != nil {
richRel = rpcRes.RichRelations
}
return
}
// Followers get users only follower relation which attr eq 2 with errgroup
func (d *Dao) Followers(c context.Context, owner int64, mids []int64, ip string) (relations map[int64]int, err error) {
relations = make(map[int64]int, len(mids))
type midRel struct {
mid int64
rel int
}
rechan := make(chan midRel, len(mids)) // avoid concurrent write map
g, ctx := errgroup.WithContext(c)
for _, mid := range mids {
var mid2 = mid // for closure, copy to avoid same mid
g.Go(func() error {
rl, e := d.acc.Relation3(ctx, &accapi.RelationReq{Mid: mid2, Owner: owner})
if e != nil || rl == nil || !rl.Following {
if e != nil {
log.Error("d.acc.Relation3(mid:%d,owner:%d,relation:%v) error(%v)", mid2, owner, rl, e)
}
rechan <- midRel{mid2, 1}
} else {
rechan <- midRel{mid2, 2}
}
return nil
})
}
g.Wait()
for i := 0; i < len(mids); i++ {
wc := <-rechan
relations[wc.mid] = wc.rel
}
return
}
// Infos get user info by mids.
func (d *Dao) Infos(c context.Context, mids []int64, ip string) (res map[int64]*accapi.Info, err error) {
res = make(map[int64]*accapi.Info)
if len(mids) == 0 {
return
}
var arg = &accapi.MidsReq{
Mids: mids,
}
var rpcRes *accapi.InfosReply
if rpcRes, err = d.acc.Infos3(c, arg); err != nil {
log.Error("d.acc.Infos3() error(%v)|ip(%s)", err, ip)
err = ecode.CreativeAccServiceErr
}
if rpcRes != nil {
res = rpcRes.Infos
}
return
}
// IdentifyInfo 获取用户实名认证状态
// tel_status int 0未绑定1已绑定有效手机号 2绑定虚拟号段170/171
// identification int 身份证绑定状态0:未绑定 1:已绑定
func (d *Dao) IdentifyInfo(c context.Context, mid int64, phoneOnly int8, ip string) (ret int, err error) {
var (
rpcRes *accapi.ProfileReply
arg = &accapi.MidReq{
Mid: mid,
}
mf *accapi.Profile
)
if rpcRes, err = d.acc.Profile3(c, arg); err != nil {
log.Error("d.acc.Profile3 error(%v) | mid(%d) ip(%s) arg(%v)", err, mid, ip, arg)
err = ecode.CreativeAccServiceErr
return
}
if rpcRes != nil {
mf = rpcRes.Profile
}
//switch for FrontEnd return json format
ret = d.switchPhoneRet(int(mf.TelStatus))
if phoneOnly == 1 {
return
}
if mf.TelStatus == 1 || mf.Identification == 1 {
return 0, err
}
return
}
// MidByName 获取mid
func (d *Dao) MidByName(c context.Context, name string) (mid int64, err error) {
var (
rpcRes *accapi.InfosReply
arg = &accapi.NamesReq{
Names: []string{name},
}
infos map[int64]*accapi.Info
)
if rpcRes, err = d.acc.InfosByName3(c, arg); err != nil {
log.Error("d.acc.InfosByName3 error(%v)", err)
err = ecode.CreativeAccServiceErr
return
}
if rpcRes != nil {
infos = rpcRes.Infos
}
for _, v := range infos {
if v != nil && v.Name == name {
return v.Mid, nil
}
}
err = ecode.AccountInexistence
return
}
// 0: "已实名认证",
// 1: "根据国家实名制认证的相关要求您需要换绑一个非170/171的手机号才能继续进行操作。",
// 2: "根据国家实名制认证的相关要求,您需要绑定手机号,才能继续进行操作。",
func (d *Dao) switchPhoneRet(newV int) (oldV int) {
switch newV {
case 0:
oldV = 2
case 1:
oldV = 0
case 2:
oldV = 1
}
return
}
// CheckIdentify fn
func (d *Dao) CheckIdentify(identify int) (err error) {
switch identify {
case 0:
err = nil
case 1:
err = ecode.UserCheckInvalidPhone
case 2:
err = ecode.UserCheckNoPhone
}
return
}
// RelationFollowers get all relation state.
func (d *Dao) RelationFollowers(c context.Context, mid int64, ip string) (res map[int64]int32, err error) {
var fls []*relaMdl.Following
if fls, err = d.rela.Followers(c, &relaMdl.ArgMid{Mid: mid, RealIP: ip}); err != nil {
log.Error("d.rela.Followers mid(%d)|ip(%s)|error(%v)", mid, ip, err)
return
}
if len(fls) == 0 {
log.Info("d.rela.Followers mid(%d)|ip(%s)", mid, ip)
return
}
res = make(map[int64]int32, len(fls))
for _, v := range fls {
res[v.Mid] = int32(v.Attribute)
}
log.Info("d.rela.Followers mid(%d)|res(%+v)|ip(%s)", mid, res, ip)
return
}
// Relations get all relation state.
func (d *Dao) Relations(c context.Context, mid int64, fids []int64, ip string) (res map[int64]int, err error) {
var rls map[int64]*relaMdl.Following
if rls, err = d.rela.Relations(c, &relaMdl.ArgRelations{Mid: mid, Fids: fids, RealIP: ip}); err != nil {
log.Error("d.rela.Relations mid(%d)|ip(%s)|error(%v)", mid, ip, err)
err = ecode.CreativeAccServiceErr
return
}
if len(rls) == 0 {
log.Info("d.rela.Relations mid(%d)|ip(%s)", mid, ip)
return
}
res = make(map[int64]int, len(rls))
for _, v := range rls {
res[v.Mid] = int(v.Attribute)
}
log.Info("d.rela.Relations mid(%d)|res(%+v)|rls(%+v)|ip(%s)", mid, res, rls, ip)
return
}
// Relations2
func (d *Dao) Relations2(c context.Context, mid int64, fids []int64, ip string) (res map[int64]int, err error) {
if res, err = d.Relations(c, mid, fids, ip); err != nil {
return
}
for k, v := range res {
if v == 2 || v == 6 { //2表示我关注他,6表示双向关注,为了兼容客户端统一吐出6作为已关注状态.
res[k] = 6
} else {
delete(res, k)
}
}
return
}
// ShouldFollow fn
func (d *Dao) ShouldFollow(c context.Context, mid int64, fids []int64, ip string) (shouldMids []int64, err error) {
var rls map[int64]*relaMdl.Following
if rls, err = d.rela.Relations(c, &relaMdl.ArgRelations{Mid: mid, Fids: fids, RealIP: ip}); err != nil {
log.Error("d.rela.Relations mid(%d)|fids(%+v)|ip(%s)|error(%v)", mid, fids, ip, err)
return
}
if len(rls) == 0 {
shouldMids = fids
return
}
shouldMids = make([]int64, 0)
for _, v := range rls {
if v.Attribute == 0 {
shouldMids = append(shouldMids, v.Mid)
}
}
log.Info("d.rela.Relations mid(%d)|shouldMids(%+v)|ip(%s)", mid, shouldMids, ip)
return
}

View File

@@ -0,0 +1,344 @@
package account
import (
"context"
"flag"
"go-common/app/interface/main/creative/conf"
accapi "go-common/app/service/main/account/api"
relaMdl "go-common/app/service/main/relation/model"
relation "go-common/app/service/main/relation/rpc/client"
"go-common/library/ecode"
"os"
"reflect"
"strings"
"testing"
"github.com/bouk/monkey"
"github.com/golang/mock/gomock"
. "github.com/smartystreets/goconvey/convey"
gock "gopkg.in/h2non/gock.v1"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.creative")
flag.Set("conf_token", "96b6a6c10bb311e894c14a552f48fef8")
flag.Set("tree_id", "2305")
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/creative.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
m.Run()
os.Exit(0)
}
func httpMock(method, url string) *gock.Request {
r := gock.New(url)
r.Method = strings.ToUpper(method)
d.client.SetTransport(gock.DefaultTransport)
d.fastClient.SetTransport(gock.DefaultTransport)
return r
}
func TestIdentifyInfo(t *testing.T) {
Convey("IdentifyInfo", t, WithMock(t, func(mockCtrl *gomock.Controller) {
var (
c = context.TODO()
err error
mid = int64(27515256)
ip = "127.0.0.1"
ret int
)
mock := accapi.NewMockAccountClient(mockCtrl)
d.acc = mock
arg := &accapi.MidReq{
Mid: mid,
}
mock.EXPECT().Profile3(gomock.Any(), arg).Return(nil, ecode.CreativeAccServiceErr)
ret, err = d.IdentifyInfo(c, mid, 1, ip)
So(err, ShouldNotBeNil)
So(ret, ShouldNotBeNil)
}))
}
func TestMidByName(t *testing.T) {
Convey("IdentifyInfo", t, WithMock(t, func(mockCtrl *gomock.Controller) {
var (
c = context.TODO()
err error
ret int64
name = "iamname"
)
mock := accapi.NewMockAccountClient(mockCtrl)
d.acc = mock
arg := &accapi.NamesReq{
Names: []string{name},
}
mock.EXPECT().InfosByName3(gomock.Any(), arg).Return(nil, ecode.CreativeAccServiceErr)
ret, err = d.MidByName(c, name)
So(err, ShouldNotBeNil)
So(ret, ShouldBeZeroValue)
}))
}
func TestInfos(t *testing.T) {
Convey("IdentifyInfo", t, WithMock(t, func(mockCtrl *gomock.Controller) {
var (
c = context.TODO()
err error
mids = []int64{2089809}
ip = "127.0.0.1"
)
mock := accapi.NewMockAccountClient(mockCtrl)
d.acc = mock
mockReq := &accapi.MidsReq{
Mids: mids,
}
mock.EXPECT().Infos3(gomock.Any(), mockReq).Return(nil, ecode.CreativeAccServiceErr)
_, err = d.Infos(c, mids, ip)
So(err, ShouldNotBeNil)
}))
}
func TestProfile(t *testing.T) {
Convey("Profile", t, WithMock(t, func(mockCtrl *gomock.Controller) {
var (
c = context.TODO()
err error
mid = int64(27515256)
ip = "127.0.0.1"
p *accapi.Profile
)
mock := accapi.NewMockAccountClient(mockCtrl)
d.acc = mock
mockReq := &accapi.MidReq{
Mid: mid,
}
mock.EXPECT().Profile3(gomock.Any(), mockReq).Return(nil, ecode.CreativeAccServiceErr)
p, err = d.Profile(c, mid, ip)
So(err, ShouldNotBeNil)
So(p, ShouldBeNil)
}))
}
func TestProfileWithStat(t *testing.T) {
Convey("ProfileWithStat", t, WithMock(t, func(mockCtrl *gomock.Controller) {
var (
c = context.TODO()
err error
mid = int64(27515256)
p *accapi.ProfileStatReply
)
mock := accapi.NewMockAccountClient(mockCtrl)
d.acc = mock
mockReq := &accapi.MidReq{
Mid: mid,
}
mock.EXPECT().ProfileWithStat3(gomock.Any(), mockReq).Return(nil, ecode.CreativeAccServiceErr)
p, err = d.ProfileWithStat(c, mid)
So(err, ShouldNotBeNil)
So(p, ShouldBeNil)
}))
}
func TestCard(t *testing.T) {
Convey("Card", t, WithMock(t, func(mockCtrl *gomock.Controller) {
var (
c = context.TODO()
err error
mid = int64(27515256)
ip = "127.0.0.1"
ret *accapi.Card
)
mock := accapi.NewMockAccountClient(mockCtrl)
d.acc = mock
mockReq := &accapi.MidReq{
Mid: mid,
}
mock.EXPECT().Card3(gomock.Any(), mockReq).Return(nil, ecode.CreativeAccServiceErr)
ret, err = d.Card(c, mid, ip)
So(err, ShouldNotBeNil)
So(ret, ShouldBeNil)
}))
}
func TestRichRelation(t *testing.T) {
Convey("RichRelation", t, WithMock(t, func(mockCtrl *gomock.Controller) {
var (
c = context.TODO()
err error
owner = int64(27515256)
mids = []int64{2089809}
ip = "127.0.0.1"
ret map[int64]int32
)
mock := accapi.NewMockAccountClient(mockCtrl)
d.acc = mock
arg := &accapi.RichRelationReq{
Owner: owner,
Mids: mids,
}
mock.EXPECT().RichRelations3(gomock.Any(), arg).Return(nil, ecode.CreativeAccServiceErr)
ret, err = d.RichRelation(c, owner, mids, ip)
So(err, ShouldNotBeNil)
So(ret, ShouldBeNil)
}))
}
func TestRelationFollowers(t *testing.T) {
Convey("RelationFollowers", t, func(ctx C) {
var (
c = context.TODO()
err error
mid = int64(2089809)
ip = "127.0.0.1"
ret map[int64]int32
)
mock := monkey.PatchInstanceMethod(reflect.TypeOf(d.rela), "Followers",
func(_ *relation.Service, _ context.Context, _ *relaMdl.ArgMid) (res []*relaMdl.Following, err error) {
return nil, ecode.CreativeAccServiceErr
})
defer mock.Unpatch()
ret, err = d.RelationFollowers(c, mid, ip)
ctx.Convey("RelationFollowers", func(ctx C) {
ctx.So(err, ShouldNotBeNil)
ctx.So(ret, ShouldBeNil)
})
})
}
func TestShouldFollow(t *testing.T) {
Convey("ShouldFollow", t, func(ctx C) {
var (
c = context.TODO()
err error
mid = int64(2089809)
fids = []int64{2089809}
ip = "127.0.0.1"
ret []int64
)
mock := monkey.PatchInstanceMethod(reflect.TypeOf(d.rela), "Relations",
func(_ *relation.Service, _ context.Context, _ *relaMdl.ArgRelations) (res map[int64]*relaMdl.Following, err error) {
res = make(map[int64]*relaMdl.Following)
res[2089809] = &relaMdl.Following{
Attribute: 0,
}
return res, nil
})
defer mock.Unpatch()
ret, err = d.ShouldFollow(c, mid, fids, ip)
ctx.Convey("RelationFollowers", func(ctx C) {
ctx.So(err, ShouldBeNil)
ctx.So(ret, ShouldNotBeNil)
})
})
}
func TestSwitchPhoneRet(t *testing.T) {
var (
new, old, identify int
err error
)
new = 1
Convey("switchPhoneRet", t, func(ctx C) {
old = d.switchPhoneRet(new)
ctx.Convey("Then err should be nil.has should not be nil.", func(ctx C) {
ctx.So(old, ShouldBeZeroValue)
})
})
identify = 1
Convey("CheckIdentify", t, func(ctx C) {
err = d.CheckIdentify(identify)
ctx.Convey("Then err should be nil.has should not be nil.", func(ctx C) {
ctx.So(err, ShouldEqual, ecode.UserCheckInvalidPhone)
})
})
}
func TestDao_Followers(t *testing.T) {
Convey("Followers", t, WithMock(t, func(mockCtrl *gomock.Controller) {
var (
c = context.TODO()
err error
mid = int64(2089809)
fid = int64(2089809)
ip = "127.0.0.1"
)
mock := accapi.NewMockAccountClient(mockCtrl)
d.acc = mock
arg := &accapi.RelationReq{
Owner: mid,
Mid: fid,
}
mock.EXPECT().Relation3(gomock.Any(), arg).Return(nil, ecode.CreativeAccServiceErr)
_, err = d.Followers(c, mid, []int64{fid}, ip)
Convey("Followers", func(ctx C) {
ctx.So(err, ShouldBeNil)
})
}))
}
func TestDao_Relations(t *testing.T) {
Convey("Relations", t, func(ctx C) {
var (
c = context.TODO()
err error
mid = int64(2089809)
fids = []int64{2089809}
ip = "127.0.0.1"
ret map[int64]int
)
mock := monkey.PatchInstanceMethod(reflect.TypeOf(d.rela), "Relations",
func(_ *relation.Service, _ context.Context, _ *relaMdl.ArgRelations) (res map[int64]*relaMdl.Following, err error) {
return nil, ecode.CreativeAccServiceErr
})
defer mock.Unpatch()
ret, err = d.Relations(c, mid, fids, ip)
ctx.Convey("RelationFollowers", func(ctx C) {
ctx.So(err, ShouldNotBeNil)
ctx.So(ret, ShouldBeNil)
})
})
}
func TestDao_Relations2(t *testing.T) {
Convey("Relations2", t, func(ctx C) {
var (
c = context.TODO()
err error
mid = int64(2089809)
fids = []int64{2089809}
ip = "127.0.0.1"
ret map[int64]int
)
mock := monkey.PatchInstanceMethod(reflect.TypeOf(d.rela), "Relations",
func(_ *relation.Service, _ context.Context, _ *relaMdl.ArgRelations) (res map[int64]*relaMdl.Following, err error) {
return nil, ecode.CreativeAccServiceErr
})
defer mock.Unpatch()
ret, err = d.Relations2(c, mid, fids, ip)
ctx.Convey("RelationFollowers", func(ctx C) {
ctx.So(err, ShouldNotBeNil)
ctx.So(ret, ShouldBeNil)
})
})
}
func WithMock(t *testing.T, f func(mock *gomock.Controller)) func() {
return func() {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
f(mockCtrl)
}
}

View File

@@ -0,0 +1,87 @@
package account
import (
"context"
"strconv"
accmdl "go-common/app/interface/main/creative/model/account"
"go-common/library/cache/memcache"
"go-common/library/log"
)
const (
_upInfoPrefix = "upinfo_"
_addMidHalfMinPrefix = "add_midhafmin_"
)
func limitMidHafMin(mid int64) string {
return _addMidHalfMinPrefix + strconv.FormatInt(mid, 10)
}
func keyUpInfo(mid int64) string {
return _upInfoPrefix + strconv.FormatInt(mid, 10)
}
// HalfMin fn
func (d *Dao) HalfMin(c context.Context, mid int64) (exist bool, ts uint64, err error) {
var (
conn = d.mc.Get(c)
rp *memcache.Item
)
defer conn.Close()
key := limitMidHafMin(mid)
rp, err = conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
} else {
log.Error("conn.Get error(%v) | key(%s) mid(%d)", err, key, mid)
}
return
}
if err = conn.Scan(rp, &ts); err != nil {
log.Error("conn.Scan(%s) error(%v)", rp.Value, err)
return
}
log.Info("HalfMin (%d) | key(%s) ts(%d)", mid, key, ts)
if ts != 0 {
exist = true
}
return
}
// UpInfoCache get stat cache.
func (d *Dao) UpInfoCache(c context.Context, mid int64) (st *accmdl.UpInfo, err error) {
var (
conn = d.mc.Get(c)
r *memcache.Item
)
defer conn.Close()
r, err = conn.Get(keyUpInfo(mid))
if err != nil {
if err == memcache.ErrNotFound {
err = nil
} else {
log.Error("conn.Get2(%d) error(%v)", mid, err)
}
return
}
if err = conn.Scan(r, &st); err != nil {
log.Error("json.Unmarshal(%s) error(%v)", r.Value, err)
st = nil
}
return
}
// AddUpInfoCache add stat cache.
func (d *Dao) AddUpInfoCache(c context.Context, mid int64, st *accmdl.UpInfo) (err error) {
var (
key = keyUpInfo(mid)
)
conn := d.mc.Get(c)
defer conn.Close()
if err = conn.Set(&memcache.Item{Key: key, Object: st, Flags: memcache.FlagJSON, Expiration: d.mcExpire}); err != nil {
log.Error("memcache.Set(%v) error(%v)", key, err)
}
return
}

View File

@@ -0,0 +1,87 @@
package account
import (
"context"
accmdl "go-common/app/interface/main/creative/model/account"
"go-common/library/cache/memcache"
"reflect"
"testing"
"github.com/bouk/monkey"
"github.com/smartystreets/goconvey/convey"
)
func TestAccountlimitMidHafMin(t *testing.T) {
var (
mid = int64(2089809)
)
convey.Convey("limitMidHafMin", t, func(ctx convey.C) {
p1 := limitMidHafMin(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestAccountkeyUpInfo(t *testing.T) {
var (
mid = int64(2089809)
)
convey.Convey("keyUpInfo", t, func(ctx convey.C) {
p1 := keyUpInfo(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestAccountHalfMin(t *testing.T) {
var (
c = context.TODO()
mid = int64(2089809)
)
convey.Convey("HalfMin", t, func(ctx convey.C) {
exist, ts, err := d.HalfMin(c, mid)
ctx.Convey("Then err should be nil.exist,ts should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(ts, convey.ShouldNotBeNil)
ctx.So(exist, convey.ShouldNotBeNil)
})
})
}
func TestAccountUpInfoCache(t *testing.T) {
var (
c = context.TODO()
mid = int64(2089809)
)
convey.Convey("UpInfoCache", t, func(ctx convey.C) {
connGuard := monkey.PatchInstanceMethod(reflect.TypeOf(d.mc), "Get", func(_ *memcache.Pool, _ context.Context) memcache.Conn {
return memcache.MockWith(memcache.ErrNotFound)
})
defer connGuard.Unpatch()
st, err := d.UpInfoCache(c, mid)
ctx.Convey("Then err should be nil.st should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(st, convey.ShouldBeNil)
})
})
}
func TestAccountAddUpInfoCache(t *testing.T) {
var (
c = context.TODO()
mid = int64(2089809)
st = &accmdl.UpInfo{}
)
convey.Convey("AddUpInfoCache", t, func(ctx convey.C) {
connGuard := monkey.PatchInstanceMethod(reflect.TypeOf(d.mc), "Get", func(_ *memcache.Pool, _ context.Context) memcache.Conn {
return memcache.MockWith(nil)
})
defer connGuard.Unpatch()
err := d.AddUpInfoCache(c, mid, st)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,70 @@
package account
import (
"context"
"net/url"
"strconv"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_picUpInfoURL = "/link_draw_ex/v0/doc/check"
_blinkUpInfoURL = "/clip_ext/v0/video/have"
_upInfoURL = "/x/internal/uper/info"
)
// Pic pic return value
type Pic struct {
Has int `json:"has_doc"`
}
// Blink blink return value
type Blink struct {
Has int `json:"has"`
}
// Pic get pic up info.
func (d *Dao) Pic(c context.Context, mid int64, ip string) (has int, err error) {
params := url.Values{}
params.Set("uid", strconv.FormatInt(mid, 10))
var res struct {
Code int `json:"code"`
Data Pic `json:"data"`
}
err = d.fastClient.Get(c, d.picUpInfoURL, ip, params, &res)
if err != nil {
log.Error("d.fastClient.Get(%s) error(%v)", d.picUpInfoURL+"?"+params.Encode(), err)
return
}
if res.Code != 0 {
log.Error("Pic url(%s) error(%v)", d.picUpInfoURL+"?"+params.Encode(), err)
err = ecode.Int(res.Code)
return
}
has = res.Data.Has
return
}
// Blink get BLink up info.
func (d *Dao) Blink(c context.Context, mid int64, ip string) (has int, err error) {
params := url.Values{}
params.Set("uid", strconv.FormatInt(mid, 10))
var res struct {
Code int `json:"code"`
Data Blink `json:"data"`
}
err = d.fastClient.Get(c, d.blinkUpInfoURL, ip, params, &res)
if err != nil {
log.Error("d.fastClient.Get(%s) error(%v)", d.blinkUpInfoURL+"?"+params.Encode(), err)
return
}
if res.Code != 0 {
log.Error("Blink url(%s) error(%v)", d.blinkUpInfoURL+"?"+params.Encode(), err)
err = ecode.Int(res.Code)
return
}
has = res.Data.Has
return
}

View File

@@ -0,0 +1,60 @@
package account
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
gock "gopkg.in/h2non/gock.v1"
)
const (
mid = int64(2089809)
ip = "127.0.0.1"
)
func TestPhoneEmail(t *testing.T) {
var (
c = context.TODO()
ck = "iamck"
)
convey.Convey("PhoneEmail", t, func(ctx convey.C) {
defer gock.OffAll()
httpMock("GET", d.passURI).Reply(200).JSON(`{"code":20007}`)
ret, err := d.PhoneEmail(c, ck, ip)
ctx.Convey("Then err should be nil.ret should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(ret, convey.ShouldBeNil)
})
})
}
func TestAccountPic(t *testing.T) {
var (
c = context.TODO()
)
convey.Convey("Pic", t, func(ctx convey.C) {
defer gock.OffAll()
httpMock("GET", d.picUpInfoURL).Reply(200).JSON(`{"code":0,"data":{"has_doc":100}}`)
has, err := d.Pic(c, mid, ip)
ctx.Convey("Then err should be nil.has should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(has, convey.ShouldNotBeNil)
})
})
}
func TestAccountBlink(t *testing.T) {
var (
c = context.TODO()
)
convey.Convey("Blink", t, func(ctx convey.C) {
defer gock.OffAll()
httpMock("GET", d.blinkUpInfoURL).Reply(200).JSON(`{"code":0,"data":{"has":100}}`)
has, err := d.Blink(c, mid, ip)
ctx.Convey("Then err should be nil.has should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(has, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,50 @@
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"],
importpath = "go-common/app/interface/main/creative/dao/activity",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/activity:go_default_library",
"//library/ecode: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 = ["dao_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/activity: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,213 @@
package activity
import (
"context"
"encoding/json"
"net/url"
"strconv"
"strings"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/model/activity"
"go-common/library/ecode"
"go-common/library/log"
httpx "go-common/library/net/http/blademaster"
)
const (
_activityAllList = "/activity/list/videoall"
_activityUpdate = "/api/likes/upbyaid/%d"
_activitySubject = "/activity/subject/%d"
_activityProtocol = "/activity/protocol/%d"
_actOnlineByTypeURI = "/activity/online/by/type"
_actURLType16 = "https://www.bilibili.com/blackboard/x/activity-tougao-h5/detail?from=snap&id="
_actLike = "/activity/likes/list/%d"
)
// Dao define
type Dao struct {
c *conf.Config
// http
client *httpx.Client
// uri
ActAllListURI string
ActUpdateURI string
ActSubjectURI string
ActProtocolURI string
ActOnlineByTypeURL string
ActLikeURI string
}
// New init dao
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
client: httpx.NewClient(c.HTTPClient.Normal),
ActAllListURI: c.Host.Activity + _activityAllList,
ActUpdateURI: c.Host.Act + _activityUpdate,
ActSubjectURI: c.Host.Activity + _activitySubject,
ActProtocolURI: c.Host.Act + _activityProtocol,
ActOnlineByTypeURL: c.Host.Activity + _actOnlineByTypeURI,
ActLikeURI: c.Host.Activity + _actLike,
}
return
}
// MissionOnlineByTid fn
func (d *Dao) MissionOnlineByTid(c context.Context, tid, plat int16) (mm []*activity.ActWithTP, err error) {
var res struct {
Code int `json:"code"`
Data []*activity.ActWithTP `json:"data"`
}
mm = make([]*activity.ActWithTP, 0)
params := url.Values{}
params.Set("type", strconv.Itoa(int(tid)))
params.Set("plat", strconv.Itoa(int(plat)))
if err = d.client.Get(c, d.ActOnlineByTypeURL, "", params, &res); err != nil {
log.Error("videoup ActOnlineByTypeURL error(%v) | ActOnlineByTypeURL(%s)", err, d.ActOnlineByTypeURL+"?"+params.Encode())
err = ecode.CreativeActivityErr
return
}
if res.Code != 0 {
log.Error("videoup ActOnlineByTypeURL res.Code nq zero error(%v) | ActOnlineByTypeURL(%s) res(%v)", res.Code, d.ActOnlineByTypeURL+"?"+params.Encode(), res)
err = ecode.CreativeActivityErr
return
}
for _, m := range res.Data {
miss := &activity.ActWithTP{
ID: m.ID,
Name: m.Name,
Hot: m.Hot,
Protocol: m.Protocol,
Types: m.Types,
}
if len(m.Tags) > 0 {
miss.Tags = strings.Split(m.Tags, ",")[0]
} else {
miss.Tags = m.Name
}
if m.Type == 16 && len(m.ActURL) == 0 {
miss.ActURL = _actURLType16 + strconv.FormatInt(miss.ID, 10)
} else {
miss.ActURL = m.ActURL
}
mm = append(mm, miss)
}
return
}
// Activities get activity list.
func (d *Dao) Activities(c context.Context) (act []*activity.Activity, err error) {
var (
url string
res struct {
Code int `json:"code"`
Data []*activity.Activity `json:"data"`
}
)
url = d.ActAllListURI
if err = d.client.Get(c, url, "", nil, &res); err != nil {
log.Error("ActivityList url(%s) response(%v) error(%v)", url, res, err)
err = ecode.CreativeActivityErr
return
}
if res.Code != 0 {
log.Error("ActivityList url(%s) res(%v)", url, res)
err = ecode.CreativeActivityErr
return
}
for _, v := range res.Data {
if v.Type == 16 && len(v.ActURL) == 0 {
v.ActURL = _actURLType16 + strconv.FormatInt(v.ID, 10)
}
}
act = res.Data
return
}
// Unbind update the aid a status of this activity
func (d *Dao) Unbind(c context.Context, aid, missionID int64, ip string) (err error) {
params := url.Values{}
params.Set("mission_id", strconv.FormatInt(missionID, 10))
params.Set("aid", strconv.FormatInt(aid, 10))
params.Set("state", "-1")
ms := json.RawMessage{}
if err = d.client.RESTfulPost(c, d.ActUpdateURI, ip, params, &ms, missionID); err != nil {
log.Error("ActUpdateURI url(%s) missionID(%d) error(%v)", d.ActUpdateURI, missionID, err)
err = ecode.CreativeActivityErr
return
}
log.Info("d.UpdateByAid url(%s) params(%s) res(%s)", d.ActUpdateURI, params.Encode(), string(ms))
return
}
//Subject get any exist activity by missionID
func (d *Dao) Subject(c context.Context, missionID int64) (sub *activity.Activity, err error) {
var res struct {
Code int `json:"code"`
Data *activity.Subject `json:"data"`
}
if err = d.client.RESTfulGet(c, d.ActSubjectURI, "", url.Values{}, &res, missionID); err != nil {
log.Error("ActSubjectURI url(%s) missionID(%d) error(%v)", d.ActSubjectURI, missionID, err)
err = ecode.CreativeActivityErr
return
}
if res.Code != 0 {
log.Error("ActSubjectURI url(%s) res(%v)", d.ActSubjectURI, res)
err = ecode.CreativeActivityErr
return
}
var ID int
if ID, err = strconv.Atoi(res.Data.ID); err != nil {
log.Error("ActSubjectURI url(%s) res(%v)", d.ActSubjectURI, res)
err = ecode.CreativeActivityErr
return
}
sub = &activity.Activity{
Name: res.Data.Name,
ID: int64(ID),
}
return
}
// Protocol fn
func (d *Dao) Protocol(c context.Context, missionID int64) (p *activity.Protocol, err error) {
var res struct {
Code int `json:"code"`
Data *activity.Protocol `json:"data"`
}
if err = d.client.RESTfulGet(c, d.ActProtocolURI, "", url.Values{}, &res, missionID); err != nil {
log.Error("ActProtocolURI url(%s) missionID(%d) error(%v)", d.ActProtocolURI, missionID, err)
err = ecode.CreativeActivityErr
return
}
if res.Code != 0 {
log.Error("ActProtocolURI url(%s) res(%v)", d.ActProtocolURI, res)
err = ecode.CreativeActivityErr
return
}
p = res.Data
return
}
//Likes fn
func (d *Dao) Likes(c context.Context, missionID int64) (likeCnt int, err error) {
var res struct {
Code int `json:"code"`
Data *activity.Like `json:"data"`
}
if err = d.client.RESTfulGet(c, d.ActLikeURI, "", url.Values{}, &res, missionID); err != nil {
log.Error("ActLikeURI url(%s) missionID(%d) error(%v)", d.ActLikeURI, missionID, err)
err = ecode.CreativeActivityErr
return
}
if res.Code != 0 {
log.Error("ActLikeURI url(%s) res(%v)", d.ActLikeURI, res)
err = ecode.CreativeActivityErr
return
}
if res.Data != nil {
likeCnt = res.Data.Count
}
return
}

View File

@@ -0,0 +1,203 @@
package activity
import (
"context"
"flag"
"fmt"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/model/activity"
"os"
"strings"
"testing"
"github.com/smartystreets/goconvey/convey"
gock "gopkg.in/h2non/gock.v1"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.creative")
flag.Set("conf_token", "96b6a6c10bb311e894c14a552f48fef8")
flag.Set("tree_id", "2305")
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/creative.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
m.Run()
os.Exit(0)
}
func httpMock(method, url string) *gock.Request {
r := gock.New(url)
r.Method = strings.ToUpper(method)
d.client.SetTransport(gock.DefaultTransport)
return r
}
func Test_Likes(t *testing.T) {
var (
c = context.TODO()
err error
missionID = int64(10364)
likeCnt int
)
convey.Convey("Likes", t, func(ctx convey.C) {
defer gock.OffAll()
url := fmt.Sprintf(d.ActLikeURI, 10364)
httpMock("GET", url).Reply(200).JSON(`{"code":0,"data":{"id":53,"mid":27515310,"uname":"1qs314567","state":2,"type":2,"position":4,"url":"http://i0.hdslb.com/bfs/article/578a61e7caf47b5deaa80940b2806f1d9ce53dde.png","md5":"79d02f08c2b7b0d2b30a6b6a4f61c97e","info":"{\"width\":325,\"height\":50}","ctime":1499764110,"mtime":1499828335},"message":"","ttl":1}`)
likeCnt, err = d.Likes(c, missionID)
ctx.Convey("Then err should be nil.has should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(likeCnt, convey.ShouldBeGreaterThanOrEqualTo, 0)
})
})
}
func Test_Protocol(t *testing.T) {
var (
c = context.TODO()
err error
missionID = int64(10364)
p *activity.Protocol
)
convey.Convey("Protocol", t, func(ctx convey.C) {
defer gock.OffAll()
url := fmt.Sprintf(d.ActProtocolURI, 10364)
httpMock("GET", url).Reply(200).JSON(`{"code":0,"data":{"id":"231","sid":"10364","protocol":"说明不超过201234567890123","types":"","tags":"","hot":"0","bgm_id":"0","paster_id":"0","oids":"","screen_set":"1"}}`)
p, err = d.Protocol(c, missionID)
ctx.Convey("Then err should be nil.has should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p, convey.ShouldNotBeNil)
})
})
}
func Test_Subject(t *testing.T) {
var (
c = context.TODO()
err error
missionID = int64(10364)
act *activity.Activity
)
convey.Convey("Subject", t, func(ctx convey.C) {
defer gock.OffAll()
url := fmt.Sprintf(d.ActSubjectURI, 10364)
httpMock("GET", url).Reply(200).JSON(`{"code":0,"data":{"id":"231","sid":"10364","Subject":"说明不超过201234567890123","types":"","tags":"","hot":"0","bgm_id":"0","paster_id":"0","oids":"","screen_set":"1"}}`)
act, err = d.Subject(c, missionID)
ctx.Convey("Then err should be nil.has should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(act, convey.ShouldNotBeNil)
})
})
}
func Test_Activities(t *testing.T) {
var (
c = context.TODO()
err error
acts []*activity.Activity
)
convey.Convey("Activities", t, func(ctx convey.C) {
defer gock.OffAll()
url := d.ActAllListURI
httpMock("GET", url).Reply(200).JSON(`{"code":0,"data":[{"id":10329,"oid":0,"type":4,"state":1,"stime":"2018-10-14 14:32:00","etime":"2018-12-17 00:00:00","ctime":"2018-08-30 18:03:30","mtime":"2018-10-17 18:27:44","name":"这是一个标题123kkkk有点长有点长可能展示不下只能展示13个字","author":"jinchenchen","act_url":"","lstime":"2018-09-08 00:00:00","letime":"2018-12-01 00:00:00","cover":"//uat-i0.hdslb.com/bfs/test/static/20181017/fb8f33d1a41042b9a1ebb515fdc19d94/nBljdwyCo.jpg","dic":"sdf","flag":"33","uetime":"0000-00-00 00:00:00","ustime":"0000-00-00 00:00:00","level":"0","h5_cover":"","rank":"123","like_limit":"1","android_url":"","ios_url":"","fan_limit_max":"0","fan_limit_min":"0","tags":"","hot":0,"bgm_id":123,"paster_id":123,"oids":"10110549|10110164|10110536|10110546","screen_set":1,"protocol":"活动说明123MMMMM展示展示只能展示20个展示不下显示"}]}`)
acts, err = d.Activities(c)
ctx.Convey("Then err should be nil.has should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(acts, convey.ShouldNotBeNil)
})
})
}
func Test_MissionOnlineByTid(t *testing.T) {
var (
c = context.TODO()
err error
tid = int16(160)
plat = int16(1)
mm []*activity.ActWithTP
)
convey.Convey("MissionOnlineByTid", t, func(ctx convey.C) {
defer gock.OffAll()
url := d.ActOnlineByTypeURL
httpMock("GET", url).Reply(200).JSON(`
{
"code": 0,
"data": [
{
"id": 10329,
"oid": 0,
"type": 4,
"state": 1,
"stime": "2018-10-14 14:32:00",
"etime": "2018-12-17 00:00:00",
"ctime": "2018-08-30 18:03:30",
"mtime": "2018-10-17 18:27:44",
"name": "这是一个",
"author": "jinchenchen",
"act_url": "",
"lstime": "2018-09-08 00:00:00",
"letime": "2018-12-01 00:00:00",
"cover": "//uat-i0.hdslb.com/bfs/test/static/20181017/fb8f33d1a41042b9a1ebb515fdc19d94/nBljdwyCo.jpg",
"dic": "sdf",
"flag": "33",
"uetime": "0000-00-00 00:00:00",
"ustime": "0000-00-00 00:00:00",
"level": "0",
"h5_cover": "",
"rank": "123",
"like_limit": "1",
"android_url": "",
"ios_url": "",
"fan_limit_max": "0",
"fan_limit_min": "0",
"tags": "",
"types": "",
"hot": 0,
"bgm_id": 123,
"paster_id": 123,
"oids": "10110549|10110164|10110536|10110546",
"screen_set": 1,
"protocol": "活动说明"
}
]
}
`)
mm, err = d.MissionOnlineByTid(c, tid, plat)
ctx.Convey("Then err should be nil.has should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(mm, convey.ShouldNotBeNil)
})
})
}
func Test_Unbind(t *testing.T) {
var (
c = context.TODO()
err error
missionID = int64(10364)
aid = int64(10110788)
ip = "127.0.0.1"
)
convey.Convey("Unbind", t, func(ctx convey.C) {
defer gock.OffAll()
url := fmt.Sprintf(d.ActUpdateURI, 10364)
httpMock("POST", url).Reply(200).JSON(`{"code":0,"data":""}`)
err = d.Unbind(c, aid, missionID, ip)
ctx.Convey("Then err should be nil.has should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}

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 = [
"app.go",
"dao.go",
],
importpath = "go-common/app/interface/main/creative/dao/app",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/app:go_default_library",
"//library/database/sql: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 = [
"app_test.go",
"dao_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/app:go_default_library",
"//library/database/sql:go_default_library",
"//vendor/github.com/bouk/monkey:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,102 @@
package app
import (
"context"
"encoding/json"
"database/sql"
"go-common/app/interface/main/creative/model/app"
"go-common/library/log"
)
const (
// select app portal
_getMulSQL = "SELECT subtitle,whiteexp,id,more,buildexp,build,compare,state,pos,title,platform,icon,url,mark,type,ctime,mtime,ptime FROM app_portal WHERE state=1 AND type=? ORDER BY pos ASC"
_addMaterialDataSQL = "INSERT INTO archive_material (aid, cid, type, data) VALUES (?,?,?,?)"
_getMaterialDataSQL = " SELECT data from archive_material where aid=? and cid=? and type=? limit 1"
)
// Portals for portal config.
func (d *Dao) Portals(c context.Context, ty int) (apt []*app.PortalMeta, err error) {
rows, err := d.db.Query(c, _getMulSQL, ty)
if err != nil {
log.Error("mysqlDB.Query error(%v)", err)
return
}
defer rows.Close()
apt = make([]*app.PortalMeta, 0)
for rows.Next() {
a := &app.PortalMeta{
BuildExps: make([]*app.BuildExp, 0),
WhiteExps: make([]*app.WhiteExp, 0),
}
var (
buildExpJSON json.RawMessage
whiteExpJSON json.RawMessage
)
if err = rows.Scan(
&a.SubTitle,
&whiteExpJSON,
&a.ID,
&a.More,
&buildExpJSON,
&a.Build,
&a.Compare,
&a.State,
&a.Pos,
&a.Title,
&a.Platform,
&a.Icon,
&a.URL,
&a.Mark,
&a.Type,
&a.CTime,
&a.MTime,
&a.PTime,
); err != nil {
log.Error("row.Scan error(%v)", err)
return
}
if len(buildExpJSON) > 0 {
var buildExps []*app.BuildExp
if err = json.Unmarshal([]byte(buildExpJSON), &buildExps); err != nil {
log.Error("json.Unmarshal buildExps failed error(%v)", err)
continue
}
a.BuildExps = buildExps
}
if len(whiteExpJSON) > 0 {
var whiteExps []*app.WhiteExp
if err = json.Unmarshal([]byte(whiteExpJSON), &whiteExps); err != nil {
log.Error("json.Unmarshal whiteExps failed error(%v)", err)
continue
}
a.WhiteExps = whiteExps
}
apt = append(apt, a)
}
return
}
// AddMaterialData fn
func (d *Dao) AddMaterialData(c context.Context, data *app.EditorData) (err error) {
_, err = d.db.Exec(c, _addMaterialDataSQL, data.AID, data.CID, data.Type, data.Data)
if err != nil {
log.Error("d.db.Exec error(%v)", err)
return
}
return
}
// GetMaterialData fn
func (d *Dao) GetMaterialData(c context.Context, data *app.EditorData) (dt []byte, err error) {
row := d.db.QueryRow(c, _getMaterialDataSQL, data.AID, data.CID, data.Type)
if err = row.Scan(&dt); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row scan error(%v)", err)
}
}
return
}

View File

@@ -0,0 +1,53 @@
package app
import (
"context"
"go-common/app/interface/main/creative/model/app"
xsql "go-common/library/database/sql"
"reflect"
"testing"
"database/sql"
"github.com/bouk/monkey"
"github.com/smartystreets/goconvey/convey"
)
func TestAppPortalConfig(t *testing.T) {
var (
c = context.TODO()
ty = int(0)
)
convey.Convey("Portals", t, func(ctx convey.C) {
apt, err := d.Portals(c, ty)
ctx.Convey("Then err should be nil.apt should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(apt, convey.ShouldNotBeNil)
})
})
}
func TestAppAddMaterialData(t *testing.T) {
var (
c = context.TODO()
aid = int64(10110788)
cid = int64(10134702)
err error
)
data := &app.EditorData{
CID: cid,
AID: aid,
Type: 3,
Data: "999",
}
convey.Convey("AddMaterialData", t, func(ctx convey.C) {
guard := monkey.PatchInstanceMethod(reflect.TypeOf(d.db), "Exec", func(_ *xsql.DB, _ context.Context, _ string, _ ...interface{}) (sql.Result, error) {
return nil, sql.ErrNoRows
})
defer guard.Unpatch()
err = d.AddMaterialData(c, data)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,30 @@
package app
import (
"context"
"go-common/app/interface/main/creative/conf"
"go-common/library/database/sql"
)
// Dao define
type Dao struct {
db *sql.DB
}
// New init dao
func New(c *conf.Config) (d *Dao) {
d = &Dao{
db: sql.NewMySQL(c.DB.Creative),
}
return
}
// Ping db
func (d *Dao) Ping(c context.Context) (err error) {
return d.db.Ping(c)
}
// Close db
func (d *Dao) Close() (err error) {
return d.db.Close()
}

View File

@@ -0,0 +1,35 @@
package app
import (
"flag"
"go-common/app/interface/main/creative/conf"
"os"
"testing"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.creative")
flag.Set("conf_token", "96b6a6c10bb311e894c14a552f48fef8")
flag.Set("tree_id", "2305")
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/creative.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
m.Run()
os.Exit(0)
}

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",
"workflow.go",
],
importpath = "go-common/app/interface/main/creative/dao/appeal",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/appeal:go_default_library",
"//library/ecode: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 = [
"dao_test.go",
"workflow_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/appeal:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,39 @@
package appeal
import (
"go-common/app/interface/main/creative/conf"
httpx "go-common/library/net/http/blademaster"
)
// Dao define
type Dao struct {
// config
c *conf.Config
// http client
client *httpx.Client
// appeal list
list string
detail string
addappeal string
addreply string
appealstar string
appealstate string
appealStarInfo string
}
// New init dao
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
// http client
client: httpx.NewClient(c.HTTPClient.Normal),
list: c.Host.API + _list,
detail: c.Host.API + _detail,
addappeal: c.Host.API + _addappeal,
addreply: c.Host.API + _addreply,
appealstar: c.Host.API + _appealstar,
appealstate: c.Host.API + _appealstate,
appealStarInfo: c.Host.API + _appealStarInfo,
}
return
}

View File

@@ -0,0 +1,35 @@
package appeal
import (
"flag"
"go-common/app/interface/main/creative/conf"
"os"
"testing"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.creative")
flag.Set("conf_token", "96b6a6c10bb311e894c14a552f48fef8")
flag.Set("tree_id", "2305")
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/creative.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
m.Run()
os.Exit(0)
}

View File

@@ -0,0 +1,197 @@
package appeal
import (
"context"
"net/url"
"strconv"
"go-common/app/interface/main/creative/model/appeal"
"go-common/library/ecode"
"go-common/library/log"
"github.com/pkg/errors"
)
// appeal url
const (
_list = "/x/internal/workflow/appeal/list"
_detail = "/x/internal/workflow/appeal/info"
_addappeal = "/x/internal/workflow/appeal/add"
_addreply = "/x/internal/workflow/appeal/reply/add"
_appealstar = "/x/internal/workflow/appeal/extra/up"
_appealstate = "/x/internal/workflow/appeal/state"
_appealStarInfo = "/x/internal/workflow/appeal/extra/info"
)
// AppealList appeal list .
func (d *Dao) AppealList(c context.Context, mid int64, business int, ip string) (as []*appeal.AppealMeta, err error) {
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("business", strconv.Itoa(business))
var res struct {
Code int `json:"code"`
Data []*appeal.AppealMeta `json:"data"`
}
if err = d.client.Get(c, d.list, ip, params, &res); err != nil {
err = errors.Wrap(err, "appeal list api")
return
}
if res.Code != 0 {
log.Error("appeal list url(%s) mid(%d) res(%v)", d.list+"?"+params.Encode(), mid, res)
err = ecode.Int(res.Code)
return
}
as = res.Data
return
}
// AppealDetail appeal detail.
func (d *Dao) AppealDetail(c context.Context, mid, id int64, business int, ip string) (a *appeal.AppealMeta, err error) {
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("id", strconv.FormatInt(id, 10))
params.Set("business", strconv.Itoa(business))
var res struct {
Code int `json:"code"`
Data *appeal.AppealMeta `json:"data"`
}
if err = d.client.Get(c, d.detail, ip, params, &res); err != nil {
err = errors.Wrap(err, "appeal api")
return
}
if res.Code != 0 {
log.Error("appeal url(%s) mid(%d) res(%v)", d.detail+"?"+params.Encode(), mid, res)
err = ecode.Int(res.Code)
return
}
a = res.Data
return
}
// AddAppeal add appeal.
func (d *Dao) AddAppeal(c context.Context, tid, aid, mid, business int64, qq, phone, email, desc, attachments, ip string, ap *appeal.BusinessAppeal) (apID int64, err error) {
params := url.Values{}
params.Set("tid", strconv.FormatInt(tid, 10))
params.Set("oid", strconv.FormatInt(aid, 10))
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("business", strconv.FormatInt(business, 10))
params.Set("qq", qq)
params.Set("phone", phone)
params.Set("email", email)
params.Set("description", desc)
params.Set("attachments", attachments)
params.Set("business_typeid", strconv.FormatInt(ap.BusinessTypeID, 10))
params.Set("business_mid", strconv.FormatInt(ap.BusinessMID, 10))
params.Set("business_title", ap.BusinessTitle)
params.Set("business_content", ap.BusinessContent)
params.Set("business_state", strconv.FormatInt(appeal.StateCreate, 10))
var res struct {
Code int `json:"code"`
Data struct {
ChallengeNo int64 `json:"challengeNo"`
} `json:"data"`
}
log.Info("AddAppeal params(%v)", params)
if err = d.client.Post(c, d.addappeal, ip, params, &res); err != nil {
err = errors.Wrap(err, "appeal api")
return
}
if res.Code != 0 {
log.Error("add appeal url(%s) mid(%d) res(%v)", d.addappeal+"?"+params.Encode(), mid, res)
err = ecode.Int(res.Code)
}
apID = res.Data.ChallengeNo
return
}
// AddReply add appeal reply .
func (d *Dao) AddReply(c context.Context, cid, event int64, content, attachments, ip string) (err error) {
params := url.Values{}
params.Set("cid", strconv.FormatInt(cid, 10))
params.Set("content", content)
params.Set("attachments", attachments)
params.Set("event", strconv.FormatInt(event, 10))
var res struct {
Code int `json:"code"`
}
if err = d.client.Post(c, d.addreply, ip, params, &res); err != nil {
err = errors.Wrap(err, "appeal reply api")
return
}
if res.Code != 0 {
log.Error("add appeal url(%s) res(%v)", d.addreply+"?"+params.Encode(), res)
err = ecode.Int(res.Code)
}
return
}
// AppealExtra modify appeal extra.
func (d *Dao) AppealExtra(c context.Context, mid, cid, business, val int64, key, ip string) (err error) {
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("cid", strconv.FormatInt(cid, 10))
params.Set("business", strconv.FormatInt(business, 10))
params.Set("key", key)
params.Set("val", strconv.FormatInt(val, 10))
var res struct {
Code int `json:"code"`
}
log.Info("AppealExtra params(%v)", params)
if err = d.client.Post(c, d.appealstar, ip, params, &res); err != nil {
err = errors.Wrap(err, "appeal star api")
return
}
if res.Code != 0 {
log.Error("appeal start url(%s) res(%v)", d.appealstar+"?"+params.Encode(), res)
err = ecode.Int(res.Code)
}
return
}
// AppealState modify appeal state .
func (d *Dao) AppealState(c context.Context, mid, id, business, state int64, ip string) (err error) {
params := url.Values{}
params.Set("id", strconv.FormatInt(id, 10))
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("business", strconv.FormatInt(business, 10))
params.Set("business_state", strconv.FormatInt(state, 10))
var res struct {
Code int `json:"code"`
}
if err = d.client.Post(c, d.appealstate, ip, params, &res); err != nil {
err = errors.Wrap(err, "appeal state api")
return
}
if res.Code != 0 {
log.Error("appeal state url(%s) res(%v)", d.appealstate+"?"+params.Encode(), res)
err = ecode.Int(res.Code)
}
return
}
// AppealStarInfo appeal star detail.
func (d *Dao) AppealStarInfo(c context.Context, mid, cid int64, business int, ip string) (star, etime string, err error) {
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("cid", strconv.FormatInt(cid, 10))
params.Set("business", strconv.Itoa(business))
var res struct {
Code int `json:"code"`
Data struct {
Star string `json:"star"`
ETime string `json:"etime"`
} `json:"data"`
}
if err = d.client.Get(c, d.appealStarInfo, ip, params, &res); err != nil {
err = errors.Wrap(err, "appeal api")
return
}
if res.Code != 0 {
log.Error("appeal url(%s) mid(%d) res(%v)", d.detail+"?"+params.Encode(), mid, res)
err = ecode.Int(res.Code)
return
}
star = res.Data.Star
etime = res.Data.ETime
return
}

View File

@@ -0,0 +1,136 @@
package appeal
import (
"context"
"go-common/app/interface/main/creative/model/appeal"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestAppealAppealList(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
business = int(0)
ip = ""
)
convey.Convey("AppealList", t, func(ctx convey.C) {
as, err := d.AppealList(c, mid, business, ip)
ctx.Convey("Then err should be nil.as should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(as, convey.ShouldNotBeNil)
})
})
}
func TestAppealAppealDetail(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
id = int64(0)
business = int(0)
ip = ""
)
convey.Convey("AppealDetail", t, func(ctx convey.C) {
a, err := d.AppealDetail(c, mid, id, business, ip)
ctx.Convey("Then err should be nil.a should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(a, convey.ShouldNotBeNil)
})
})
}
func TestAppealAddAppeal(t *testing.T) {
var (
c = context.TODO()
tid = int64(0)
aid = int64(0)
mid = int64(0)
business = int64(0)
qq = ""
phone = ""
email = ""
desc = ""
attachments = ""
ip = ""
ap = &appeal.BusinessAppeal{}
)
convey.Convey("AddAppeal", t, func(ctx convey.C) {
apID, err := d.AddAppeal(c, tid, aid, mid, business, qq, phone, email, desc, attachments, ip, ap)
ctx.Convey("Then err should be nil.apID should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(apID, convey.ShouldNotBeNil)
})
})
}
func TestAppealAddReply(t *testing.T) {
var (
c = context.TODO()
cid = int64(0)
event = int64(0)
content = ""
attachments = ""
ip = ""
)
convey.Convey("AddReply", t, func(ctx convey.C) {
err := d.AddReply(c, cid, event, content, attachments, ip)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestAppealAppealExtra(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
cid = int64(0)
business = int64(0)
val = int64(0)
key = ""
ip = ""
)
convey.Convey("AppealExtra", t, func(ctx convey.C) {
err := d.AppealExtra(c, mid, cid, business, val, key, ip)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestAppealAppealState(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
id = int64(0)
business = int64(0)
state = int64(0)
ip = ""
)
convey.Convey("AppealState", t, func(ctx convey.C) {
err := d.AppealState(c, mid, id, business, state, ip)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestAppealAppealStarInfo(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
cid = int64(0)
business = int(0)
ip = ""
)
convey.Convey("AppealStarInfo", t, func(ctx convey.C) {
star, etime, err := d.AppealStarInfo(c, mid, cid, business, ip)
ctx.Convey("Then err should be nil.star,etime should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(etime, convey.ShouldNotBeNil)
ctx.So(star, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,95 @@
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",
"biz_test.go",
"dao_test.go",
"fav_test.go",
"history_test.go",
"memcache_test.go",
"music_test.go",
"netsafe_test.go",
"porder_test.go",
"rpc_test.go",
"staff_test.go",
"viewpoint_test.go",
],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/archive:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/cache/redis:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode: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",
"biz.go",
"dao.cache.go",
"dao.go",
"fav.go",
"history.go",
"mc.cache.go",
"memcache.go",
"music.go",
"netsafe.go",
"porder.go",
"rpc.go",
"staff.go",
"viewpoint.go",
],
importpath = "go-common/app/interface/main/creative/dao/archive",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/dao/tool:go_default_library",
"//app/interface/main/creative/model/archive:go_default_library",
"//app/interface/main/creative/model/music:go_default_library",
"//app/service/main/archive/api:go_default_library",
"//app/service/main/archive/api/gorpc:go_default_library",
"//app/service/main/archive/model/archive:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/cache/redis:go_default_library",
"//library/database/sql: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/stat/prom:go_default_library",
"//library/sync/pipeline/fanout:go_default_library",
"//library/xstr:go_default_library",
"//vendor/golang.org/x/sync/singleflight: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,390 @@
package archive
import (
"context"
"fmt"
"net/http"
"net/url"
"sort"
"strconv"
"strings"
"time"
"go-common/app/interface/main/creative/conf"
"go-common/app/interface/main/creative/dao/tool"
"go-common/app/interface/main/creative/model/archive"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/xstr"
)
const (
_view = "/videoup/view"
_views = "/videoup/views"
_del = "/videoup/del"
_video = "/videoup/cid"
_archives = "/videoup/up/archives"
_descFormat = "/videoup/desc/format"
_simpleVideos = "/videoup/simplevideos"
_simpleArchive = "/videoup/simplearchive"
_videoJam = "/videoup/video/jam"
_upSpecial = "/x/internal/uper/special"
_flowjudge = "/videoup/flow/list/judge"
_staffApplies = "/videoup/staff/apply/filter"
_staffApply = "/videoup/staff/apply/submit"
_staffCheck = "/videoup/staff/mid/applys"
)
// SimpleArchive fn
func (d *Dao) SimpleArchive(c context.Context, aid int64, ip string) (sa *archive.SpArchive, err error) {
params := url.Values{}
params.Set("aid", strconv.FormatInt(aid, 10))
var res struct {
Code int `json:"code"`
Data *archive.SpArchive `json:"data"`
}
if err = d.client.Get(c, d.simpleArchive, ip, params, &res); err != nil {
log.Error("archive.simpleArchive url(%s) mid(%d) error(%v)", d.simpleArchive+"?"+params.Encode(), aid, err)
err = ecode.CreativeArchiveAPIErr
return
}
if res.Code != 0 {
log.Error("archive.simpleArchive url(%s) mid(%d) res(%v)", d.simpleArchive+"?"+params.Encode(), aid, res)
err = ecode.Int(res.Code)
return
}
if res.Data == nil {
log.Error("archive.simpleArchive url(%s) aid(%d) res(%v)", d.simpleVideos+"?"+params.Encode(), aid, res)
return
}
sa = res.Data
return
}
// SimpleVideos fn
func (d *Dao) SimpleVideos(c context.Context, aid int64, ip string) (vs []*archive.SpVideo, err error) {
params := url.Values{}
params.Set("aid", strconv.FormatInt(aid, 10))
var res struct {
Code int `json:"code"`
Data []*archive.SpVideo `json:"data"`
}
if err = d.client.Get(c, d.simpleVideos, ip, params, &res); err != nil {
log.Error("archive.simpleVideos url(%s) mid(%d) error(%v)", d.simpleVideos+"?"+params.Encode(), aid, err)
err = ecode.CreativeArchiveAPIErr
return
}
if res.Code != 0 {
log.Error("archive.simpleVideos url(%s) aid(%d) res(%v)", d.simpleVideos+"?"+params.Encode(), aid, res)
err = ecode.Int(res.Code)
return
}
if res.Data == nil {
log.Error("archive.simpleVideos url(%s) aid(%d) res(%v)", d.simpleVideos+"?"+params.Encode(), aid, res)
return
}
vs = res.Data
sort.Slice(vs, func(i, j int) bool {
return vs[i].Index <= vs[j].Index
})
return
}
// View get archive
func (d *Dao) View(c context.Context, mid, aid int64, ip string, needPOI, needVote int) (av *archive.ArcVideo, err error) {
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("aid", strconv.FormatInt(aid, 10))
params.Set("need_poi", strconv.Itoa(needPOI))
params.Set("need_vote", strconv.Itoa(needVote))
var res struct {
Code int `json:"code"`
Data *archive.ArcVideo `json:"data"`
}
if err = d.client.Get(c, d.view, ip, params, &res); err != nil {
log.Error("archive.view url(%s) mid(%d) error(%v)", d.view+"?"+params.Encode(), mid, err)
err = ecode.CreativeArchiveAPIErr
return
}
if res.Code != 0 {
log.Error("archive.view url(%s) mid(%d) res(%v)", d.view+"?"+params.Encode(), mid, res)
err = ecode.Int(res.Code)
return
}
if res.Data.Archive == nil {
log.Error("archive.view url(%s) mid(%d) res(%v)", d.view+"?"+params.Encode(), mid, res)
return
}
if res.Data.Archive.Staffs == nil {
res.Data.Archive.Staffs = []*archive.StaffView{}
}
res.Data.Archive.StateDesc = d.c.StatDesc(int(res.Data.Archive.State))
res.Data.Archive.StatePanel = archive.StatePanel(res.Data.Archive.State)
av = res.Data
return
}
// Views get archives
func (d *Dao) Views(c context.Context, mid int64, aids []int64, ip string) (avm map[int64]*archive.ArcVideo, err error) {
params := url.Values{}
params.Set("aids", xstr.JoinInts(aids))
params.Set("mid", strconv.FormatInt(mid, 10))
var res struct {
Code int `json:"code"`
Data map[string]*archive.ArcVideo `json:"data"`
}
if err = d.client.Get(c, d.views, ip, params, &res); err != nil {
log.Error("archive.views url(%s) mid(%d) error(%v)", d.views+"?"+params.Encode(), mid, err)
err = ecode.CreativeArchiveAPIErr
return
}
if res.Code != 0 {
log.Error("archive.views url(%s) mid(%d) res(%v)", d.views+"?"+params.Encode(), mid, res)
err = ecode.Int(res.Code)
return
}
avm = map[int64]*archive.ArcVideo{}
for aidStr, av := range res.Data {
var err error
aid, err := strconv.ParseInt(aidStr, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", aidStr, err)
continue
}
av.Archive.StateDesc = d.c.StatDesc(int(av.Archive.State))
av.Archive.StatePanel = archive.StatePanel(av.Archive.State)
avm[aid] = av
}
return
}
// Del delete archive.
func (d *Dao) Del(c context.Context, mid, aid int64, ip string) (err error) {
params := url.Values{}
params.Set("appkey", conf.Conf.App.Key)
params.Set("appsecret", conf.Conf.App.Secret)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
// uri
var (
query, _ = tool.Sign(params)
uri = d.del + "?" + query
)
// new request
req, err := http.NewRequest("POST", uri, strings.NewReader(fmt.Sprintf(`{"mid":%d,"aid":%d}`, mid, aid)))
if err != nil {
log.Error("http.NewRequest(%s) error(%v); mid(%d), aid(%d), ip(%s)", d.del, err, mid, aid, ip)
err = ecode.CreativeArchiveAPIErr
return
}
req.Header.Set("X-BACKEND-BILI-REAL-IP", ip)
var res struct {
Code int `json:"code"`
}
if err = d.client.Do(c, req, &res); err != nil {
log.Error("d.client.Do(%s) error(%v); mid(%d), aid(%d), ip(%s)", d.del, err, mid, aid, ip)
err = ecode.CreativeArchiveAPIErr
return
}
if res.Code != 0 {
err = ecode.Int(res.Code)
log.Error("del archive url(%s) res(%v); mid(%d), aid(%d), ip(%s)", d.del, res, mid, aid, ip)
return
}
return
}
// VideoByCid get videos by cids.
func (d *Dao) VideoByCid(c context.Context, cid int64, ip string) (v *archive.Video, err error) {
params := url.Values{}
params.Set("cid", strconv.FormatInt(cid, 10))
var res struct {
Code int `json:"code"`
Data *archive.Video `json:"data"`
}
if err = d.client.Get(c, d.video, ip, params, &res); err != nil {
log.Error("VideoByCid cidURI(%s) error(%v)", d.video+"?"+params.Encode(), err)
return
}
if res.Code != 0 {
err = ecode.Int(res.Code)
log.Error("VideoByCid cidURI(%s) Code=(%d)", d.video+"?"+params.Encode(), res.Code)
return
}
v = res.Data
return
}
// UpArchives get archives by mid.
func (d *Dao) UpArchives(c context.Context, mid, pn, ps, group int64, ip string) (aids []int64, count int64, err error) {
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("pn", strconv.FormatInt(pn, 10))
params.Set("ps", strconv.FormatInt(ps, 10))
params.Set("group", strconv.FormatInt(mid, 10)) //0:全部稿件1:开放稿件2:未开放稿件
var res struct {
Code int `json:"code"`
Data struct {
Aids []int64 `json:"aids"`
Count int64 `json:"count"`
} `json:"data"`
}
if err = d.client.Get(c, d.upArchives, ip, params, &res); err != nil {
log.Error("upArchives URI(%s) error(%v)", d.upArchives+"?"+params.Encode(), err)
err = ecode.CreativeArchiveAPIErr
return
}
if res.Code != 0 {
log.Error("upArchives URI(%s) Code=(%d)", d.upArchives+"?"+params.Encode(), res.Code)
err = ecode.Int(res.Code)
return
}
aids = res.Data.Aids
count = res.Data.Count
return
}
// DescFormat get desc format by typeid and copyright
func (d *Dao) DescFormat(c context.Context) (descs []*archive.DescFormat, err error) {
params := url.Values{}
var res struct {
Code int `json:"code"`
Message string `json:"message"`
Data []*archive.DescFormat `json:"data"`
}
descs = []*archive.DescFormat{}
if err = d.client.Get(c, d.descFormat, "", params, &res); err != nil {
log.Error("videoup descFormat error(%v) | descFormat(%s) params(%v)", err, d.descFormat+"?"+params.Encode(), params)
err = ecode.CreativeArchiveAPIErr
return
}
if res.Code != 0 {
log.Error("videoup descFormat res.Code(%d) | descFormat(%s)params(%v) res(%v)", res.Code, d.descFormat+"?"+params.Encode(), params, res)
err = ecode.Int(res.Code)
return
}
descs = res.Data
log.Info("res.Code(%d) descFormat(%s) params(%v)", res.Code, d.descFormat+"?"+params.Encode(), params)
return
}
// VideoJam get video-check traffic jam level
func (d *Dao) VideoJam(c context.Context, ip string) (level int8, err error) {
params := url.Values{}
var res struct {
Code int `json:"code"`
Data *struct {
Level int8 `json:"level"`
} `json:"data"`
}
if err = d.client.Get(c, d.videoJam, ip, params, &res); err != nil {
log.Error("archive.VideoJam url(%s) error(%v)", d.videoJam+"?"+params.Encode(), err)
err = ecode.CreativeArchiveAPIErr
return
}
if res.Code != 0 {
log.Error("archive.VideoJam url(%s) res(%v)", d.videoJam+"?"+params.Encode(), res)
err = ecode.Int(res.Code)
return
}
if res.Data == nil {
log.Error("archive.VideoJam url(%s) res(%v)", d.videoJam+"?"+params.Encode(), res)
return
}
level = res.Data.Level
return
}
// FlowJudge fn
func (d *Dao) FlowJudge(c context.Context, business, groupID int64, oids []int64) (hitOids []int64, err error) {
params := url.Values{}
params.Set("business", strconv.FormatInt(business, 10))
params.Set("gid", strconv.FormatInt(groupID, 10))
params.Set("oids", xstr.JoinInts(oids))
var res struct {
Code int `json:"code"`
Message string `json:"message"`
Data []int64 `json:"data"`
}
if err = d.client.Get(c, d.flowJudge, "", params, &res); err != nil {
log.Error("archive.FlowJudge url(%s) error(%v)", d.upSpecialURL+"?"+params.Encode(), err)
return
}
if res.Code != 0 {
log.Error("FlowJudge api url(%s) res(%v) code(%d)", d.upSpecialURL, res, res.Code)
err = ecode.CreativeArchiveAPIErr
return
}
hitOids = res.Data
return
}
// StaffApplies fn
func (d *Dao) StaffApplies(c context.Context, staffMid int64, aids []int64) (apply []*archive.StaffApply, err error) {
params := url.Values{}
params.Set("mid", strconv.FormatInt(staffMid, 10))
params.Set("aids", xstr.JoinInts(aids))
var res struct {
Code int `json:"code"`
Message string `json:"message"`
Data []*archive.StaffApply `json:"data"`
}
if err = d.client.Get(c, d.staffApplies, "", params, &res); err != nil {
log.Error("archive.staffApplies url(%s) error(%v)", d.staffApplies+"?"+params.Encode(), err)
return
}
if res.Code != 0 {
log.Error("staffApplies api url(%s) res(%v) code(%d)", d.staffApplies, res, res.Code)
err = ecode.CreativeArchiveAPIErr
return
}
apply = res.Data
return
}
// StaffMidValidate fn
func (d *Dao) StaffMidValidate(c context.Context, mid int64) (data int, err error) {
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
var res struct {
Code int `json:"code"`
Message string `json:"message"`
Data int `json:"data"`
}
if err = d.client.Get(c, d.staffCheck, "", params, &res); err != nil {
log.Error("archive.StaffMidValidate url(%s) error(%v)", d.staffCheck+"?"+params.Encode(), err)
return
}
if res.Code != 0 {
log.Error("StaffMidValidate api url(%s) res(%v) code(%d)", d.staffCheck, res, res.Code)
err = ecode.Int(res.Code)
return
}
data = res.Data
return
}
// StaffApplySubmit fn
func (d *Dao) StaffApplySubmit(c context.Context, id, aid, mid, state, atype int64, flagAddBlack, flagRefuse int) (err error) {
params := url.Values{}
params.Set("id", strconv.FormatInt(id, 10))
params.Set("state", strconv.FormatInt(state, 10))
params.Set("type", strconv.FormatInt(atype, 10))
params.Set("apply_aid", strconv.FormatInt(aid, 10))
params.Set("apply_staff_mid", strconv.FormatInt(mid, 10))
params.Set("flag_add_black", strconv.Itoa(flagAddBlack))
params.Set("flag_refuse", strconv.Itoa(flagRefuse))
var res struct {
Code int `json:"code"`
Message string `json:"message"`
}
if err = d.client.Post(c, d.staffApply, "", params, &res); err != nil {
log.Error("archive.StaffApplySubmit url(%s) error(%v)", d.staffApply+"?"+params.Encode(), err)
return
}
if res.Code != 0 {
log.Error("StaffApplySubmit api url(%s) res(%v) code(%d)", d.staffApply, res, res.Code)
err = ecode.Int(res.Code)
return
}
return
}

View File

@@ -0,0 +1,256 @@
package archive
import (
"context"
"encoding/json"
"go-common/app/interface/main/creative/model/archive"
"go-common/library/ecode"
"testing"
"github.com/smartystreets/goconvey/convey"
gock "gopkg.in/h2non/gock.v1"
)
func TestFlowJudge(t *testing.T) {
var (
c = context.TODO()
err error
business = int64(1)
groupID = int64(2)
oids = []int64{1, 2, 3}
hitOids []int64
)
convey.Convey("FlowJudge", t, func(ctx convey.C) {
defer gock.OffAll()
httpMock("GET", d.flowJudge).Reply(200).JSON(`{"code":20001}`)
hitOids, err = d.FlowJudge(c, business, groupID, oids)
ctx.Convey("Then err should be nil.hitOids should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(hitOids, convey.ShouldBeNil)
})
})
}
func TestArchiveSimpleArchive(t *testing.T) {
var (
c = context.TODO()
aid = int64(10110817)
ip = "127.0.0.1"
err error
sa *archive.SpArchive
res struct {
Code int `json:"code"`
Data *archive.SpArchive `json:"data"`
}
)
convey.Convey("4", t, func(ctx convey.C) {
defer gock.OffAll()
httpMock("GET", d.simpleArchive).Reply(-502)
sa, err = d.SimpleArchive(c, aid, ip)
ctx.Convey("Then err should be nil.sa should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(err, convey.ShouldEqual, ecode.CreativeArchiveAPIErr)
ctx.So(sa, convey.ShouldBeNil)
})
})
convey.Convey("1", t, func(ctx convey.C) {
defer gock.OffAll()
httpMock("GET", d.simpleArchive).Reply(200).JSON(`{"code":20001}`)
sa, err = d.SimpleArchive(c, aid, ip)
ctx.Convey("Then err should be nil.sa should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(err, convey.ShouldEqual, ecode.CreativeArchiveAPIErr)
ctx.So(sa, convey.ShouldBeNil)
})
})
convey.Convey("2", t, func(ctx convey.C) {
res.Code = 0
res.Data = &archive.SpArchive{
Aid: aid,
Title: "iamtitle",
Mid: 2089809,
}
js, _ := json.Marshal(res)
defer gock.OffAll()
httpMock("GET", d.simpleArchive).Reply(200).JSON(string(js))
sa, err = d.SimpleArchive(c, aid, ip)
ctx.Convey("Then err should be nil.sa should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(sa, convey.ShouldNotBeNil)
})
})
convey.Convey("3", t, func(ctx convey.C) {
res.Code = 0
res.Data = nil
js, _ := json.Marshal(res)
defer gock.OffAll()
httpMock("GET", d.simpleArchive).Reply(200).JSON(string(js))
sa, err = d.SimpleArchive(c, aid, ip)
ctx.Convey("Then err should be nil.sa should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(sa, convey.ShouldBeNil)
})
})
}
func TestArchiveSimpleVideos(t *testing.T) {
var (
c = context.TODO()
aid = int64(10110817)
ip = "127.0.0.1"
res struct {
Code int `json:"code"`
Data []*archive.SpVideo `json:"data"`
}
)
convey.Convey("1", t, func(ctx convey.C) {
defer gock.OffAll()
js, _ := json.Marshal(res)
httpMock("GET", d.simpleVideos).Reply(200).JSON(string(js))
vs, err := d.SimpleVideos(c, aid, ip)
ctx.Convey("Then err should be nil.vs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(vs, convey.ShouldBeNil)
})
})
convey.Convey("2", t, func(ctx convey.C) {
defer gock.OffAll()
res.Code = 20001
res.Data = nil
js, _ := json.Marshal(res)
httpMock("GET", d.simpleVideos).Reply(200).JSON(string(js))
vs, err := d.SimpleVideos(c, aid, ip)
ctx.Convey("Then err should be nil.vs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(vs, convey.ShouldBeNil)
})
})
convey.Convey("3", t, func(ctx convey.C) {
defer gock.OffAll()
res.Code = 0
res.Data = append(res.Data, &archive.SpVideo{
Cid: 1,
Index: 1,
Title: "1title",
}, &archive.SpVideo{
Cid: 2,
Index: 2,
Title: "2title",
})
js, _ := json.Marshal(res)
httpMock("GET", d.simpleVideos).Reply(200).JSON(string(js))
vs, err := d.SimpleVideos(c, aid, ip)
ctx.Convey("Then err should be nil.vs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(vs, convey.ShouldNotBeNil)
})
})
}
func TestArchiveView(t *testing.T) {
var (
c = context.TODO()
mid = int64(2089809)
aid = int64(10110817)
ip = "127.0.0.1"
)
convey.Convey("View", t, func(ctx convey.C) {
av, err := d.View(c, mid, aid, ip, 0, 0)
ctx.Convey("Then err should be nil.av should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(av, convey.ShouldNotBeNil)
})
})
}
func TestArchiveViews(t *testing.T) {
var (
c = context.TODO()
mid = int64(2089809)
aids = []int64{10110817, 10110816}
ip = "127.0.0.1"
)
convey.Convey("Views", t, func(ctx convey.C) {
avm, err := d.Views(c, mid, aids, ip)
ctx.Convey("Then err should be nil.avm should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(avm, convey.ShouldNotBeNil)
})
})
}
func TestArchiveDel(t *testing.T) {
var (
c = context.TODO()
mid = int64(2089809)
aid = int64(10110817)
ip = "127.0.0.1"
)
convey.Convey("Del", t, func(ctx convey.C) {
err := d.Del(c, mid, aid, ip)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldEqual, ecode.ArchiveAlreadyDel)
})
})
}
func TestArchiveVideoByCid(t *testing.T) {
var (
c = context.TODO()
cid = int64(10134702)
ip = "127.0.0.1"
)
convey.Convey("VideoByCid", t, func(ctx convey.C) {
v, err := d.VideoByCid(c, cid, ip)
ctx.Convey("Then err should be nil.v should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(v, convey.ShouldNotBeNil)
})
})
}
func TestArchiveUpArchives(t *testing.T) {
var (
c = context.TODO()
mid = int64(2089809)
pn = int64(1)
ps = int64(10)
group = int64(0)
ip = "127.0.0.1"
)
convey.Convey("UpArchives", t, func(ctx convey.C) {
aids, count, err := d.UpArchives(c, mid, pn, ps, group, ip)
ctx.Convey("Then err should be nil.aids,count should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(count, convey.ShouldNotBeNil)
ctx.So(aids, convey.ShouldNotBeNil)
})
})
}
func TestArchiveDescFormat(t *testing.T) {
var (
c = context.TODO()
)
convey.Convey("DescFormat", t, func(ctx convey.C) {
descs, err := d.DescFormat(c)
ctx.Convey("Then err should be nil.descs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(descs, convey.ShouldNotBeNil)
})
})
}
func TestArchiveVideoJam(t *testing.T) {
var (
c = context.TODO()
ip = "127.0.0.1"
)
convey.Convey("VideoJam", t, func(ctx convey.C) {
level, err := d.VideoJam(c, ip)
ctx.Convey("Then err should be nil.level should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(level, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,34 @@
package archive
import (
"context"
"time"
model "go-common/app/interface/main/creative/model/archive"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
_bizsByTimeSQL = "SELECT aid,type,ctime FROM archive_biz WHERE mtime >= ? AND mtime < ? AND type = ? ORDER BY mtime"
)
// BIZsByTime list businesses by time and type
func (d *Dao) BIZsByTime(c context.Context, start, end *time.Time, tp int8) (bizs []*model.BIZ, err error) {
var rows *sql.Rows
if rows, err = d.db.Query(c, _bizsByTimeSQL, start, end, tp); err != nil {
log.Error("d.db.Query error(%v)", err)
return
}
defer rows.Close()
bizs = []*model.BIZ{}
for rows.Next() {
var b = new(model.BIZ)
if err = rows.Scan(&b.Aid, &b.Type, &b.Ctime); err != nil {
log.Error("row.Scan error(%v)", err)
return
}
bizs = append(bizs, b)
}
return
}

View File

@@ -0,0 +1,27 @@
package archive
import (
"context"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestArchiveBIZsByTime(t *testing.T) {
convey.Convey("BIZsByTime", t, func(ctx convey.C) {
var (
c = context.Background()
start = &time.Time{}
end = &time.Time{}
tp = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
bizs, err := d.BIZsByTime(c, start, end, tp)
ctx.Convey("Then err should be nil.bizs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(bizs, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,94 @@
// Code generated by $GOPATH/src/go-common/app/tool/cache/gen. DO NOT EDIT.
/*
Package archive is a generated cache proxy package.
It is generated from:
type _cache interface {
// cache: -singleflight=true -nullcache=[]*arcMdl.Staff{{ID:-1}} -check_null_code=len($)==1&&$[0].ID==-1
StaffData(c context.Context, aid int64) ([]*arcMdl.Staff, error)
ViewPoint(c context.Context, aid int64, cid int64) (vp *arcMdl.ViewPointRow, err error)
}
*/
package archive
import (
"context"
arcMdl "go-common/app/interface/main/creative/model/archive"
"go-common/library/net/metadata"
"go-common/library/stat/prom"
"golang.org/x/sync/singleflight"
)
var _ _cache
var cacheSingleFlights = [1]*singleflight.Group{{}}
// StaffData get data from cache if miss will call source method, then add to cache.
func (d *Dao) StaffData(c context.Context, id int64) (res []*arcMdl.Staff, err error) {
addCache := true
res, err = d.CacheStaffData(c, id)
if err != nil {
addCache = false
err = nil
}
defer func() {
if len(res) == 1 && res[0].ID == -1 {
res = nil
}
}()
if len(res) != 0 {
prom.CacheHit.Incr("StaffData")
return
}
var rr interface{}
sf := d.cacheSFStaffData(id)
rr, err, _ = cacheSingleFlights[0].Do(sf, func() (r interface{}, e error) {
prom.CacheMiss.Incr("StaffData")
r, e = d.RawStaffData(c, id)
return
})
res = rr.([]*arcMdl.Staff)
if err != nil {
return
}
miss := res
if len(miss) == 0 {
miss = []*arcMdl.Staff{{ID: -1}}
}
if !addCache {
return
}
d.cache.Do(c, func(c context.Context) {
d.AddCacheStaffData(metadata.WithContext(c), id, miss)
})
return
}
// ViewPoint cache: -singleflight=true -nullcache=[]*arcMdl.Staff{{ID:-1}} -check_null_code=len($)==1&&$[0].ID==-1
func (d *Dao) ViewPoint(c context.Context, id int64, cid int64) (res *arcMdl.ViewPointRow, err error) {
addCache := true
res, err = d.CacheViewPoint(c, id, cid)
if err != nil {
addCache = false
err = nil
}
if res != nil {
prom.CacheHit.Incr("ViewPoint")
return
}
prom.CacheMiss.Incr("ViewPoint")
res, err = d.RawViewPoint(c, id, cid)
if err != nil {
return
}
miss := res
if !addCache {
return
}
d.cache.Do(c, func(c context.Context) {
d.AddCacheViewPoint(metadata.WithContext(c), id, miss, cid)
})
return
}

View File

@@ -0,0 +1,143 @@
package archive
import (
"context"
"time"
"fmt"
"go-common/app/interface/main/creative/conf"
arcMdl "go-common/app/interface/main/creative/model/archive"
archive "go-common/app/service/main/archive/api/gorpc"
"go-common/library/cache/memcache"
"go-common/library/cache/redis"
"go-common/library/database/sql"
bm "go-common/library/net/http/blademaster"
"go-common/library/sync/pipeline/fanout"
)
// Dao is archive dao.
type Dao struct {
// config
c *conf.Config
// rpc
arc *archive.Service2
// select
client *bm.Client
// db
db *sql.DB
// mc
mc *memcache.Pool
mcExpire int32
//cache tool
cache *fanout.Fanout
// redis
redis *redis.Pool
redisExpire int32
// uri
view string
views string
del string
video string
hList string
hView string
flow string
upArchives string
descFormat string
nsMd5 string
simpleVideos string
simpleArchive string
videoJam string
upSpecialURL string
flowJudge string
staffApplies string
staffApply string
staffCheck string
}
// New init api url
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
arc: archive.New2(c.ArchiveRPC),
// http client
client: bm.NewClient(c.HTTPClient.Normal),
// db
db: sql.NewMySQL(c.DB.Archive),
cache: fanout.New("dao_archive", fanout.Worker(5), fanout.Buffer(10240)),
// mc
mc: memcache.NewPool(c.Memcache.Archive.Config),
mcExpire: 600,
//Fav redis cache
redis: redis.NewPool(c.Redis.Cover.Config),
redisExpire: int32(time.Duration(c.Redis.Cover.Expire) / time.Second),
// uri
view: c.Host.Videoup + _view,
views: c.Host.Videoup + _views,
video: c.Host.Videoup + _video,
del: c.Host.Videoup + _del,
hList: c.Host.Videoup + _hList,
hView: c.Host.Videoup + _hView,
flow: c.Host.Videoup + _flow,
upArchives: c.Host.Videoup + _archives,
descFormat: c.Host.Videoup + _descFormat,
nsMd5: c.Host.Videoup + _nsMd5,
simpleVideos: c.Host.Videoup + _simpleVideos,
simpleArchive: c.Host.Videoup + _simpleArchive,
videoJam: c.Host.Videoup + _videoJam,
upSpecialURL: c.Host.API + _upSpecial,
flowJudge: c.Host.Videoup + _flowjudge,
staffApplies: c.Host.Videoup + _staffApplies,
staffApply: c.Host.Videoup + _staffApply,
staffCheck: c.Host.Videoup + _staffCheck,
}
return
}
// Ping fn
func (d *Dao) Ping(c context.Context) (err error) {
if err = d.pingRedis(c); err != nil {
return
}
return
}
// Close fn
func (d *Dao) Close() (err error) {
if d.redis != nil {
d.redis.Close()
}
if d.mc != nil {
d.mc.Close()
}
return d.db.Close()
}
func staffKey(aid int64) string {
return fmt.Sprintf("staff_aid_%d", aid)
}
func (d *Dao) cacheSFStaffData(aid int64) string {
return fmt.Sprintf("staff_aid_sf_%d", aid)
}
//go:generate $GOPATH/src/go-common/app/tool/cache/gen
type _cache interface {
// cache: -singleflight=true -nullcache=[]*arcMdl.Staff{{ID:-1}} -check_null_code=len($)==1&&$[0].ID==-1
StaffData(c context.Context, aid int64) ([]*arcMdl.Staff, error)
ViewPoint(c context.Context, aid int64, cid int64) (vp *arcMdl.ViewPointRow, err error)
}
//go:generate $GOPATH/src/go-common/app/tool/cache/mc
type _mc interface {
// mc: -key=staffKey
CacheStaffData(c context.Context, key int64) ([]*arcMdl.Staff, error)
// 这里也支持自定义注释 会替换默认的注释
// mc: -key=staffKey -expire=3 -encode=json|gzip
AddCacheStaffData(c context.Context, key int64, value []*arcMdl.Staff) error
// mc: -key=staffKey
DelCacheStaffData(c context.Context, key int64) error
//mc: -key=viewPointCacheKey -expire=_viewPointExp -encode=json
AddCacheViewPoint(c context.Context, aid int64, vp *arcMdl.ViewPointRow, cid int64) (err error)
//mc: -key=viewPointCacheKey
CacheViewPoint(c context.Context, aid int64, cid int64) (vp *arcMdl.ViewPointRow, err error)
}

View File

@@ -0,0 +1,45 @@
package archive
import (
"flag"
"go-common/app/interface/main/creative/conf"
"os"
"strings"
"testing"
gock "gopkg.in/h2non/gock.v1"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.creative")
flag.Set("conf_token", "96b6a6c10bb311e894c14a552f48fef8")
flag.Set("tree_id", "2305")
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/creative.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
m.Run()
os.Exit(0)
}
func httpMock(method, url string) *gock.Request {
r := gock.New(url)
r.Method = strings.ToUpper(method)
d.client.SetTransport(gock.DefaultTransport)
return r
}

View File

@@ -0,0 +1,34 @@
package archive
import (
"context"
"strconv"
"go-common/library/cache/redis"
"go-common/library/log"
)
const (
_upFavTpsPrefix = "up_fav_tps_"
)
func keyUpFavTpsPrefix(mid int64) string {
return _upFavTpsPrefix + strconv.FormatInt(mid, 10)
}
// FavTypes fn
func (d *Dao) FavTypes(c context.Context, mid int64) (items map[string]int64, err error) {
conn := d.redis.Get(c)
defer conn.Close()
if items, err = redis.Int64Map(conn.Do("ZRANGE", keyUpFavTpsPrefix(mid), "0", "-1", "WITHSCORES")); err != nil {
log.Error("redis.Int64Map(conn.Do(ZRANGE, %s, 0, -1)) error(%v)", keyUpFavTpsPrefix(mid), err)
}
return
}
func (d *Dao) pingRedis(c context.Context) (err error) {
conn := d.redis.Get(c)
_, err = conn.Do("SET", "PING", "PONG")
conn.Close()
return
}

View File

@@ -0,0 +1,59 @@
package archive
import (
"context"
"errors"
"reflect"
"testing"
"go-common/library/cache/redis"
"github.com/bouk/monkey"
"github.com/smartystreets/goconvey/convey"
)
var (
errConnClosed = errors.New("redigo: connection closed")
)
func TestArchivekeyUpFavTpsPrefix(t *testing.T) {
var (
mid = int64(888952460)
)
convey.Convey("keyUpFavTpsPrefix", t, func(ctx convey.C) {
p1 := keyUpFavTpsPrefix(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestArchiveFavTypes(t *testing.T) {
var (
c = context.TODO()
mid = int64(888952460)
)
convey.Convey("FavTypes", t, func(ctx convey.C) {
connGuard := monkey.PatchInstanceMethod(reflect.TypeOf(d.redis), "Get", func(_ *redis.Pool, _ context.Context) redis.Conn {
return redis.MockWith(errConnClosed)
})
defer connGuard.Unpatch()
items, err := d.FavTypes(c, mid)
ctx.Convey("Then err should be nil.items should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(items, convey.ShouldBeNil)
})
})
}
func TestArchivepingRedis(t *testing.T) {
var (
c = context.TODO()
)
convey.Convey("pingRedis", t, func(ctx convey.C) {
err := d.pingRedis(c)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,62 @@
package archive
import (
"context"
"net/url"
"strconv"
"go-common/app/interface/main/creative/model/archive"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_hList = "/videoup/history/list"
_hView = "/videoup/history/view"
)
// HistoryList get the history of aid
func (d *Dao) HistoryList(c context.Context, mid, aid int64, ip string) (historys []*archive.ArcHistory, err error) {
params := url.Values{}
params.Set("aid", strconv.FormatInt(aid, 10))
params.Set("mid", strconv.FormatInt(mid, 10))
var res struct {
Code int `json:"code"`
Data []*archive.ArcHistory `json:"data"`
}
if err = d.client.Get(c, d.hList, ip, params, &res); err != nil {
log.Error("archive.HistoryList url(%s) mid(%d) error(%v)", d.hList+"?"+params.Encode(), mid, err)
err = ecode.CreativeArchiveAPIErr
return
}
if res.Code != 0 {
log.Error("archive.HistoryList url(%s) mid(%d) res(%v)", d.hList+"?"+params.Encode(), mid, res)
err = ecode.CreativeArchiveAPIErr
return
}
historys = res.Data
return
}
// HistoryView get the history of hid
func (d *Dao) HistoryView(c context.Context, mid, hid int64, ip string) (history *archive.ArcHistory, err error) {
params := url.Values{}
params.Set("hid", strconv.FormatInt(hid, 10))
params.Set("mid", strconv.FormatInt(mid, 10))
var res struct {
Code int `json:"code"`
Data *archive.ArcHistory `json:"data"`
}
if err = d.client.Get(c, d.hView, ip, params, &res); err != nil {
log.Error("archive.HistoryView url(%s) mid(%d) error(%v)", d.hView+"?"+params.Encode(), mid, err)
err = ecode.CreativeArchiveAPIErr
return
}
if res.Code != 0 {
log.Error("archive.HistoryView url(%s) mid(%d) res(%v)", d.hView+"?"+params.Encode(), mid, res)
err = ecode.CreativeArchiveAPIErr
return
}
history = res.Data
return
}

View File

@@ -0,0 +1,45 @@
package archive
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
gock "gopkg.in/h2non/gock.v1"
)
func TestArchiveHistoryList(t *testing.T) {
var (
c = context.TODO()
mid = int64(888952460)
aid = int64(10110560)
ip = "127.0.0.1"
)
convey.Convey("HistoryList", t, func(ctx convey.C) {
defer gock.OffAll()
httpMock("GET", d.hList).Reply(200).JSON(`{"code":20001}`)
historys, err := d.HistoryList(c, mid, aid, ip)
ctx.Convey("Then err should be nil.historys should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(historys, convey.ShouldBeNil)
})
})
}
func TestArchiveHistoryView(t *testing.T) {
var (
c = context.TODO()
mid = int64(888952460)
hid = int64(0)
ip = "127.0.0.1"
)
convey.Convey("HistoryView", t, func(ctx convey.C) {
defer gock.OffAll()
httpMock("GET", d.hView).Reply(200).JSON(`{"code":20001}`)
history, err := d.HistoryView(c, mid, hid, ip)
ctx.Convey("Then err should be nil.history should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(history, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,134 @@
// Code generated by $GOPATH/src/go-common/app/tool/cache/mc. DO NOT EDIT.
/*
Package archive is a generated mc cache package.
It is generated from:
type _mc interface {
// mc: -key=staffKey
CacheStaffData(c context.Context, key int64) ([]*arcMdl.Staff, error)
// 这里也支持自定义注释 会替换默认的注释
// mc: -key=staffKey -expire=3 -encode=json|gzip
AddCacheStaffData(c context.Context, key int64, value []*arcMdl.Staff) error
// mc: -key=staffKey
DelCacheStaffData(c context.Context, key int64) error
//mc: -key=viewPointCacheKey -expire=_viewPointExp -encode=json
AddCacheViewPoint(c context.Context, aid int64, vp *arcMdl.ViewPointRow, cid int64) (err error)
//mc: -key=viewPointCacheKey
CacheViewPoint(c context.Context, aid int64, cid int64) (vp *arcMdl.ViewPointRow, err error)
}
*/
package archive
import (
"context"
"fmt"
arcMdl "go-common/app/interface/main/creative/model/archive"
"go-common/library/cache/memcache"
"go-common/library/log"
"go-common/library/stat/prom"
)
var _ _mc
// CacheStaffData get data from mc
func (d *Dao) CacheStaffData(c context.Context, id int64) (res []*arcMdl.Staff, err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := staffKey(id)
reply, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:CacheStaffData")
log.Errorv(c, log.KV("CacheStaffData", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
res = []*arcMdl.Staff{}
err = conn.Scan(reply, &res)
if err != nil {
prom.BusinessErrCount.Incr("mc:CacheStaffData")
log.Errorv(c, log.KV("CacheStaffData", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// AddCacheStaffData 这里也支持自定义注释 会替换默认的注释
func (d *Dao) AddCacheStaffData(c context.Context, id int64, val []*arcMdl.Staff) (err error) {
if len(val) == 0 {
return
}
conn := d.mc.Get(c)
defer conn.Close()
key := staffKey(id)
item := &memcache.Item{Key: key, Object: val, Expiration: 3, Flags: memcache.FlagJSON | memcache.FlagGzip}
if err = conn.Set(item); err != nil {
prom.BusinessErrCount.Incr("mc:AddCacheStaffData")
log.Errorv(c, log.KV("AddCacheStaffData", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// DelCacheStaffData delete data from mc
func (d *Dao) DelCacheStaffData(c context.Context, id int64) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := staffKey(id)
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:DelCacheStaffData")
log.Errorv(c, log.KV("DelCacheStaffData", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// AddCacheViewPoint Set data to mc
func (d *Dao) AddCacheViewPoint(c context.Context, id int64, val *arcMdl.ViewPointRow, cid int64) (err error) {
if val == nil {
return
}
conn := d.mc.Get(c)
defer conn.Close()
key := viewPointCacheKey(id, cid)
item := &memcache.Item{Key: key, Object: val, Expiration: _viewPointExp, Flags: memcache.FlagJSON}
if err = conn.Set(item); err != nil {
prom.BusinessErrCount.Incr("mc:AddCacheViewPoint")
log.Errorv(c, log.KV("AddCacheViewPoint", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// CacheViewPoint get data from mc
func (d *Dao) CacheViewPoint(c context.Context, id int64, cid int64) (res *arcMdl.ViewPointRow, err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := viewPointCacheKey(id, cid)
reply, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:CacheViewPoint")
log.Errorv(c, log.KV("CacheViewPoint", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
res = &arcMdl.ViewPointRow{}
err = conn.Scan(reply, res)
if err != nil {
prom.BusinessErrCount.Incr("mc:CacheViewPoint")
log.Errorv(c, log.KV("CacheViewPoint", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}

View File

@@ -0,0 +1,113 @@
package archive
import (
"context"
"crypto/md5"
"encoding/hex"
"strconv"
arcmdl "go-common/app/interface/main/creative/model/archive"
"go-common/library/cache/memcache"
"go-common/library/log"
)
const (
_prefix = "porder_"
_cmPrefix = "arccm_"
_addMidAndTitlePrefix = "add_midtitle_"
)
func limitMidSameTitle(mid int64, title string) string {
ms := md5.Sum([]byte(title))
return _addMidAndTitlePrefix + strconv.FormatInt(mid, 10) + "_" + hex.EncodeToString(ms[:])
}
func keyPorder(aid int64) string {
return _prefix + strconv.FormatInt(aid, 10)
}
func keyArcCM(aid int64) string {
return _cmPrefix + strconv.FormatInt(aid, 10)
}
// POrderCache get stat cache.
func (d *Dao) POrderCache(c context.Context, aid int64) (st *arcmdl.Porder, err error) {
var (
conn = d.mc.Get(c)
r *memcache.Item
)
defer conn.Close()
r, err = conn.Get(keyPorder(aid))
if err != nil {
if err == memcache.ErrNotFound {
err = nil
} else {
log.Error("conn.Get2(%d) error(%v)", aid, err)
}
return
}
if err = conn.Scan(r, &st); err != nil {
log.Error("json.Unmarshal(%s) error(%v)", r.Value, err)
st = nil
}
return
}
// AddPOrderCache add stat cache.
func (d *Dao) AddPOrderCache(c context.Context, aid int64, st *arcmdl.Porder) (err error) {
var (
key = keyPorder(aid)
)
conn := d.mc.Get(c)
defer conn.Close()
if err = conn.Set(&memcache.Item{Key: key, Object: st, Flags: memcache.FlagJSON, Expiration: d.mcExpire}); err != nil {
log.Error("memcache.Set(%v) error(%v)", key, err)
}
return
}
// ArcCMCache get stat cache.
func (d *Dao) ArcCMCache(c context.Context, aid int64) (st *arcmdl.Commercial, err error) {
var (
conn = d.mc.Get(c)
r *memcache.Item
)
defer conn.Close()
r, err = conn.Get(keyArcCM(aid))
if err != nil {
if err == memcache.ErrNotFound {
err = nil
} else {
log.Error("conn.Get2(%d) error(%v)", aid, err)
}
return
}
if err = conn.Scan(r, &st); err != nil {
log.Error("json.Unmarshal(%s) error(%v)", r.Value, err)
st = nil
}
return
}
// AddArcCMCache add stat cache.
func (d *Dao) AddArcCMCache(c context.Context, aid int64, st *arcmdl.Commercial) (err error) {
var (
key = keyArcCM(aid)
)
conn := d.mc.Get(c)
defer conn.Close()
if err = conn.Set(&memcache.Item{Key: key, Object: st, Flags: memcache.FlagJSON, Expiration: d.mcExpire}); err != nil {
log.Error("memcache.Set(%v) error(%v)", key, err)
}
return
}
// DelSubmitCache func
func (d *Dao) DelSubmitCache(c context.Context, mid int64, title string) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
if err = conn.Delete(limitMidSameTitle(mid, title)); err == memcache.ErrNotFound {
err = nil
}
return
}

View File

@@ -0,0 +1,108 @@
package archive
import (
"context"
arcmdl "go-common/app/interface/main/creative/model/archive"
"go-common/library/cache/memcache"
"reflect"
"testing"
"github.com/bouk/monkey"
"github.com/smartystreets/goconvey/convey"
)
func TestArchivekeyPorder(t *testing.T) {
var (
aid = int64(10110560)
)
convey.Convey("keyPorder", t, func(ctx convey.C) {
p1 := keyPorder(aid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestArchivekeyArcCM(t *testing.T) {
var (
aid = int64(10110560)
)
convey.Convey("keyArcCM", t, func(ctx convey.C) {
p1 := keyArcCM(aid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestArchivePOrderCache(t *testing.T) {
var (
c = context.TODO()
aid = int64(10110560)
)
convey.Convey("POrderCache", t, func(ctx convey.C) {
connGuard := monkey.PatchInstanceMethod(reflect.TypeOf(d.mc), "Get", func(_ *memcache.Pool, _ context.Context) memcache.Conn {
return memcache.MockWith(memcache.ErrNotFound)
})
defer connGuard.Unpatch()
st, err := d.POrderCache(c, aid)
ctx.Convey("Then err should be nil.st should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(st, convey.ShouldBeNil)
})
})
}
func TestArchiveAddPOrderCache(t *testing.T) {
var (
c = context.TODO()
aid = int64(10110560)
st = &arcmdl.Porder{}
)
convey.Convey("AddPOrderCache", t, func(ctx convey.C) {
connGuard := monkey.PatchInstanceMethod(reflect.TypeOf(d.mc), "Get", func(_ *memcache.Pool, _ context.Context) memcache.Conn {
return memcache.MockWith(memcache.ErrNotFound)
})
defer connGuard.Unpatch()
err := d.AddPOrderCache(c, aid, st)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
}
func TestArchiveArcCMCache(t *testing.T) {
var (
c = context.TODO()
aid = int64(10110560)
)
convey.Convey("ArcCMCache", t, func(ctx convey.C) {
connGuard := monkey.PatchInstanceMethod(reflect.TypeOf(d.mc), "Get", func(_ *memcache.Pool, _ context.Context) memcache.Conn {
return memcache.MockWith(memcache.ErrNotFound)
})
defer connGuard.Unpatch()
st, err := d.ArcCMCache(c, aid)
ctx.Convey("Then err should be nil.st should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(st, convey.ShouldBeNil)
})
})
}
func TestArchiveAddArcCMCache(t *testing.T) {
var (
c = context.TODO()
aid = int64(10110560)
st = &arcmdl.Commercial{}
)
convey.Convey("AddArcCMCache", t, func(ctx convey.C) {
connGuard := monkey.PatchInstanceMethod(reflect.TypeOf(d.mc), "Get", func(_ *memcache.Pool, _ context.Context) memcache.Conn {
return memcache.MockWith(memcache.ErrNotFound)
})
defer connGuard.Unpatch()
err := d.AddArcCMCache(c, aid, st)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,61 @@
package archive
import (
"context"
"encoding/json"
"sort"
"strings"
"go-common/app/interface/main/creative/model/music"
"go-common/library/log"
)
const (
_AllMusicsSQL = "SELECT cooperate,id,sid,name,frontname,musicians,mid,cover,playurl,state,duration,filesize,ctime,pubtime,tags,timeline FROM music"
)
// AllMusics fn
func (d *Dao) AllMusics(c context.Context) (res map[int64]*music.Music, err error) {
rows, err := d.db.Query(c, _AllMusicsSQL)
if err != nil {
log.Error("mysqlDB.Query error(%v)", err)
return
}
defer rows.Close()
res = make(map[int64]*music.Music)
for rows.Next() {
v := &music.Music{}
var fName string
if err = rows.Scan(&v.Cooperate, &v.ID, &v.SID, &v.Name, &fName, &v.Musicians, &v.UpMID, &v.Cover, &v.Playurl, &v.State, &v.Duration, &v.FileSize, &v.CTime, &v.Pubtime, &v.TagsStr, &v.Timeline); err != nil {
log.Error("row.Scan error(%v)", err)
return
}
if len(fName) > 0 {
v.Name = fName
}
v.Tl = make([]*music.TimePoint, 0)
if len(v.Timeline) > 0 {
if err = json.Unmarshal([]byte(v.Timeline), &v.Tl); err != nil {
log.Error("json.Unmarshal Timeline failed error(%v)", err)
continue
}
sort.Slice(v.Tl, func(i, j int) bool {
return v.Tl[i].Point < v.Tl[j].Point
})
if len(v.Tl) > 0 {
for _, point := range v.Tl {
if point.Recommend == 1 {
v.RecommendPoint = point.Point
break
}
}
}
}
v.Tags = make([]string, 0)
if len(v.TagsStr) > 0 {
v.Tags = strings.Split(v.TagsStr, ",")
}
res[v.SID] = v
}
return
}

View File

@@ -0,0 +1,36 @@
package archive
import (
"context"
"fmt"
xsql "go-common/library/database/sql"
"reflect"
"testing"
"github.com/bouk/monkey"
"github.com/smartystreets/goconvey/convey"
)
func TestMusics(t *testing.T) {
convey.Convey("Musics", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("uat db ok", func(ctx convey.C) {
_, err := d.AllMusics(c)
ctx.Convey("Then err should be nil.bizs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
ctx.Convey("db error", func(ctx convey.C) {
guard := monkey.PatchInstanceMethod(reflect.TypeOf(d.db), "Query", func(_ *xsql.DB, _ context.Context, _ string, _ ...interface{}) (*xsql.Rows, error) {
return nil, fmt.Errorf("db.Query error")
})
defer guard.Unpatch()
_, err := d.AllMusics(c)
ctx.Convey("Then err should be nil.bizs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,75 @@
package archive
import (
"context"
"crypto/tls"
"fmt"
"go-common/library/ecode"
"go-common/library/log"
"io/ioutil"
"net"
"net/http"
"net/url"
"strconv"
"strings"
"time"
)
const (
_nsMd5 = "/videoup/ns/md5"
_notifyURL = "https://wax.gtloadbalance.cn:38080/InterfaceInfo/GetResult"
)
// AddNetSafeMd5 fn
func (d *Dao) AddNetSafeMd5(c context.Context, nid int64, md5 string) (err error) {
params := url.Values{}
params.Set("nid", strconv.FormatInt(nid, 10))
params.Set("md5", md5)
var res struct {
Code int `json:"code"`
}
if err = d.client.Post(c, d.nsMd5, "", params, &res); err != nil {
log.Error("d.client.Post(%s,%s) err(%v)", d.nsMd5, params.Encode(), err)
err = ecode.CreativeArchiveAPIErr
return
}
if res.Code != 0 {
log.Error("d.client.res.Code (%s,%s) err(%v)", d.nsMd5, params.Encode(), res.Code)
err = ecode.Int(res.Code)
return
}
return
}
// NotifyNetSafe fn
func (d *Dao) NotifyNetSafe(c context.Context, nid int64) (err error) {
req, err := http.NewRequest("POST", _notifyURL, strings.NewReader(fmt.Sprintf(`nid=%d&companyId=%d`, nid, 2)))
if err != nil {
log.Error("http.NewRequest error(%v) | uri(%s)", err, _notifyURL)
return
}
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
req.Header.Add("cache-control", "no-cache")
httpClient := &http.Client{
Timeout: time.Duration(time.Duration(5) * time.Second),
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
Dial: (&net.Dialer{
Timeout: 5 * time.Second,
Deadline: time.Now().Add(5 * time.Second),
KeepAlive: 5 * time.Second,
}).Dial,
TLSHandshakeTimeout: 5 * time.Second,
ResponseHeaderTimeout: time.Second * 2,
},
}
var resp *http.Response
if resp, err = httpClient.Do(req); err != nil {
log.Error("NotifyNetSafe d.client.Do error(%v) | uri(%s)", err, _notifyURL)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
log.Warn("NotifyNetSafe ret body (%+v), nid(%+v)", string(body), nid)
return
}

View File

@@ -0,0 +1,35 @@
package archive
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestArchiveAddNetSafeMd5(t *testing.T) {
var (
c = context.TODO()
nid = int64(0)
md5 = ""
)
convey.Convey("AddNetSafeMd5", t, func(ctx convey.C) {
err := d.AddNetSafeMd5(c, nid, md5)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
}
func TestArchiveNotifyNetSafe(t *testing.T) {
var (
c = context.TODO()
nid = int64(0)
)
convey.Convey("NotifyNetSafe", t, func(ctx convey.C) {
err := d.NotifyNetSafe(c, nid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,56 @@
package archive
import (
"context"
"database/sql"
"net/url"
"go-common/app/interface/main/creative/model/archive"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_flow = "/videoup/flows"
_porderSQL = "SELECT id,aid,industry_id,brand_id,brand_name,official,show_type,advertiser,agent,ctime,mtime FROM archive_porder WHERE aid=? AND show_front = 1"
)
// Flows fn
func (d *Dao) Flows(c context.Context) (flows []*archive.Flow, err error) {
params := url.Values{}
flows = []*archive.Flow{}
var res struct {
Code int `json:"code"`
Data []*archive.Flow `json:"data"`
}
if err = d.client.Get(c, d.flow, "", params, &res); err != nil {
log.Error("archive.Flow url(%s) error(%v)", d.flow+"?"+params.Encode(), err)
err = ecode.CreativeArchiveAPIErr
return
}
if res.Code != 0 {
log.Error("archive.Flow url(%s) res(%v)", d.flow+"?"+params.Encode(), res)
err = ecode.CreativeArchiveAPIErr
return
}
if res.Data == nil || len(res.Data) == 0 {
return
}
flows = res.Data
return
}
// Porder NOTE: move to up service
func (d *Dao) Porder(c context.Context, aid int64) (pd *archive.Porder, err error) {
row := d.db.QueryRow(c, _porderSQL, aid)
pd = &archive.Porder{}
if err = row.Scan(&pd.ID, &pd.AID, &pd.IndustryID, &pd.BrandID, &pd.BrandName, &pd.Official, &pd.ShowType, &pd.Advertiser, &pd.Agent, &pd.Ctime, &pd.Mtime); err != nil {
if err == sql.ErrNoRows {
pd = nil
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}

View File

@@ -0,0 +1,51 @@
package archive
import (
"context"
"go-common/app/interface/main/creative/model/archive"
xsql "go-common/library/database/sql"
"reflect"
"testing"
"github.com/bouk/monkey"
"github.com/smartystreets/goconvey/convey"
gock "gopkg.in/h2non/gock.v1"
)
func TestArchiveFlows(t *testing.T) {
var (
c = context.TODO()
err error
flows []*archive.Flow
)
convey.Convey("Flows", t, func(ctx convey.C) {
defer gock.OffAll()
httpMock("GET", d.simpleArchive).Reply(200).JSON(`{"code":20001}`)
flows, err = d.Flows(c)
ctx.Convey("Then err should be nil.flows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(flows, convey.ShouldNotBeNil)
})
})
}
func TestArchivePorder(t *testing.T) {
var (
err error
c = context.TODO()
aid = int64(10110560)
res *archive.Porder
)
convey.Convey("Porder", t, func(ctx convey.C) {
ret := &xsql.Row{}
guard := monkey.PatchInstanceMethod(reflect.TypeOf(d.db), "QueryRow", func(_ *xsql.DB, _ context.Context, _ string, _ ...interface{}) *xsql.Row {
return ret
})
defer guard.Unpatch()
res, err = d.Porder(c, aid)
ctx.Convey("Then err should be nil.pd should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,64 @@
package archive
import (
"context"
"go-common/app/service/main/archive/api"
"go-common/app/service/main/archive/model/archive"
"go-common/library/ecode"
"go-common/library/log"
)
// Archive get archive.
func (d *Dao) Archive(c context.Context, aid int64, ip string) (a *api.Arc, err error) {
var arg = &archive.ArgAid2{Aid: aid, RealIP: ip}
if a, err = d.arc.Archive3(c, arg); err != nil {
log.Error("rpc archive (%d) error(%v)", aid, err)
err = ecode.CreativeArcServiceErr
}
return
}
// Archives get archive list.
func (d *Dao) Archives(c context.Context, aids []int64, ip string) (a map[int64]*api.Arc, err error) {
var arg = &archive.ArgAids2{Aids: aids, RealIP: ip}
if a, err = d.arc.Archives3(c, arg); err != nil {
log.Error("rpc archive (%v) error(%v)", aids, err)
err = ecode.CreativeArcServiceErr
}
return
}
// Stats get archives stat.
func (d *Dao) Stats(c context.Context, aids []int64, ip string) (a map[int64]*api.Stat, err error) {
var arg = &archive.ArgAids2{Aids: aids, RealIP: ip}
if a, err = d.arc.Stats3(c, arg); err != nil {
log.Error("rpc Stats (%v) error(%v)", aids, err)
err = ecode.CreativeArcServiceErr
}
return
}
// UpCount get archives count.
func (d *Dao) UpCount(c context.Context, mid int64) (count int, err error) {
var arg = &archive.ArgUpCount2{Mid: mid}
if count, err = d.arc.UpCount2(c, arg); err != nil {
log.Error("rpc UpCount2 (%v) error(%v)", mid, err)
err = ecode.CreativeArcServiceErr
}
return
}
// Video get video.
func (d *Dao) Video(c context.Context, aid, cid int64, ip string) (v *api.Page, err error) {
var arg = &archive.ArgVideo2{Aid: aid, Cid: cid, RealIP: ip}
if v, err = d.arc.Video3(c, arg); err != nil {
if ecode.Cause(err) == ecode.NothingFound {
err = nil
return
}
log.Error("rpc video3 (%d) error(%v)", aid, err)
err = ecode.CreativeArcServiceErr
}
return
}

View File

@@ -0,0 +1,83 @@
package archive
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestArchiveArchive(t *testing.T) {
var (
c = context.TODO()
aid = int64(10110560)
ip = "127.0.0.1"
)
convey.Convey("Archive", t, func(ctx convey.C) {
a, err := d.Archive(c, aid, ip)
ctx.Convey("Then err should be nil.a should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(a, convey.ShouldNotBeNil)
})
})
}
func TestArchiveArchives(t *testing.T) {
var (
c = context.TODO()
aids = []int64{}
ip = ""
)
convey.Convey("Archives", t, func(ctx convey.C) {
a, err := d.Archives(c, aids, ip)
ctx.Convey("Then err should be nil.a should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(a, convey.ShouldNotBeNil)
})
})
}
func TestArchiveStats(t *testing.T) {
var (
c = context.TODO()
aids = []int64{}
ip = ""
)
convey.Convey("Stats", t, func(ctx convey.C) {
a, err := d.Stats(c, aids, ip)
ctx.Convey("Then err should be nil.a should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(a, convey.ShouldNotBeNil)
})
})
}
func TestArchiveUpCount(t *testing.T) {
var (
c = context.TODO()
mid = int64(888952460)
)
convey.Convey("UpCount", t, func(ctx convey.C) {
count, err := d.UpCount(c, mid)
ctx.Convey("Then err should be nil.count should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(count, convey.ShouldNotBeNil)
})
})
}
func TestArchiveVideo(t *testing.T) {
var (
c = context.TODO()
aid = int64(10110816)
cid = int64(10134702)
ip = "127.0.0.1"
)
convey.Convey("Video", t, func(ctx convey.C) {
v, err := d.Video(c, aid, cid, ip)
ctx.Convey("Then err should be nil.v should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(v, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,63 @@
package archive
import (
"context"
"go-common/app/interface/main/creative/model/archive"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
_staffCountSQL = "SELECT count(*) as count FROM archive_staff_apply WHERE apply_staff_mid=? AND deal_state = 1"
_staffSQL = "SELECT id,aid,mid,staff_mid,staff_title FROM archive_staff WHERE aid=? AND state = 1"
)
// RawStaffData get staff data from db
func (d *Dao) RawStaffData(c context.Context, aid int64) (res []*archive.Staff, err error) {
rows, err := d.db.Query(c, _staffSQL, aid)
if err != nil {
log.Error("mysqlDB.Query error(%v)", err)
return
}
defer rows.Close()
res = make([]*archive.Staff, 0)
res = append(res, &archive.Staff{AID: aid})
var mid int64
for rows.Next() {
v := &archive.Staff{}
if err = rows.Scan(&v.ID, &v.AID, &v.MID, &v.StaffMID, &v.StaffTitle); err != nil {
log.Error("row.Scan error(%v)", err)
res = res[0:0]
return
}
res = append(res, v)
mid = v.MID
}
if len(res) == 1 {
return res[0:0], nil
}
for _, v := range res {
if v.MID == 0 {
v.MID = mid
v.StaffMID = mid
v.StaffTitle = "UP"
break
}
}
return
}
// CountByMID .
func (d *Dao) CountByMID(c context.Context, mid int64) (count int, err error) {
row := d.db.QueryRow(c, _staffCountSQL, mid)
if err = row.Scan(&count); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}

View File

@@ -0,0 +1,30 @@
package archive
import (
"context"
"fmt"
xsql "go-common/library/database/sql"
"reflect"
"testing"
"github.com/bouk/monkey"
"github.com/smartystreets/goconvey/convey"
)
func TestStaff(t *testing.T) {
convey.Convey("RawStaff", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
guard := monkey.PatchInstanceMethod(reflect.TypeOf(d.db), "Query", func(_ *xsql.DB, _ context.Context, _ string, _ ...interface{}) (*xsql.Rows, error) {
return nil, fmt.Errorf("db.Query error")
})
defer guard.Unpatch()
_, err := d.RawStaffData(c, 10110195)
ctx.Convey("Then err should be nil.bizs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,84 @@
package archive
import (
"context"
"encoding/json"
"fmt"
"go-common/app/interface/main/creative/model/archive"
"go-common/library/log"
)
const (
_viewPointKey = "viewpoint_%d_%d"
_viewPointExp = 300
_videoViewPoints = "SELECT id,aid,cid,content,state,ctime,mtime FROM video_viewpoint WHERE aid=? AND cid=? AND state=1 ORDER BY mtime DESC LIMIT ?"
)
// viewPointCacheKey 高能看点MC缓存key
func viewPointCacheKey(aid, cid int64) string {
return fmt.Sprintf(_viewPointKey, aid, cid)
}
// RawViewPoint get video highlight viewpoint
func (d *Dao) RawViewPoint(c context.Context, aid, cid int64) (vp *archive.ViewPointRow, err error) {
vps, err := d.RawViewPoints(c, aid, cid, 1)
if err != nil {
return
}
if len(vps) == 0 {
return
}
vp = vps[0]
return
}
// RawViewPoints 获取多个版本的高能看点
func (d *Dao) RawViewPoints(c context.Context, aid, cid int64, count int) (vps []*archive.ViewPointRow, err error) {
rows, err := d.db.Query(c, _videoViewPoints, aid, cid, count)
if err != nil {
log.Error("d.Query() error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
var (
p struct {
ID int64
AID int64
CID int64
Content string
State int32
CTime string
MTime string
}
points struct {
Points []*archive.ViewPoint `json:"points"`
}
)
if err = rows.Scan(&p.ID, &p.AID, &p.CID, &p.Content, &p.State, &p.CTime, &p.MTime); err != nil {
log.Error("row.Scan error(%v)", err)
return
}
if err = json.Unmarshal([]byte(p.Content), &points); err != nil {
log.Error("json.Unmarshal(%s) error(%v)", p.Content, err)
return
}
for i := 0; i < len(points.Points); i++ {
if points.Points[i].State != 1 {
points.Points = append(points.Points[:i], points.Points[i+1:]...)
i--
}
}
vps = append(vps, &archive.ViewPointRow{
ID: p.ID,
AID: p.AID,
CID: p.CID,
Points: points.Points,
State: p.State,
CTime: p.CTime,
MTime: p.MTime,
})
}
return
}

View File

@@ -0,0 +1,21 @@
package archive
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDao_ViewPoints(t *testing.T) {
var (
c = context.TODO()
)
convey.Convey("ViewPoint", t, func(ctx convey.C) {
vp, err := d.ViewPoint(c, 10106351, 10126396)
ctx.Convey("", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(vp, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,62 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"article.go",
"dao.go",
"draft.go",
],
importpath = "go-common/app/interface/main/creative/dao/article",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/article:go_default_library",
"//app/interface/openplatform/article/model:go_default_library",
"//app/interface/openplatform/article/rpc/client:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = [
"article_test.go",
"dao_test.go",
"draft_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/article:go_default_library",
"//app/interface/openplatform/article/model:go_default_library",
"//app/interface/openplatform/article/rpc/client:go_default_library",
"//library/ecode:go_default_library",
"//vendor/github.com/bouk/monkey:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,250 @@
package article
import (
"context"
"go-common/library/log"
"strconv"
"strings"
artMdl "go-common/app/interface/main/creative/model/article"
"go-common/app/interface/openplatform/article/model"
"go-common/library/ecode"
)
// Articles get article list.
func (d *Dao) Articles(c context.Context, mid int64, pn, ps, sort, group, category int, ip string) (res *model.CreationArts, err error) {
var arg = &model.ArgCreationArts{
Mid: mid,
Pn: pn,
Ps: ps,
Sort: sort,
Group: group,
Category: category,
RealIP: ip,
}
if res, err = d.art.CreationUpperArticles(c, arg); err != nil {
log.Error("d.art.CreationUpperArticles (%v) error(%v)", arg, err)
if _, er := strconv.ParseInt(err.Error(), 10, 64); er != nil {
err = ecode.CreativeArticleRPCErr
}
}
return
}
// Categories list all category contain child.
func (d *Dao) Categories(c context.Context, ip string) (res *model.Categories, err error) {
var arg = &model.ArgIP{
RealIP: ip,
}
if res, err = d.art.Categories(c, arg); err != nil {
log.Error("d.art.Categories (%v) error(%v)", arg, err)
if _, er := strconv.ParseInt(err.Error(), 10, 64); er != nil {
err = ecode.CreativeArticleRPCErr
}
}
return
}
// CategoriesMap list all category.
func (d *Dao) CategoriesMap(c context.Context, ip string) (res map[int64]*model.Category, err error) {
var arg = &model.ArgIP{
RealIP: ip,
}
if res, err = d.art.CategoriesMap(c, arg); err != nil {
log.Error("d.art.CategoriesMap (%v) error(%v)", arg, err)
if _, er := strconv.ParseInt(err.Error(), 10, 64); er != nil {
err = ecode.CreativeArticleRPCErr
}
}
return
}
// Article get article detail.
func (d *Dao) Article(c context.Context, aid, mid int64, ip string) (res *model.Article, err error) {
var arg = &model.ArgAidMid{
Aid: aid,
Mid: mid,
RealIP: ip,
}
if res, err = d.art.CreationArticle(c, arg); err != nil {
log.Error("d.art.CreationArticle (%v) error(%v)", arg, err)
if _, er := strconv.ParseInt(err.Error(), 10, 64); er != nil {
err = ecode.CreativeArticleRPCErr
}
}
if res == nil || res.Meta == nil {
return
}
log.Info("d.art.CreationArticle id (%d) words (%d)", res.Meta.ID, len(res.Content))
return
}
// AddArticle add article.
func (d *Dao) AddArticle(c context.Context, art *artMdl.ArtParam) (id int64, err error) {
var arg = &model.ArgArticle{
Aid: art.AID,
Mid: art.MID,
Category: art.Category,
State: art.State,
Reprint: art.Reprint,
TemplateID: art.TemplateID,
Title: art.Title,
BannerURL: art.BannerURL,
Content: art.Content,
Summary: art.Summary,
RealIP: art.RealIP,
Words: art.Words,
DynamicIntro: art.DynamicIntro,
ImageURLs: art.ImageURLs,
OriginImageURLs: art.OriginImageURLs,
ActivityID: art.ActivityID,
}
if art.Tags != "" {
arg.Tags = strings.Split(art.Tags, ",")
} else {
arg.Tags = []string{}
}
log.Info("d.art.AddArticle id (%d) words (%d) ImageURLs (%s) OriginImageURLs (%s)", arg.Aid, len(arg.Content), art.ImageURLs, art.OriginImageURLs)
if id, err = d.art.AddArticle(c, arg); err != nil {
arg.Content = ""
log.Error("d.art.AddArticle (%v) error(%v)", arg, err)
if _, er := strconv.ParseInt(err.Error(), 10, 64); er != nil {
err = ecode.CreativeArticleRPCErr
}
}
return
}
// UpdateArticle update article.
func (d *Dao) UpdateArticle(c context.Context, art *artMdl.ArtParam) (err error) {
var arg = &model.ArgArticle{
Aid: art.AID,
Mid: art.MID,
Category: art.Category,
State: art.State,
Reprint: art.Reprint,
TemplateID: art.TemplateID,
Title: art.Title,
BannerURL: art.BannerURL,
Content: art.Content,
Summary: art.Summary,
RealIP: art.RealIP,
Words: art.Words,
DynamicIntro: art.DynamicIntro,
ImageURLs: art.ImageURLs,
OriginImageURLs: art.OriginImageURLs,
}
if art.Tags != "" {
arg.Tags = strings.Split(art.Tags, ",")
} else {
arg.Tags = []string{}
}
log.Info("d.art.UpdateArticle id (%d) words (%d) ImageURLs (%s) OriginImageURLs (%s)", arg.Aid, len(arg.Content), art.ImageURLs, art.OriginImageURLs)
if err = d.art.UpdateArticle(c, arg); err != nil {
arg.Content = ""
log.Error("d.art.UpdateArticle (%v) error(%v)", arg, err)
if _, er := strconv.ParseInt(err.Error(), 10, 64); er != nil {
err = ecode.CreativeArticleRPCErr
}
}
return
}
// DelArticle delete article.
func (d *Dao) DelArticle(c context.Context, aid, mid int64, ip string) (err error) {
var arg = &model.ArgAidMid{
Aid: aid,
Mid: mid,
RealIP: ip,
}
if err = d.art.DelArticle(c, arg); err != nil {
log.Error("d.art.AddArticle (%v) error(%v)", arg, err)
if _, er := strconv.ParseInt(err.Error(), 10, 64); er != nil {
err = ecode.CreativeArticleRPCErr
}
}
return
}
// WithDrawArticle withdraw article.
func (d *Dao) WithDrawArticle(c context.Context, aid, mid int64, ip string) (err error) {
var arg = &model.ArgAidMid{
Aid: aid,
Mid: mid,
RealIP: ip,
}
if err = d.art.CreationWithdrawArticle(c, arg); err != nil {
log.Error("d.art.CreationWithdrawArticle (%v) error(%v)", arg, err)
if _, er := strconv.ParseInt(err.Error(), 10, 64); er != nil {
err = ecode.CreativeArticleRPCErr
}
}
return
}
// IsAuthor checks that whether user has permission to write article.
func (d *Dao) IsAuthor(c context.Context, mid int64, ip string) (res bool, err error) {
var arg = &model.ArgMid{
Mid: mid,
RealIP: ip,
}
if res, err = d.art.IsAuthor(c, arg); err != nil {
if _, er := strconv.ParseInt(err.Error(), 10, 64); er != nil {
log.Error("d.art.IsAuthor (%v) error(%v)", arg, err)
err = ecode.CreativeArticleRPCErr
}
}
return
}
// RemainCount article up limit.
func (d *Dao) RemainCount(c context.Context, mid int64, ip string) (res int, err error) {
var arg = &model.ArgMid{
Mid: mid,
RealIP: ip,
}
if res, err = d.art.ArticleRemainCount(c, arg); err != nil {
log.Error("d.art.ArticleRemainCount (%v) error(%v)", arg, err)
if _, er := strconv.ParseInt(err.Error(), 10, 64); er != nil {
err = ecode.CreativeArticleRPCErr
}
}
return
}
// ArticleStat article stat
func (d *Dao) ArticleStat(c context.Context, mid int64, ip string) (res model.UpStat, err error) {
arg := &model.ArgMid{Mid: mid, RealIP: ip}
if res, err = d.art.CreationUpStat(c, arg); err != nil {
log.Error("d.art.UpStat(%+v) error(%v)", arg, err)
if _, er := strconv.ParseInt(err.Error(), 10, 64); er != nil {
err = ecode.CreativeArticleRPCErr
}
}
return
}
// ThirtyDayArticle thirty day article
func (d *Dao) ThirtyDayArticle(c context.Context, mid int64, ip string) (res []*model.ThirtyDayArticle, err error) {
arg := &model.ArgMid{Mid: mid, RealIP: ip}
if res, err = d.art.CreationUpThirtyDayStat(c, arg); err != nil {
log.Error("d.art.CreationUpThirtyDayStat(%+v) error(%v)", arg, err)
if _, er := strconv.ParseInt(err.Error(), 10, 64); er != nil {
err = ecode.CreativeArticleRPCErr
}
}
return
}
// ArticleMetas batch get articles by aids.
func (d *Dao) ArticleMetas(c context.Context, aids []int64, ip string) (res map[int64]*model.Meta, err error) {
arg := &model.ArgAids{Aids: aids, RealIP: ip}
if res, err = d.art.ArticleMetas(c, arg); err != nil {
log.Error("d.art.ArticleMetas(%+v) error(%v)", arg, err)
if _, er := strconv.ParseInt(err.Error(), 10, 64); er != nil {
err = ecode.CreativeArticleRPCErr
}
}
log.Info("d.art.ArticleMetas aids(%v)", aids)
return
}

View File

@@ -0,0 +1,278 @@
package article
import (
"context"
artMdl "go-common/app/interface/main/creative/model/article"
"testing"
"go-common/app/interface/openplatform/article/model"
"go-common/app/interface/openplatform/article/rpc/client"
"go-common/library/ecode"
"reflect"
"github.com/bouk/monkey"
"github.com/smartystreets/goconvey/convey"
)
func TestArticleArticles(t *testing.T) {
var (
c = context.TODO()
mid = int64(1)
pn = int(0)
ps = int(0)
sort = int(0)
group = int(0)
category = int(0)
ip = ""
)
convey.Convey("Articles", t, func(ctx convey.C) {
// mock
mock := monkey.PatchInstanceMethod(reflect.TypeOf(d.art), "CreationUpperArticles",
func(_ *client.Service, _ context.Context, _ *model.ArgCreationArts) (res *model.CreationArts, err error) {
return nil, ecode.CreativeArticleRPCErr
})
defer mock.Unpatch()
res, err := d.Articles(c, mid, pn, ps, sort, group, category, ip)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
}
func TestArticleCategories(t *testing.T) {
var (
c = context.TODO()
ip = ""
)
convey.Convey("Categories", t, func(ctx convey.C) {
// mock
mock := monkey.PatchInstanceMethod(reflect.TypeOf(d.art), "Categories",
func(_ *client.Service, _ context.Context, _ *model.ArgIP) (res *model.Categories, err error) {
return nil, ecode.CreativeArticleRPCErr
})
defer mock.Unpatch()
res, err := d.Categories(c, ip)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
}
func TestArticleCategoriesMap(t *testing.T) {
var (
c = context.TODO()
ip = ""
)
convey.Convey("CategoriesMap", t, func(ctx convey.C) {
// mock
mock := monkey.PatchInstanceMethod(reflect.TypeOf(d.art), "CategoriesMap",
func(_ *client.Service, _ context.Context, _ *model.ArgIP) (res map[int64]*model.Category, err error) {
return nil, ecode.CreativeArticleRPCErr
})
defer mock.Unpatch()
res, err := d.CategoriesMap(c, ip)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldEqual, 20017)
ctx.So(len(res), convey.ShouldEqual, 0)
})
})
}
func TestArticleArticle(t *testing.T) {
var (
c = context.TODO()
aid = int64(1198)
mid = int64(0)
ip = ""
)
convey.Convey("Article", t, func(ctx convey.C) {
// mock
mock := monkey.PatchInstanceMethod(reflect.TypeOf(d.art), "CreationArticle",
func(_ *client.Service, _ context.Context, _ *model.ArgAidMid) (res *model.Article, err error) {
return nil, ecode.CreativeArticleRPCErr
})
defer mock.Unpatch()
res, err := d.Article(c, aid, mid, ip)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
}
func TestArticleAddArticle(t *testing.T) {
var (
c = context.TODO()
art = &artMdl.ArtParam{}
)
convey.Convey("AddArticle", t, func(ctx convey.C) {
// mock
mock := monkey.PatchInstanceMethod(reflect.TypeOf(d.art), "AddArticle",
func(_ *client.Service, _ context.Context, _ *model.ArgArticle) (id int64, err error) {
return 0, ecode.CreativeArticleRPCErr
})
defer mock.Unpatch()
id, err := d.AddArticle(c, art)
ctx.Convey("Then err should be nil.id should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(id, convey.ShouldEqual, 0)
})
})
}
func TestArticleUpdateArticle(t *testing.T) {
var (
c = context.TODO()
art = &artMdl.ArtParam{}
)
convey.Convey("UpdateArticle", t, func(ctx convey.C) {
// mock
mock := monkey.PatchInstanceMethod(reflect.TypeOf(d.art), "UpdateArticle",
func(_ *client.Service, _ context.Context, _ *model.ArgArticle) (err error) {
return ecode.CreativeArticleRPCErr
})
defer mock.Unpatch()
err := d.UpdateArticle(c, art)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
}
func TestArticleDelArticle(t *testing.T) {
var (
c = context.TODO()
aid = int64(0)
mid = int64(0)
ip = ""
)
convey.Convey("DelArticle", t, func(ctx convey.C) {
// mock
mock := monkey.PatchInstanceMethod(reflect.TypeOf(d.art), "DelArticle",
func(_ *client.Service, _ context.Context, _ *model.ArgAidMid) (err error) {
return ecode.CreativeArticleRPCErr
})
defer mock.Unpatch()
err := d.DelArticle(c, aid, mid, ip)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
}
func TestArticleWithDrawArticle(t *testing.T) {
var (
c = context.TODO()
aid = int64(0)
mid = int64(0)
ip = ""
)
convey.Convey("WithDrawArticle", t, func(ctx convey.C) {
err := d.WithDrawArticle(c, aid, mid, ip)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
}
func TestArticleIsAuthor(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
ip = ""
)
convey.Convey("IsAuthor", t, func(ctx convey.C) {
// mock
mock := monkey.PatchInstanceMethod(reflect.TypeOf(d.art), "IsAuthor",
func(_ *client.Service, _ context.Context, _ *model.ArgMid) (res bool, err error) {
return false, ecode.CreativeArticleRPCErr
})
defer mock.Unpatch()
res, err := d.IsAuthor(c, mid, ip)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldEqual, false)
})
})
}
func TestArticleRemainCount(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
ip = ""
)
convey.Convey("ArticleRemainCount", t, func(ctx convey.C) {
// mock
mock := monkey.PatchInstanceMethod(reflect.TypeOf(d.art), "ArticleRemainCount",
func(_ *client.Service, _ context.Context, _ *model.ArgMid) (res int, err error) {
return 0, ecode.CreativeArticleRPCErr
})
defer mock.Unpatch()
res, err := d.RemainCount(c, mid, ip)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldEqual, 0)
})
})
}
func TestArticleArticleStat(t *testing.T) {
var (
c = context.TODO()
mid = int64(2333)
ip = ""
)
convey.Convey("ArticleStat", t, func(ctx convey.C) {
// mock
//mock := monkey.PatchInstanceMethod(reflect.TypeOf(d.art), "CreationUpStat",
// func(_ *client.Service, _ context.Context, _ *model.ArgMid) (res model.UpStat, err error) {
// return new(model.UpStat), ecode.CreativeArticleRPCErr
// })
//defer mock.Unpatch()
res, err := d.ArticleStat(c, mid, ip)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestArticleThirtyDayArticle(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
ip = ""
)
convey.Convey("ThirtyDayArticle", t, func(ctx convey.C) {
res, err := d.ThirtyDayArticle(c, mid, ip)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
}
func TestArticleArticleMetas(t *testing.T) {
var (
c = context.TODO()
aids = []int64{233}
ip = ""
)
convey.Convey("ArticleMetas", t, func(ctx convey.C) {
//mock
mock := monkey.PatchInstanceMethod(reflect.TypeOf(d.art), "ArticleMetas",
func(_ *client.Service, _ context.Context, _ *model.ArgAids) (res map[int64]*model.Meta, err error) {
return nil, ecode.CreativeArticleRPCErr
})
defer mock.Unpatch()
res, err := d.ArticleMetas(c, aids, ip)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,24 @@
package article
import (
"go-common/app/interface/main/creative/conf"
article "go-common/app/interface/openplatform/article/rpc/client"
)
// Dao is archive dao.
type Dao struct {
// config
c *conf.Config
// rpc
art *article.Service
}
// New init api url
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
// rpc
art: article.New(c.ArticleRPC),
}
return
}

View File

@@ -0,0 +1,35 @@
package article
import (
"flag"
"go-common/app/interface/main/creative/conf"
"os"
"testing"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.creative")
flag.Set("conf_token", "96b6a6c10bb311e894c14a552f48fef8")
flag.Set("tree_id", "2305")
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/creative.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
m.Run()
os.Exit(0)
}

View File

@@ -0,0 +1,99 @@
package article
import (
"context"
artMdl "go-common/app/interface/main/creative/model/article"
"go-common/app/interface/openplatform/article/model"
"go-common/library/ecode"
"go-common/library/log"
"strconv"
"strings"
)
// AddDraft add draft.
func (d *Dao) AddDraft(c context.Context, art *artMdl.ArtParam) (id int64, err error) {
var arg = &model.ArgArticle{
Aid: art.AID,
Mid: art.MID,
Category: art.Category,
State: art.State,
Reprint: art.Reprint,
TemplateID: art.TemplateID,
Title: art.Title,
BannerURL: art.BannerURL,
Content: art.Content,
Summary: art.Summary,
RealIP: art.RealIP,
Words: art.Words,
DynamicIntro: art.DynamicIntro,
ImageURLs: art.ImageURLs,
OriginImageURLs: art.OriginImageURLs,
}
if art.Tags != "" {
arg.Tags = strings.Split(art.Tags, ",")
} else {
arg.Tags = []string{}
}
log.Info("d.art.AddDraft id (%d) words (%d) ImageURLs (%s) OriginImageURLs (%s)", arg.Aid, len(arg.Content), art.ImageURLs, art.OriginImageURLs)
if id, err = d.art.AddArtDraft(c, arg); err != nil {
arg.Content = ""
log.Error("d.art.AddArtDraft (%v) error(%v)", arg, err)
if _, er := strconv.ParseInt(err.Error(), 10, 64); er != nil {
err = ecode.CreativeArticleRPCErr
}
}
return
}
// DelDraft delete draft.
func (d *Dao) DelDraft(c context.Context, aid, mid int64, ip string) (err error) {
var arg = &model.ArgAidMid{
Aid: aid,
Mid: mid,
RealIP: ip,
}
if err = d.art.DelArtDraft(c, arg); err != nil {
log.Error("d.art.DelArtDraft (%v) error(%v)", arg, err)
if _, er := strconv.ParseInt(err.Error(), 10, 64); er != nil {
err = ecode.CreativeArticleRPCErr
}
}
return
}
// Draft get draft detail.
func (d *Dao) Draft(c context.Context, aid, mid int64, ip string) (res *model.Draft, err error) {
var arg = &model.ArgAidMid{
Aid: aid,
Mid: mid,
RealIP: ip,
}
if res, err = d.art.ArtDraft(c, arg); err != nil {
log.Error("d.art.ArtDraft (%v) error(%v)", arg, err)
if _, er := strconv.ParseInt(err.Error(), 10, 64); er != nil {
err = ecode.CreativeArticleRPCErr
}
}
if res == nil || res.Meta == nil {
return
}
log.Info("d.art.CreationArticle id (%d) words (%d)", res.Meta.ID, len(res.Content))
return
}
// Drafts get draft list.
func (d *Dao) Drafts(c context.Context, mid int64, pn, ps int, ip string) (res *model.Drafts, err error) {
var arg = &model.ArgUpDraft{
Mid: mid,
Pn: pn,
Ps: ps,
RealIP: ip,
}
if res, err = d.art.UpperDrafts(c, arg); err != nil {
log.Error("d.art.UpperDrafts (%v) error(%v)", arg, err)
if _, er := strconv.ParseInt(err.Error(), 10, 64); er != nil {
err = ecode.CreativeArticleRPCErr
}
}
return
}

View File

@@ -0,0 +1,74 @@
package article
import (
"context"
"testing"
artMdl "go-common/app/interface/main/creative/model/article"
"go-common/library/ecode"
"github.com/smartystreets/goconvey/convey"
)
func TestArticleAddDraft(t *testing.T) {
var (
c = context.TODO()
art = &artMdl.ArtParam{}
)
convey.Convey("AddDraft", t, func(ctx convey.C) {
id, err := d.AddDraft(c, art)
ctx.Convey("Then err should be nil.id should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotEqual, ecode.ArtCreationNoPrivilege)
ctx.So(id, convey.ShouldEqual, 0)
})
})
}
func TestArticleDelDraft(t *testing.T) {
var (
c = context.TODO()
aid = int64(1)
mid = int64(0)
ip = ""
)
convey.Convey("DelDraft", t, func(ctx convey.C) {
err := d.DelDraft(c, aid, mid, ip)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotEqual, ecode.ArtCreationNoPrivilege)
})
})
}
func TestArticleDraft(t *testing.T) {
var (
c = context.TODO()
aid = int64(0)
mid = int64(0)
ip = ""
)
convey.Convey("Draft", t, func(ctx convey.C) {
res, err := d.Draft(c, aid, mid, ip)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotEqual, ecode.ArtCreationNoPrivilege)
ctx.So(res, convey.ShouldBeNil)
})
})
}
func TestArticleDrafts(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
pn = int(0)
ps = int(0)
ip = ""
)
convey.Convey("Drafts", t, func(ctx convey.C) {
res, err := d.Drafts(c, mid, pn, ps, ip)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotEqual, ecode.ArtCreationNoPrivilege)
ctx.So(res, convey.ShouldBeNil)
})
})
}

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 = [
"assist.go",
"dao.go",
"live.go",
],
importpath = "go-common/app/interface/main/creative/dao/assist",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/assist:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/time:go_default_library",
"//library/xstr:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = [
"assist_test.go",
"dao_test.go",
"live_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/interface/main/creative/model/assist:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
"//vendor/gopkg.in/h2non/gock.v1:go_default_library",
],
)

View File

@@ -0,0 +1,257 @@
package assist
import (
"context"
"go-common/app/interface/main/creative/model/assist"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/xstr"
"net/url"
"strconv"
"strings"
)
const (
// api
_addAssistURI = "/x/internal/assist/add"
_delAssistURI = "/x/internal/assist/del"
_getAssistInfoURI = "/x/internal/assist/info"
_getAssistLogsURI = "/x/internal/assist/logs"
_addAssistLogURI = "/x/internal/assist/log/add"
_getAssistURI = "/x/internal/assist/assists"
_getAssistLogInfoURI = "/x/internal/assist/log/info"
_revocAssistLogURI = "/x/internal/assist/log/cancel"
_getAssistLogObjURI = "/x/internal/assist/log/obj"
_getAssistStatURI = "/x/internal/assist/stat"
)
// Assists get all Assists from assist service.
func (d *Dao) Assists(c context.Context, mid int64, ip string) (assists []*assist.Assist, err error) {
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
var res struct {
Code int `json:"code"`
Data []*assist.Assist `json:"data"`
}
if err = d.client.Get(c, d.assistListURL, ip, params, &res); err != nil {
log.Error("d.client.Get(%s,%s,%s) err(%v)", d.assistListURL, ip, params.Encode(), err)
err = ecode.CreativeAssistErr
return
}
if res.Code != 0 {
err = ecode.Int(res.Code)
log.Error("d.client.Get(%s,%s,%s) err(%v)", d.assistListURL, ip, params.Encode(), err)
return
}
assists = res.Data
return
}
// AssistLog get assist log info from assist service
func (d *Dao) AssistLog(c context.Context, mid, assistMid, logID int64, ip string) (assistLog *assist.AssistLog, err error) {
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("assist_mid", strconv.FormatInt(assistMid, 10))
params.Set("log_id", strconv.FormatInt(logID, 10))
var res struct {
Code int `json:"code"`
Data *assist.AssistLog `json:"data"`
}
if err = d.client.Get(c, d.assistLogInfoURL, ip, params, &res); err != nil {
log.Error("d.client.Get(%s,%s,%s) err(%v)", d.assistLogInfoURL, ip, params.Encode(), err)
err = ecode.CreativeAssistErr
return
}
if res.Code != 0 {
err = ecode.Int(res.Code)
log.Error("d.client.Get(%s,%s,%s) err(%v)", d.assistLogInfoURL, ip, params.Encode(), err)
return
}
assistLog = res.Data
return
}
// AssistLogs get logs from assist service.
func (d *Dao) AssistLogs(c context.Context, mid, assistMid, pn, ps, stime, etime int64, ip string) (logs []*assist.AssistLog, pager map[string]int64, err error) {
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("assist_mid", strconv.FormatInt(assistMid, 10))
params.Set("pn", strconv.FormatInt(pn, 10))
params.Set("ps", strconv.FormatInt(ps, 10))
params.Set("stime", strconv.FormatInt(stime, 10))
params.Set("etime", strconv.FormatInt(etime, 10))
var res struct {
Code int `json:"code"`
Data []*assist.AssistLog `json:"data"`
Pager map[string]int64 `json:"pager"`
}
if err = d.client.Get(c, d.assistLogsURL, ip, params, &res); err != nil {
log.Error("d.client.Get(%s,%s,%s) err(%v)", d.assistLogsURL, ip, params.Encode(), err)
err = ecode.CreativeAssistErr
return
}
if res.Code != 0 {
err = ecode.Int(res.Code)
log.Error("d.client.Get(%s,%s,%s) err(%v)", d.assistLogsURL, ip, params.Encode(), err)
return
}
for _, v := range res.Data {
if v.Type == 3 && v.Action == 8 {
detailT3A8 := strings.Split(v.Detail, ":")
if len(detailT3A8) > 1 {
v.Detail = " 用户UID:" + detailT3A8[len(detailT3A8)-1]
}
}
if v.Type == 3 && v.Action == 9 {
detailT3A9 := strings.Split(v.Detail, ":")
if len(detailT3A9) > 1 {
v.Detail = " 用户UID:" + detailT3A9[len(detailT3A9)-1]
}
}
}
logs = res.Data
pager = res.Pager
return
}
// AddAssist add assist
func (d *Dao) AddAssist(c context.Context, mid, assistMid int64, ip, upUname string) (err error) {
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("up_uname", upUname)
params.Set("assist_mid", strconv.FormatInt(assistMid, 10))
var res struct {
Code int `json:"code"`
}
log.Info("AddOrDelAssist d.client.Post(%s,%s,%s) err(%v)", d.assistAddURL, ip, params.Encode(), err)
if err = d.client.Post(c, d.assistAddURL, ip, params, &res); err != nil {
log.Error("d.client.Post(%s,%s,%s) err(%v)", d.assistAddURL, ip, params.Encode(), err)
err = ecode.CreativeAssistErr
return
}
if res.Code != 0 {
err = ecode.Int(res.Code)
log.Error("d.client.Post(%s,%s,%s) err(%v)", d.assistAddURL, ip, params.Encode(), err)
return
}
return
}
// DelAssist cancel assist
func (d *Dao) DelAssist(c context.Context, mid, assistMid int64, ip, upUname string) (err error) {
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("assist_mid", strconv.FormatInt(assistMid, 10))
params.Set("up_uname", upUname)
var res struct {
Code int `json:"code"`
}
log.Info("AddOrDelAssist d.client.Post(%s,%s,%s) err(%v)", d.assistDelURL, ip, params.Encode(), err)
if err = d.client.Post(c, d.assistDelURL, ip, params, &res); err != nil {
log.Error("d.client.Post(%s,%s,%s) err(%v)", d.assistDelURL, ip, params.Encode(), err)
err = ecode.CreativeAssistErr
return
}
if res.Code != 0 {
err = ecode.Int(res.Code)
log.Error("d.client.Post(%s,%s,%s) err(%v)", d.assistDelURL, ip, params.Encode(), err)
return
}
return
}
// RevocAssistLog calcel assistlog action
func (d *Dao) RevocAssistLog(c context.Context, mid, assistMid, logID int64, ip string) (err error) {
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("assist_mid", strconv.FormatInt(assistMid, 10))
params.Set("log_id", strconv.FormatInt(logID, 10))
var res struct {
Code int `json:"code"`
}
if err = d.client.Post(c, d.assistLogRevocURL, ip, params, &res); err != nil {
log.Error("d.client.Post(%s,%s,%s) err(%v)", d.assistLogRevocURL, ip, params.Encode(), err)
err = ecode.CreativeAssistErr
return
}
if res.Code != 0 {
err = ecode.Int(res.Code)
log.Error("d.client.Post(%s,%s,%s) err(%v)", d.assistLogRevocURL, ip, params.Encode(), err)
return
}
return
}
// Stat get assists stat
func (d *Dao) Stat(c context.Context, mid int64, assistMids []int64, ip string) (stat map[int64]map[int8]map[int8]int, err error) {
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("assmids", xstr.JoinInts(assistMids))
var res struct {
Code int `json:"code"`
Data map[int64]map[int8]map[int8]int `json:"data"`
}
if err = d.client.Get(c, d.assistStatURL, ip, params, &res); err != nil {
log.Error("d.client.Get(%s,%s,%s) err(%v)", d.assistStatURL, ip, params.Encode(), err)
err = ecode.CreativeAssistErr
return
}
if res.Code != 0 {
log.Error("d.client.Get(%s,%s,%s) err(%v)", d.assistStatURL, ip, params.Encode(), err)
err = ecode.Int(res.Code)
return
}
stat = res.Data
return
}
// Info check if is assist
func (d *Dao) Info(c context.Context, mid, assistMid int64, ip string) (assist int8, err error) {
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("assist_mid", strconv.FormatInt(assistMid, 10))
params.Set("type", "1")
var res struct {
Code int `json:"code"`
Data struct {
Assist int8 `json:"assist"`
} `json:"data"`
}
if err = d.client.Get(c, d.assistInfoURL, ip, params, &res); err != nil {
log.Error("d.client.Post(%s,%s,%s) err(%v)", d.assistInfoURL, ip, params.Encode(), err)
err = ecode.CreativeAssistErr
return
}
if res.Code != 0 {
log.Error("d.client.Post(%s,%s,%s) err(%v)", d.assistInfoURL, ip, params.Encode(), err)
err = ecode.Int(res.Code)
return
}
assist = res.Data.Assist
return
}
// AssistLogObj get assist log info from assist service
func (d *Dao) AssistLogObj(c context.Context, tp, act int8, mid, objID int64) (assLog *assist.AssistLog, err error) {
params := url.Values{}
params.Set("type", strconv.FormatInt(int64(tp), 10))
params.Set("action", strconv.FormatInt(int64(act), 10))
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("object_id", strconv.FormatInt(objID, 10))
var res struct {
Code int `json:"code"`
Data *assist.AssistLog `json:"data"`
}
if err = d.client.Get(c, d.assistLogObjURL, "", params, &res); err != nil {
log.Error("d.client.Get(%s,%s) err(%v)", d.assistLogObjURL, params.Encode(), err)
err = ecode.CreativeAssistErr
return
}
if res.Code != 0 {
err = ecode.Int(res.Code)
log.Error("d.client.Get(%s,%s) err(%v)", d.assistLogObjURL, params.Encode(), err)
return
}
assLog = res.Data
return
}

View File

@@ -0,0 +1,248 @@
package assist
import (
"context"
"go-common/app/interface/main/creative/model/assist"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestAssistAssists(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
ip = ""
)
convey.Convey("Assists", t, func(ctx convey.C) {
var res = struct {
Code int `json:"code"`
Data []*assist.Assist `json:"data"`
}{
Code: 0,
Data: []*assist.Assist{
{
AssistMid: 1,
Banned: 1,
},
},
}
httpMock("GET", d.assistListURL).Reply(200).JSON(res)
assists, err := d.Assists(c, mid, ip)
ctx.Convey("Then err should be nil.assists should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(assists, convey.ShouldNotBeNil)
})
})
}
var assLogRes = struct {
Code int `json:"code"`
Data *assist.AssistLog `json:"data"`
}{
Code: 0,
Data: &assist.AssistLog{
ID: 1,
Mid: 0,
AssistMid: 0,
AssistAvatar: "",
AssistName: "",
Type: 0,
Action: 0,
SubjectID: 0,
ObjectID: "",
Detail: "",
State: 0,
CTime: 0,
},
}
func TestAssistAssistLog(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
assistMid = int64(0)
logID = int64(0)
ip = ""
)
convey.Convey("AssistLog", t, func(ctx convey.C) {
httpMock("GET", d.assistLogInfoURL).Reply(200).JSON(assLogRes)
assistLog, err := d.AssistLog(c, mid, assistMid, logID, ip)
ctx.Convey("Then err should be nil.assistLog should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(assistLog, convey.ShouldNotBeNil)
})
})
}
func TestAssistAssistLogs(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
assistMid = int64(0)
pn = int64(0)
ps = int64(0)
stime = int64(0)
etime = int64(0)
ip = ""
res = struct {
Code int `json:"code"`
Data []*assist.AssistLog `json:"data"`
Pager map[string]int64 `json:"pager"`
}{
Code: 0,
Data: []*assist.AssistLog{
{
ID: 0,
Mid: 0,
AssistMid: 0,
AssistAvatar: "",
AssistName: "",
Type: 0,
Action: 0,
SubjectID: 0,
ObjectID: "",
Detail: "",
State: 0,
CTime: 0,
},
},
Pager: map[string]int64{
"pn": 1,
"ps": 10,
},
}
)
convey.Convey("AssistLogs", t, func(ctx convey.C) {
httpMock("GET", d.assistLogsURL).Reply(200).JSON(res)
logs, pager, err := d.AssistLogs(c, mid, assistMid, pn, ps, stime, etime, ip)
ctx.Convey("Then err should be nil.logs,pager should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(pager, convey.ShouldNotBeNil)
ctx.So(logs, convey.ShouldNotBeNil)
})
})
}
func TestAssistAddAssist(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
assistMid = int64(0)
ip = "127.0.0.1"
upUname = "12"
)
convey.Convey("AddAssist", t, func(ctx convey.C) {
httpMock("POST", d.assistAddURL).Reply(200).JSON(`{"code":0}`)
err := d.AddAssist(c, mid, assistMid, ip, upUname)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestAssistDelAssist(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
assistMid = int64(0)
ip = ""
upUname = ""
)
convey.Convey("DelAssist", t, func(ctx convey.C) {
httpMock("POST", d.assistDelURL).Reply(200).JSON(`{"code":0}`)
err := d.DelAssist(c, mid, assistMid, ip, upUname)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestAssistRevocAssistLog(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
assistMid = int64(0)
logID = int64(0)
ip = ""
)
convey.Convey("RevocAssistLog", t, func(ctx convey.C) {
httpMock("POST", d.assistLogRevocURL).Reply(200).JSON(`{"code":0}`)
err := d.RevocAssistLog(c, mid, assistMid, logID, ip)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestAssistStat(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
assistMids = []int64{}
ip = ""
res = struct {
Code int `json:"code"`
Data map[int64]map[int8]map[int8]int `json:"data"`
}{
Code: 0,
Data: map[int64]map[int8]map[int8]int{},
}
)
convey.Convey("Stat", t, func(ctx convey.C) {
httpMock("GET", d.assistStatURL).Reply(200).JSON(res)
stat, err := d.Stat(c, mid, assistMids, ip)
ctx.Convey("Then err should be nil.stat should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(stat, convey.ShouldNotBeNil)
})
})
}
func TestAssistInfo(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
assistMid = int64(0)
ip = ""
res = struct {
Code int `json:"code"`
Data struct {
Assist int8 `json:"assist"`
} `json:"data"`
}{
Code: 0,
Data: struct {
Assist int8 `json:"assist"`
}{
Assist: 1,
},
}
)
convey.Convey("Info", t, func(ctx convey.C) {
httpMock("GET", d.assistInfoURL).Reply(200).JSON(res)
assist, err := d.Info(c, mid, assistMid, ip)
ctx.Convey("Then err should be nil.assist should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(assist, convey.ShouldNotBeNil)
})
})
}
func TestAssistAssistLogObj(t *testing.T) {
var (
c = context.TODO()
tp = int8(0)
act = int8(0)
mid = int64(0)
objID = int64(0)
)
convey.Convey("AssistLogObj", t, func(ctx convey.C) {
httpMock("GET", d.assistLogObjURL).Reply(200).JSON(assLogRes)
assLog, err := d.AssistLogObj(c, tp, act, mid, objID)
ctx.Convey("Then err should be nil.assLog should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(assLog, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,56 @@
package assist
import (
"go-common/app/interface/main/creative/conf"
bm "go-common/library/net/http/blademaster"
)
// Dao is creative dao.
type Dao struct {
// config
c *conf.Config
// http client
client *bm.Client
// assist url
assistLogsURL string
assistListURL string
assistInfoURL string
assistLogInfoURL string
assistAddURL string
assistDelURL string
assistLogAddURL string
assistLogRevocURL string
assistStatURL string
assistLogObjURL string
liveStatusURL string
liveAddAssistURL string
liveDelAssistURL string
liveRevocBannedURL string
liveAssistsURL string
liveCheckAssURL string
}
// New init api url
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
client: bm.NewClient(c.HTTPClient.Normal),
assistAddURL: c.Host.API + _addAssistURI,
assistDelURL: c.Host.API + _delAssistURI,
assistInfoURL: c.Host.API + _getAssistInfoURI,
assistLogInfoURL: c.Host.API + _getAssistLogInfoURI,
assistLogsURL: c.Host.API + _getAssistLogsURI,
assistLogAddURL: c.Host.API + _addAssistLogURI,
assistListURL: c.Host.API + _getAssistURI,
assistLogRevocURL: c.Host.API + _revocAssistLogURI,
assistStatURL: c.Host.API + _getAssistStatURI,
assistLogObjURL: c.Host.API + _getAssistLogObjURI,
liveStatusURL: c.Host.Live + _liveStatus,
liveAddAssistURL: c.Host.Live + _liveAddAssist,
liveDelAssistURL: c.Host.Live + _liveDelAssist,
liveRevocBannedURL: c.Host.Live + _liveRevocBanned,
liveAssistsURL: c.Host.Live + _liveAssists,
liveCheckAssURL: c.Host.Live + _liveCheckAssist,
}
return
}

View File

@@ -0,0 +1,45 @@
package assist
import (
"flag"
"go-common/app/interface/main/creative/conf"
"os"
"strings"
"testing"
"gopkg.in/h2non/gock.v1"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.creative")
flag.Set("conf_token", "96b6a6c10bb311e894c14a552f48fef8")
flag.Set("tree_id", "2305")
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/creative.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
m.Run()
os.Exit(0)
}
func httpMock(method, url string) *gock.Request {
r := gock.New(url)
r.Method = strings.ToUpper(method)
d.client.SetTransport(gock.DefaultTransport)
return r
}

View File

@@ -0,0 +1,231 @@
package assist
import (
"context"
"net/http"
"net/url"
"strconv"
"time"
"go-common/app/interface/main/creative/model/assist"
"go-common/library/ecode"
"go-common/library/log"
gtime "go-common/library/time"
)
const (
// api
_liveStatus = "/user/v1/UserRoom/isAnchor"
_liveAddAssist = "/live_user/v1/RoomAdmin/add"
_liveDelAssist = "/live_user/v1/RoomAdmin/del"
_liveRevocBanned = "/live_user/v1/RoomSilent/del"
_liveAssists = "/live_user/v1/RoomAdmin/get_by_anchor"
_liveCheckAssist = "/live_user/v1/RoomAdmin/is_admin"
)
// LiveStatus check if user opened live room. 0:yes 500401: no
func (d *Dao) LiveStatus(c context.Context, mid int64, ip string) (ok int8, err error) {
var req *http.Request
params := url.Values{}
params.Set("uid", strconv.FormatInt(mid, 10))
if req, err = http.NewRequest("GET", d.liveStatusURL+"?"+params.Encode(), nil); err != nil {
log.Error("LiveStatus url(%s) error(%v)", d.liveStatusURL+"?"+params.Encode(), err)
err = ecode.CreativeLiveErr
return
}
req.Header.Set("X-BiliLive-UID", strconv.FormatInt(mid, 10))
var res struct {
Code int `json:"code"`
}
if err = d.client.Do(c, req, &res); err != nil {
log.Error("LiveStatus url(%s) response(%+v) error(%v)", d.liveStatusURL+"?"+params.Encode(), res, err)
err = ecode.CreativeLiveErr
return
}
if res.Code == 500401 {
return
}
if res.Code != 0 {
log.Error("LiveStatus url(%s) res(%v)", d.liveStatusURL+"?"+params.Encode(), res)
err = ecode.Int(res.Code)
return
}
ok = 1
return
}
// LiveAddAssist add assist in live room 120013: 直播间不存在
func (d *Dao) LiveAddAssist(c context.Context, mid, assistMid int64, cookie, ip string) (err error) {
var req *http.Request
params := url.Values{}
params.Set("admin", strconv.FormatInt(assistMid, 10))
params.Set("anchor_id", strconv.FormatInt(mid, 10))
if req, err = http.NewRequest("POST", d.liveAddAssistURL+"?"+params.Encode(), nil); err != nil {
log.Error("LiveAddAssist url(%s) error(%v)", d.liveAddAssistURL+"?"+params.Encode(), err)
err = ecode.CreativeLiveErr
return
}
req.Header.Set("X-BiliLive-UID", strconv.FormatInt(mid, 10))
req.Header.Set("Cookie", cookie)
var res struct {
Code int `json:"code"`
Message string `json:"message"`
}
if err = d.client.Do(c, req, &res); err != nil {
log.Error("LiveAddAssist url(%s) response(%+v) error(%v)", d.liveAddAssistURL+"?"+params.Encode(), res, err)
err = ecode.CreativeLiveErr
return
}
if res.Code == 120013 {
log.Error("LiveAddAssist url(%s) mid(%d) not opened(%v)", d.liveAddAssistURL+"?"+params.Encode(), mid, 120013)
err = ecode.CreativeLiveNotOpenErr
return
}
if res.Code != 0 {
log.Error("LiveAddAssist url(%s) res(%v)", d.liveAddAssistURL+"?"+params.Encode(), res)
err = ecode.Int(res.Code)
return
}
return
}
// LiveDelAssist del assist in live room
func (d *Dao) LiveDelAssist(c context.Context, mid, assistMid int64, cookie, ip string) (err error) {
var req *http.Request
params := url.Values{}
params.Set("admin", strconv.FormatInt(assistMid, 10))
params.Set("anchor_id", strconv.FormatInt(mid, 10))
if req, err = http.NewRequest("POST", d.liveDelAssistURL+"?"+params.Encode(), nil); err != nil {
log.Error("LiveDelAssist url(%s) error(%v)", d.liveDelAssistURL+"?"+params.Encode(), err)
err = ecode.CreativeLiveErr
return
}
req.Header.Set("X-BiliLive-UID", strconv.FormatInt(mid, 10))
req.Header.Set("Cookie", cookie)
var res struct {
Code int `json:"code"`
Message string `json:"message"`
}
if err = d.client.Do(c, req, &res); err != nil {
log.Error("LiveDelAssist url(%s) response(%+v) error(%v)", d.liveDelAssistURL+"?"+params.Encode(), res, err)
err = ecode.CreativeLiveErr
return
}
if res.Code == 120013 {
log.Error("LiveDelAssist url(%s) mid(%d) not opened(%v)", d.liveDelAssistURL+"?"+params.Encode(), mid, 120013)
err = ecode.CreativeLiveNotOpenErr
return
}
if res.Code != 0 {
log.Error("LiveDelAssist url(%s) res(%v)", d.liveDelAssistURL+"?"+params.Encode(), res)
err = ecode.Int(res.Code)
return
}
return
}
// LiveBannedRevoc recover assist banned state
func (d *Dao) LiveBannedRevoc(c context.Context, mid int64, banID, cookie, ip string) (err error) {
var req *http.Request
params := url.Values{}
params.Set("uid", strconv.FormatInt(mid, 10))
params.Set("id", banID)
if req, err = http.NewRequest("POST", d.liveRevocBannedURL+"?"+params.Encode(), nil); err != nil {
log.Error("liveRevocBanned url(%s) error(%v)", d.liveRevocBannedURL+"?"+params.Encode(), err)
err = ecode.CreativeLiveErr
return
}
req.Header.Set("X-BiliLive-UID", strconv.FormatInt(mid, 10))
req.Header.Set("Cookie", cookie)
var res struct {
Code int `json:"code"`
Message string `json:"message"`
}
if err = d.client.Do(c, req, &res); err != nil {
log.Error("liveRevocBanned url(%s) response(%+v) error(%v)", d.liveRevocBannedURL+"?"+params.Encode(), res, err)
err = ecode.CreativeLiveErr
return
}
if res.Code != 0 {
log.Error("liveRevocBanned url(%s) res(%v)", d.liveRevocBannedURL+"?"+params.Encode(), res)
err = ecode.Int(res.Code)
return
}
return
}
// LiveAssists get assists from live
func (d *Dao) LiveAssists(c context.Context, mid int64, ip string) (assists []*assist.LiveAssist, err error) {
var req *http.Request
params := url.Values{}
params.Set("anchor_id", strconv.FormatInt(mid, 10))
if req, err = http.NewRequest("GET", d.liveAssistsURL+"?"+params.Encode(), nil); err != nil {
log.Error("LiveAssists url(%s) error(%v)", d.liveAssistsURL+"?"+params.Encode(), err)
err = ecode.CreativeLiveErr
return
}
req.Header.Set("X-BiliLive-UID", strconv.FormatInt(mid, 10))
var res struct {
Code int `json:"code"`
Data []*assist.LiveAssist `json:"data"`
}
if err = d.client.Do(c, req, &res); err != nil {
log.Error("LiveAssists url(%s) response(%+v) error(%v)", d.liveAssistsURL+"?"+params.Encode(), res, err)
err = ecode.CreativeLiveErr
return
}
if res.Code == 120013 {
err = nil
return
}
if res.Code != 0 {
log.Error("LiveAssists url(%s) res(%v)", d.liveAssistsURL+"?"+params.Encode(), res)
err = ecode.Int(res.Code)
return
}
assists = res.Data
// set ctime
for _, ass := range assists {
intTime, err := time.Parse("2006-01-02 15:04:05", ass.Datetime)
if err == nil {
var ctime gtime.Time
ctime.Scan(intTime)
ass.CTime = ctime - 8*3600 // adjust timezone for fe
}
}
return
}
// LiveCheckAssist check assist in live room
func (d *Dao) LiveCheckAssist(c context.Context, mid, assistMid int64, ip string) (isAss int8, err error) {
var req *http.Request
params := url.Values{}
params.Set("uid", strconv.FormatInt(assistMid, 10))
params.Set("anchor_id", strconv.FormatInt(mid, 10))
if req, err = http.NewRequest("POST", d.liveCheckAssURL+"?"+params.Encode(), nil); err != nil {
log.Error("LiveCheckAssist url(%s) error(%v)", d.liveCheckAssURL+"?"+params.Encode(), err)
err = ecode.CreativeLiveErr
return
}
req.Header.Set("X-BiliLive-UID", strconv.FormatInt(mid, 10))
var res struct {
Code int `json:"code"`
}
if err = d.client.Do(c, req, &res); err != nil {
log.Error("LiveCheckAssist url(%s) response(%+v) error(%v)", d.liveCheckAssURL+"?"+params.Encode(), res, err)
err = ecode.CreativeLiveErr
return
}
if res.Code == 120013 {
log.Error("LiveCheckAssist url(%s) mid(%d) not opened(%v)", d.liveCheckAssURL+"?"+params.Encode(), mid, 120013)
err = ecode.CreativeLiveNotOpenErr
return
}
if res.Code != 0 {
log.Error("LiveCheckAssist url(%s) res(%v)", d.liveCheckAssURL+"?"+params.Encode(), res)
err = ecode.Int(res.Code)
return
}
isAss = 1
return
}

View File

@@ -0,0 +1,159 @@
package assist
import (
"context"
"net/url"
"strconv"
"testing"
"go-common/app/interface/main/creative/model/assist"
"github.com/smartystreets/goconvey/convey"
)
func TestAssistLiveStatus(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
ip = ""
res = struct {
Code int `json:"code"`
}{
Code: 0,
}
)
convey.Convey("LiveStatus", t, func(ctx convey.C) {
httpMock("GET", d.liveStatusURL+"?uid="+strconv.FormatInt(mid, 10)).Reply(0).JSON(res)
ok, err := d.LiveStatus(c, mid, ip)
ctx.Convey("Then err should be nil.ok should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(ok, convey.ShouldNotBeNil)
})
})
}
var msgRes = struct {
Code int `json:"code"`
Message string `json:"message"`
}{
Code: 0,
Message: "message",
}
func TestAssistLiveAddAssist(t *testing.T) {
var (
c = context.TODO()
mid = int64(1)
assistMid = int64(10)
cookie = ""
ip = ""
params = url.Values{}
)
params.Set("admin", strconv.FormatInt(assistMid, 10))
params.Set("anchor_id", strconv.FormatInt(mid, 10))
convey.Convey("LiveAddAssist", t, func(ctx convey.C) {
httpMock("POST", d.liveAddAssistURL+"?"+params.Encode()).
Reply(0).JSON(msgRes)
err := d.LiveAddAssist(c, mid, assistMid, cookie, ip)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestAssistLiveDelAssist(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
assistMid = int64(0)
cookie = ""
ip = ""
params = url.Values{}
)
params.Set("admin", strconv.FormatInt(assistMid, 10))
params.Set("anchor_id", strconv.FormatInt(mid, 10))
convey.Convey("LiveDelAssist", t, func(ctx convey.C) {
httpMock("POST", d.liveDelAssistURL+"?"+params.Encode()).Reply(0).JSON(msgRes)
err := d.LiveDelAssist(c, mid, assistMid, cookie, ip)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestAssistLiveBannedRevoc(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
banID = ""
cookie = ""
ip = ""
params = url.Values{}
)
params.Set("uid", strconv.FormatInt(mid, 10))
params.Set("id", banID)
convey.Convey("LiveBannedRevoc", t, func(ctx convey.C) {
httpMock("POST", d.liveRevocBannedURL+"?"+params.Encode()).Reply(200).JSON(msgRes)
err := d.LiveBannedRevoc(c, mid, banID, cookie, ip)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestAssistLiveAssists(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
ip = ""
params = url.Values{}
res = struct {
Code int `json:"code"`
Data []*assist.LiveAssist `json:"data"`
}{
Code: 0,
Data: []*assist.LiveAssist{
{
AssistMid: 0,
RoomID: 0,
CTime: 0,
Datetime: "",
},
},
}
)
params.Set("anchor_id", strconv.FormatInt(mid, 10))
convey.Convey("LiveAssists", t, func(ctx convey.C) {
httpMock("GET", d.liveAssistsURL+"?"+params.Encode()).Reply(200).JSON(res)
assists, err := d.LiveAssists(c, mid, ip)
ctx.Convey("Then err should be nil.assists should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(assists, convey.ShouldNotBeNil)
})
})
}
func TestAssistLiveCheckAssist(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
assistMid = int64(0)
ip = ""
params = url.Values{}
res = struct {
Code int `json:"code"`
}{
Code: 0,
}
)
params.Set("uid", strconv.FormatInt(assistMid, 10))
params.Set("anchor_id", strconv.FormatInt(mid, 10))
convey.Convey("LiveCheckAssist", t, func(ctx convey.C) {
httpMock("POST", d.liveCheckAssURL+"?"+params.Encode()).Reply(200).JSON(res)
isAss, err := d.LiveCheckAssist(c, mid, assistMid, ip)
ctx.Convey("Then err should be nil.isAss should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(isAss, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,54 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"cover.go",
"dao.go",
],
importpath = "go-common/app/interface/main/creative/dao/bfs",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = [
"cover_test.go",
"dao_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf: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",
],
)

View File

@@ -0,0 +1,59 @@
package bfs
import (
"bytes"
"context"
"io/ioutil"
"net/http"
"fmt"
"go-common/library/log"
)
// UpVideoCovers upload video covers.
func (d *Dao) UpVideoCovers(c context.Context, covers []string) (cvs []string, err error) {
var (
nfsURL string
)
for _, cv := range covers {
// get nfs file
bs, err := d.bvcCover(cv)
if err != nil || len(bs) == 0 {
log.Error("d.UpVideoCovers(%s) error(%v) or bs==0", nfsURL, err)
continue
}
// up to bfs
bfsPath, err := d.UploadArc(c, http.DetectContentType(bs), bytes.NewReader(bs))
if err != nil {
log.Error("d.UpVideoCovers raw url(%s) error(%v)", cv, err)
continue
}
// parse bfs return path
if err != nil {
log.Error("url.Parse(%v) error(%v)", bfsPath, err)
continue
}
cvs = append(cvs, bfsPath)
log.Info("UpVideoCovers cover(%s) bfs (%s)", cv, bfsPath)
}
return
}
// bvcCover http get bvc cover bytes.
func (d *Dao) bvcCover(url string) (bs []byte, err error) {
resp, err := d.client.Get(url)
if err != nil {
log.Error("s.client.Get(%v) error(%v)", url, err)
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
err = fmt.Errorf("get NFS file faild, url(%s) http status: %d", url, resp.StatusCode)
return
}
// read bytes
if bs, err = ioutil.ReadAll(resp.Body); err != nil {
log.Error("ioutil.ReadAll error(%v)", err)
}
return
}

View File

@@ -0,0 +1,42 @@
package bfs
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
var mockHeader = map[string]string{"location": "mockLocation", "code": "200"}
func TestBfsUpVideoCovers(t *testing.T) {
var (
c = context.TODO()
covers = []string{
"http://static.hdslb.com/images/transparent.gif",
}
)
convey.Convey("UpVideoCovers", t, func(ctx convey.C) {
httpMock(_method, _url).Reply(200).SetHeaders(mockHeader)
httpMock("GET", covers[0]).Reply(200).JSON("mock byte")
cvs, err := d.UpVideoCovers(c, covers)
ctx.Convey("Then err should be nil.cvs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(cvs, convey.ShouldResemble, []string{"mockLocation"})
})
})
}
func TestBfsbvcCover(t *testing.T) {
var (
url = "http://static.hdslb.com/images/transparent.gif"
)
convey.Convey("bvcCover", t, func(ctx convey.C) {
httpMock("GET", url).Reply(200).JSON("mock byte")
bs, err := d.bvcCover(url)
ctx.Convey("Then err should be nil.bs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(bs, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,316 @@
package bfs
import (
"bytes"
"context"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"errors"
"fmt"
"hash"
"io"
"io/ioutil"
"net"
"net/http"
nurl "net/url"
"strconv"
"strings"
"time"
"go-common/app/interface/main/creative/conf"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_bucket = "archive"
_url = "http://bfs.bilibili.co/bfs/archive/"
_method = "PUT"
_key = "8d4e593ba7555502"
_secret = "0bdbd4c7caeeddf587c3c4daec0475"
)
var (
errUpload = errors.New("Upload failed")
errDownload = errors.New("Download out image link failed")
)
// Dao is bfs dao.
type Dao struct {
c *conf.Config
client *http.Client
captureCli *http.Client
}
// New new a bfs dao.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
client: &http.Client{
Timeout: time.Duration(c.BFS.Timeout),
},
captureCli: &http.Client{
Timeout: time.Duration(time.Second),
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return ecode.RequestErr
},
},
}
return d
}
// Upload upload bfs.
func (d *Dao) Upload(c context.Context, fileType string, bs []byte) (location string, err error) {
req, err := http.NewRequest(d.c.BFS.Method, d.c.BFS.URL, bytes.NewBuffer(bs))
if err != nil {
log.Error("http.NewRequest error (%v) | fileType(%s)", err, fileType)
return
}
expire := time.Now().Unix()
authorization := authorize(d.c.BFS.Key, d.c.BFS.Secret, d.c.BFS.Method, d.c.BFS.Bucket, expire)
req.Header.Set("Host", d.c.BFS.URL)
req.Header.Add("Date", fmt.Sprint(expire))
req.Header.Add("Authorization", authorization)
req.Header.Add("Content-Type", fileType)
// timeout
ctx, cancel := context.WithTimeout(c, time.Duration(d.c.BFS.Timeout))
req = req.WithContext(ctx)
defer cancel()
resp, err := d.client.Do(req)
if err != nil {
log.Error("d.Client.Do error(%v) | url(%s)", err, d.c.BFS.URL)
err = ecode.BfsUploadServiceUnavailable
return
}
if resp.StatusCode != http.StatusOK {
log.Error("Upload http.StatusCode nq http.StatusOK (%d) | url(%s)", resp.StatusCode, d.c.BFS.URL)
err = errUpload
return
}
header := resp.Header
code := header.Get("Code")
if code != strconv.Itoa(http.StatusOK) {
log.Error("strconv.Itoa err, code(%s) | url(%s)", code, d.c.BFS.URL)
err = errUpload
return
}
location = header.Get("Location")
return
}
// UploadArc upload bfs to archive bucket.
func (d *Dao) UploadArc(c context.Context, fileType string, body io.Reader) (location string, err error) {
req, err := http.NewRequest(_method, _url, body)
if err != nil {
log.Error("http.NewRequest error (%v) | fileType(%s)", err, fileType)
return
}
expire := time.Now().Unix()
authorization := authorize(_key, _secret, _method, _bucket, expire)
req.Header.Set("Host", _url)
req.Header.Add("Date", fmt.Sprint(expire))
req.Header.Add("Authorization", authorization)
req.Header.Add("Content-Type", fileType)
// timeout
c, cancel := context.WithTimeout(c, time.Duration(d.c.BFS.Timeout))
req = req.WithContext(c)
defer cancel()
resp, err := d.client.Do(req)
if err != nil {
log.Error("d.Client.Do error(%v) | url(%s)", err, _url)
err = ecode.BfsUploadServiceUnavailable
return
}
if resp.StatusCode != http.StatusOK {
log.Error("Upload http.StatusCode nq http.StatusOK (%d) | url(%s)", resp.StatusCode, _url)
err = errUpload
return
}
header := resp.Header
code := header.Get("Code")
if code != strconv.Itoa(http.StatusOK) {
log.Error("strconv.Itoa err, code(%s) | url(%s)", code, _url)
err = errUpload
return
}
location = header.Get("Location")
return
}
// authorize returns authorization for upload file to bfs
func authorize(key, secret, method, bucket string, expire int64) (authorization string) {
var (
content string
mac hash.Hash
signature string
)
content = fmt.Sprintf("%s\n%s\n\n%d\n", method, bucket, 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
}
// UploadByFile upload local img file.
func (d *Dao) UploadByFile(c context.Context, imgpath string) (location string, err error) {
data, err := ioutil.ReadFile(imgpath)
if err != nil {
log.Error("UploadByFile ioutil.ReadFile error (%v) | imgpath(%s)", err, imgpath)
return
}
fileType := http.DetectContentType(data)
if fileType != "image/jpeg" && fileType != "image/png" {
log.Error("file type not allow file type(%s)", fileType)
err = ecode.CreativeArticleImageTypeErr
}
body := new(bytes.Buffer)
_, err = body.Write(data)
if err != nil {
log.Error("body.Write error (%v)", err)
return
}
req, err := http.NewRequest(_method, _url, body)
if err != nil {
log.Error("http.NewRequest error (%v) | fileType(%s)", err, fileType)
return
}
expire := time.Now().Unix()
authorization := authorize(_key, _secret, _method, _bucket, expire)
req.Header.Set("Host", _url)
req.Header.Add("Date", fmt.Sprint(expire))
req.Header.Add("Authorization", authorization)
req.Header.Add("Content-Type", fileType)
// timeout
c, cancel := context.WithTimeout(c, time.Duration(d.c.BFS.Timeout))
req = req.WithContext(c)
defer cancel()
resp, err := d.client.Do(req)
if err != nil {
log.Error("d.Client.Do error(%v) | url(%s)", err, _url)
err = ecode.BfsUploadServiceUnavailable
return
}
if resp.StatusCode != http.StatusOK {
log.Error("Upload http.StatusCode nq http.StatusOK (%d) | url(%s)", resp.StatusCode, _url)
err = errUpload
return
}
header := resp.Header
code := header.Get("Code")
if code != strconv.Itoa(http.StatusOK) {
log.Error("strconv.Itoa err, code(%s) | url(%s)", code, _url)
err = errUpload
return
}
location = header.Get("Location")
return
}
//Capture performs a HTTP Get request for the image url and upload bfs.
func (d *Dao) Capture(c context.Context, url string) (loc string, size int, err error) {
if err = checkURL(url); err != nil {
return
}
bs, ct, err := d.download(c, url)
if err != nil {
return
}
size = len(bs)
if size == 0 {
log.Error("capture image size(%d)|url(%s)", size, url)
return
}
if ct != "image/jpeg" && ct != "image/jpg" && ct != "image/png" && ct != "image/gif" {
log.Error("capture not allow image file type(%s)", ct)
err = ecode.CreativeArticleImageTypeErr
return
}
loc, err = d.Upload(c, ct, bs)
return loc, size, err
}
func (d *Dao) download(c context.Context, url string) (bs []byte, ct string, err error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
log.Error("capture http.NewRequest error(%v)|url (%s)", err, url)
return
}
// timeout
ctx, cancel := context.WithTimeout(c, 800*time.Millisecond)
req = req.WithContext(ctx)
defer cancel()
resp, err := d.captureCli.Do(req)
if err != nil {
log.Error("capture d.client.Do error(%v)|url(%s)", err, url)
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
log.Error("capture http.StatusCode nq http.StatusOK(%d)|url(%s)", resp.StatusCode, url)
err = errDownload
return
}
if bs, err = ioutil.ReadAll(resp.Body); err != nil {
log.Error("capture ioutil.ReadAll error(%v)", err)
err = errDownload
return
}
ct = http.DetectContentType(bs)
return
}
func checkURL(url string) (err error) {
// http || https
if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
log.Error("capture url invalid(%s)", url)
err = ecode.RequestErr
return
}
u, err := nurl.Parse(url)
if err != nil {
log.Error("capture url.Parse error(%v)", err)
err = ecode.RequestErr
return
}
// make sure ip is public. avoid ssrf
ips, err := net.LookupIP(u.Host) // take from 1st argument
if err != nil {
log.Error("capture url(%s) LookupIP failed", url)
err = ecode.RequestErr
return
}
if len(ips) == 0 {
log.Error("capture url(%s) LookupIP length 0", url)
err = ecode.RequestErr
return
}
for _, v := range ips {
if !isPublicIP(v) {
log.Error("capture url(%s) is not public ip(%v)", url, v)
err = ecode.RequestErr
return
}
}
return
}
func isPublicIP(IP net.IP) bool {
if IP.IsLoopback() || IP.IsLinkLocalMulticast() || IP.IsLinkLocalUnicast() {
return false
}
if ip4 := IP.To4(); ip4 != nil {
switch true {
case ip4[0] == 10:
return false
case ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31:
return false
case ip4[0] == 192 && ip4[1] == 168:
return false
default:
return true
}
}
return false
}

View File

@@ -0,0 +1,132 @@
package bfs
import (
"context"
"flag"
"github.com/bouk/monkey"
"github.com/smartystreets/goconvey/convey"
"go-common/app/interface/main/creative/conf"
"gopkg.in/h2non/gock.v1"
"io/ioutil"
"net"
"os"
"strings"
"testing"
)
var (
d *Dao
defaultImg = "https://avatars3.githubusercontent.com/u/12002442"
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.creative")
flag.Set("conf_token", "96b6a6c10bb311e894c14a552f48fef8")
flag.Set("tree_id", "2305")
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/creative.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
m.Run()
os.Exit(0)
}
func httpMock(method, url string) *gock.Request {
r := gock.New(url)
r.Method = strings.ToUpper(method)
d.client.Transport = gock.DefaultTransport
return r
}
func TestBfsUpload(t *testing.T) {
convey.Convey("Upload", t, func(ctx convey.C) {
var (
c = context.Background()
fileType = ""
bs = []byte("")
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
httpMock(d.c.BFS.Method, d.c.BFS.URL).Reply(200).SetHeaders(mockHeader).JSON("mockByte")
location, err := d.Upload(c, fileType, bs)
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 TestBfsUploadByFile(t *testing.T) {
convey.Convey("UploadByFile", t, func(ctx convey.C) {
var (
c = context.Background()
imgpath = defaultImg
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
monkey.Patch(ioutil.ReadFile, func(_ string) ([]byte, error) {
return []byte{}, nil
})
httpMock(_method, _url).Reply(200).SetHeaders(mockHeader)
location, err := d.UploadByFile(c, imgpath)
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 TestBfsCapture(t *testing.T) {
convey.Convey("Capture", t, func(ctx convey.C) {
var (
c = context.Background()
url = defaultImg
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
httpMock("GET", url).Reply(200).SetHeaders(mockHeader)
loc, size, err := d.Capture(c, url)
ctx.Convey("Then err should be nil.loc,size should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(size, convey.ShouldNotBeNil)
ctx.So(loc, convey.ShouldNotBeNil)
})
})
})
}
func TestBfscheckURL(t *testing.T) {
convey.Convey("checkURL", t, func(ctx convey.C) {
var (
url = defaultImg
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := checkURL(url)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestBfsisPublicIP(t *testing.T) {
convey.Convey("isPublicIP", t, func(ctx convey.C) {
var IP = net.ParseIP("127.0.0.1")
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := isPublicIP(IP)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}

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",
"rpc.go",
],
importpath = "go-common/app/interface/main/creative/dao/coin",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//app/service/main/coin/api:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = [
"dao_test.go",
"rpc_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,24 @@
package coin
import (
"go-common/app/interface/main/creative/conf"
coinclient "go-common/app/service/main/coin/api"
)
// Dao str
type Dao struct {
c *conf.Config
coinClient coinclient.CoinClient
}
// New fn
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
}
var err error
if d.coinClient, err = coinclient.NewClient(c.CoinClient); err != nil {
panic(err)
}
return
}

View File

@@ -0,0 +1,35 @@
package coin
import (
"flag"
"go-common/app/interface/main/creative/conf"
"os"
"testing"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.creative")
flag.Set("conf_token", "96b6a6c10bb311e894c14a552f48fef8")
flag.Set("tree_id", "2305")
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/creative.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
m.Run()
os.Exit(0)
}

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