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,21 @@
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/interface/main/report-click/cmd:all-srcs",
"//app/interface/main/report-click/conf:all-srcs",
"//app/interface/main/report-click/dao:all-srcs",
"//app/interface/main/report-click/http:all-srcs",
"//app/interface/main/report-click/model:all-srcs",
"//app/interface/main/report-click/service:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,336 @@
#### report-click 点击上报
##### Version 2.17.6
> 1. 增加heartbeat/mobile上报失败的接口
> 2. heartbeat/mobile中增加build号的prom上报
##### Version 2.17.5
> 1. 修复h5播放上报的cookie中的did无法解析出正确的ftime的问题
##### Version 2.17.4
> 1. h5播放上报的ip改用metadata中的ip
##### Version 2.17.3
> 1. http Shutdown
##### Version 2.17.2
> 1. 将inline_play_heartbeat改为inline_play_to_view
##### Version 2.17.1
> 1. IPv4 fix
##### Version 2.17.0
> 1. 新增inline播放超10秒计入播放数
> 2. 原有的auto_play改为inline_play_begininline开播和inline_play_heartbeatinline播放结束
> 3. play中新增session参数
> 4. cache.New改为Fanout
##### Version 2.16.15
> 1. IPv6 fix
##### Version 2.16.14
> 1. IPv6
##### Version 2.16.13
> 1. 动态自动播放 from 711,7111,712,7151,7161,7163,7171,7181 增加播放计数
##### Version 2.16.12
> 1. 删除 Topic:ArchiveClick-T databus
> 2. 删除model
##### Version 2.16.11
> 1. /x/report/heartbeat/mobile auto_play(2) ===> /x/report/click/android2 & ios
##### Version 2.16.10
> 1. copy buf
##### Version 2.16.9
> 1. detail_play_time&list_play_time
##### Version 2.16.8
> 1. autoPlay
##### Version 2.16.7
> 1. merge databus
##### Version 2.16.6
> 1. delete csrf
##### Version 2.16.5
> 1. RemoteIP()--> metadata.RemoteIP
##### Version 2.16.4
> 1. h5 click 优化播放数上报
##### Version 2.16.3
> 1. 自动播放
##### Version 2.16.2
> 1. 播放时长返回ts 时间
##### Version 2.16.1
> 1. mid 0
##### Version 2.16.0
> 1. bm
##### Version 2.15.0
> 1. update infoc sdk
##### Version 2.14.6
> 1. 播放时长增加 epid_status play_status user_status 字段
##### Version 2.14.5
> 1. 播放时长增加 play_mode device from 字段
> 2. 点击上报增加 play_mode platform device mobi_app 字段
> 3. 去掉kafka
##### Version 2.14.4
> 1. 增大服务端超时范围
##### Version 2.14.3
> 1. 修复mobileapp 接口上报参数mobile_app至mobi_app
##### Version 2.14.2
> 1.account依赖接入discovery
##### Version 2.14.1
> 1.使用account-service v7
##### Version 2.14.0
> 1.增加h5 外链点击上报
> 2.迁移interface main大目录
##### Version 2.13.2
> 1.删除 老infoc通道上报数据
##### Version 2.13.1
> 1.删除statsd
##### Version 2.13.0
> 1.点展数据双写kafka
> 2.增加Android TV点展接口
##### Version 2.12.8
> 1.增加app端统计上报播放时长需求
> 2.修改infoc2的配置方式
##### Version 2.12.7
> 1.fix context.TODO()
##### Version 2.12.6
> 1.rpc.account.card2 to UserInfo
##### Version 2.12.5
> 1.兼容参数avid ios app
##### Version 2.12.4
> 1.针对移动端上报传参mid>0并且没有accesskey或者accesskey校验不通过时使用不同UA标记
##### Version 2.12.3
> 1.针对移动端传accesskey与参数mid不一致UA标记
##### Version 2.12.2
> 1.没有校验通过的和检验通过的用户采用不同的UA进行标记
> 2.增加/x/report/click/outer接口14004警告日志
##### Version 2.12.1
> 1.heartbeat增加新字段playtype上报兼容playtype和play_type
##### Version 2.12.0
> 1.增加app端点展access_key参数
##### Version 2.11.4
> 1.修复移动端mid防刷
##### Version 2.11.3
> 1.心跳日志web端与app端字段个数保持一致
##### Version 2.11.2
> 1.点展增加接口上报字段type、sub_type、sid、epid
##### Version 2.11.1
> 1.增加数据写入Kafka时的异步处理
##### Version 2.11.0
> 1.增加AI&dataPlatfrom 数据上报字段
##### Version 2.10.4
> 1.删除日志
##### Version 2.10.3
> 1.增加sub_type参数
##### Version 2.10.2
> 1.修复web端mid防刷
##### Version 2.10.1
> 1.flash端账号防刷
##### Version 2.10.0
> 1.接入大仓库
##### Version 2.9.0
> 1.优化用户等级
##### Version 2.5.13
> 1.heartbeat 增加pause字段,click增加buvid字段
##### Version 2.5.12
> 1.修改为不区分大小写did兼容客户端
##### Version 2.5.11
> 1.升级go-commongo-business(去掉panic)
> 2.接入prom
> 3.增加对m域名的区分上报
##### Version 2.5.10
> 1.修复IP字段为空
> 2.使用GuestConfigPost和GuestPost
##### Version 2.5.9
> 1.升级infoc2
##### Version 2.5.8
> 1.升级go-business修复csrf
> 2.兼容seasonID
##### Version 2.5.7
> 1.infoc改成一条条发
##### Version 2.5.6
> 1.增加infoc超时
##### Version 2.5.5
> 1.修复csrf
##### Version 2.5.4
> 1.增加infoc错误日志
##### Version 2.5.3
> 1.修复mid认证
##### Version 2.5.2
> 1.更新go-business的infoc2
##### Version 2.5.1
> 1.本地tw
##### Version 2.5.0
> 1.接入新配置中心
> 2.web/heartbeat 改为GuestPost
> 3.report-click接入历史记录rpc
##### Version 2.4.3
> 1.心跳日志双写一份到下沙
##### Version 2.4.2
> 1.monitor ping
##### Version 2.4.1
> 1.平滑发布
##### Version 2.4.0
> 1.增加epid参数
##### Version 2.3.4
> 1.增加配置开关
##### Version 2.3.3
> 1.升级库切identify
##### Version 2.3.2
> 1.先注释掉播放上报
##### Version 2.3.2
> 1.先注释掉播放上报
##### Version 2.3.1
> 1.修复历史进度上报为POST
##### Version 2.3.0
> 1.添加历史进度上报
##### Version 2.2.3
> 1.修复web心跳buvid
##### Version 2.2.2
> 1.拜年祭上报兼容
##### Version 2.2.1
> 1.过滤aid=0的情况
##### Version 2.2.0
> 1.增加web播放器心跳上报
##### Version 2.1.1
> 1.升级vendor
##### Version 2.1.0
> 1.配置中心
> 2.升级vendor
##### Version 2.0.3
> 1.新增播放上报字段
##### Version 2.0.2
> 1.播放上报新增字段
##### Version 2.0.1
> 1.更新infoc vendor支持tcp发
##### Version 2.0.0
> 1.更新底层库依赖
> 2.增加govendor
##### Version 1.2.1
> 1.修复ChecDid bug
##### Version 1.2.0
> 1.h5上报算法优化
> 2.web h5上报接口
##### Version 1.1.0
> 1.支持视频播放上报每隔30s上报一次只打日志
##### Version 1.0.0
> 1.report-click 基础功能

View File

@@ -0,0 +1,16 @@
# Owner
zhangshengchao
liangkai
renyashun
liweijia
peiyifei
# Author
zhangshengchao
renyashun
zhaoshichen
# Reviewer
zhangshengchao
liangkai
renyashun

View File

@@ -0,0 +1,20 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- liangkai
- liweijia
- peiyifei
- renyashun
- zhangshengchao
- zhaoshichen
labels:
- interface
- interface/main/report-click
- main
options:
no_parent_owners: true
reviewers:
- liangkai
- renyashun
- zhangshengchao
- zhaoshichen

View File

@@ -0,0 +1,16 @@
#### report-click
##### 项目简介
> 1.点展上报
##### 编译环境
> 请使用golang v1.8.x以上版本编译执行。
##### 依赖包
> 1.公共包go-common.
##### 编译执行
> 在主目录执行go build.
##### 特别说明
请先认真阅读info文档,项目设计面广泛,每一处修改要倍加仔细.

View File

@@ -0,0 +1,41 @@
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 = ["report-click.toml"],
importpath = "go-common/app/interface/main/report-click/cmd",
tags = ["automanaged"],
deps = [
"//app/interface/main/report-click/conf:go_default_library",
"//app/interface/main/report-click/http:go_default_library",
"//library/log:go_default_library",
"//library/net/trace:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,47 @@
package main
import (
"context"
"flag"
"os"
"os/signal"
"syscall"
"time"
"go-common/app/interface/main/report-click/conf"
"go-common/app/interface/main/report-click/http"
"go-common/library/log"
"go-common/library/net/trace"
)
func main() {
flag.Parse()
if err := conf.Init(); err != nil {
log.Error("conf.Init() error(%v)", err)
panic(err)
}
log.Init(conf.Conf.Xlog)
defer log.Close()
log.Info("report-click start")
trace.Init(conf.Conf.Tracer)
defer trace.Close()
engine := http.New(conf.Conf)
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("report-click get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
ctx, cancel := context.WithTimeout(context.Background(), time.Second*60)
defer cancel()
engine.Shutdown(ctx)
log.Info("report-click exit")
return
case syscall.SIGHUP:
// TODO reload
default:
return
}
}
}

View File

@@ -0,0 +1,171 @@
# This is a TOML document. Boom.
version = "2.0.0"
user = "nobody"
pid = "/tmp/report-click.pid"
dir = "./"
perf = "127.0.0.1:6180"
checkFile = "/data/www/report-click.html"
family = "report-click"
address = ""
env = "dev"
[infoc2]
[infoc2.realTime]
taskID = "000146"
proto = "tcp"
addr = "172.16.113.149:15140"
chanSize = 10240
[infoc2.statistics]
taskID = "000891"
proto = "tcp"
addr = "172.19.100.20:5401"
chanSize = 10240
[tracer]
proto = "udp"
addr = "172.16.33.46:5140"
tag = "platform/report-click"
[xlog]
dir = "/data/log/report-click/"
# [xlog.elk]
# project = "report_click"
# addr = "172.18.20.17:8520"
# chanSize = 1024
[app]
key = "53e2fa226f5ad348"
secret = "3cf6bd1b0ff671021da5f424fea4b04a"
[identify]
whiteAccessKey = ""
whiteMid = 0
csrfOn = false
[identify.app]
key = "53e2fa226f5ad348"
secret = "3cf6bd1b0ff671021da5f424fea4b04a"
[identify.memcache]
name = "go-business/identify"
proto = "tcp"
addr = "172.16.0.148:11211"
active = 5
idle = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
[identify.host]
auth = "http://passport.bilibili.co"
secret = "http://open.bilibili.co"
[identify.httpClient]
key = "53e2fa226f5ad348"
secret = "3cf6bd1b0ff671021da5f424fea4b04a"
dial = "30ms"
timeout = "100ms"
keepAlive = "60s"
[identify.httpClient.breaker]
window = "10s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[identify.httpClient.url]
"http://passport.bilibili.co/intranet/auth/tokenInfo" = {timeout = "100ms"}
"http://passport.bilibili.co/intranet/auth/cookieInfo" = {timeout = "100ms"}
"http://open.bilibili.co/api/getsecret" = {timeout = "500ms"}
[multiHttp]
[multiHttp.outer]
addrs = ["0.0.0.0:6181"]
maxListen = 1000
[multiHttp.local]
addrs = ["0.0.0.0:6182"]
maxListen = 1000
[bm]
addr = "0.0.0.0:6181"
maxListen = 1000
timeout = "800ms"
[accRPC]
policy=""
color=""
[accRPC.client]
proto = "tcp"
timeout = "1s"
timer = 1000
[accRPC.client.breaker]
window ="3s"
sleep ="100ms"
bucket = 10
ratio = 0.5
request = 100
[accRPC.conf]
domain="api.bilibili.co"
key="170e302355453683"
secret="6037a2b881a004e23349d8d3120097ba"
[hisRPC]
pullInterval = "10s"
[hisRPC.client]
proto = "tcp"
addr = "172.16.33.56:6009"
timeout = "1s"
timer = 1000
[hisRPC.client.breaker]
window ="3s"
sleep ="100ms"
bucket = 10
ratio = 0.5
request = 100
[hisRPC.zookeeper]
root = "/microservice/history/"
addrs = ["172.16.33.54:2181"]
timeout = "30s"
[databus]
[databus.Merge]
key = "170e302355453683"
secret= "6037a2b881a004e23349d8d3120097ba"
group= "ClickMerge-MainCommunity-P"
topic= "ClickMerge-T"
action="pub"
name = "report-click"
proto = "tcp"
addr = "172.16.33.158:6205"
idle = 100
active = 100
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
[kafkaProducer]
brokers = ["172.16.33.54:9092"]
sync = true
[kafkaProducer.zookeeper]
root = "/kafka"
addrs = ["172.16.33.54:2181"]
timeout = "30s"
# WebReport :0 关闭,1 全开,2 只开番剧 ,ground:true 落地false 不落地
[click]
webSecret = "903ef99b5be1300f843b4adf2ca55410"
outSecret = "57184ba1409f2a151f6a595630a882c7"
aesKey = ""
aesIv = ""
aesSalt = ""
aesKey2 = ""
aesIv2 = ""
aesSalt2 = ""
playTopic = "count-log"
WebReport = 1
ground = true
reportURL = "http://api.bilibili.co/x/internal/v2/history/report"
From = [761]
FromInline = [7140]
InlineDuration = 10

View File

@@ -0,0 +1,39 @@
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/report-click/conf",
tags = ["automanaged"],
deps = [
"//library/conf:go_default_library",
"//library/log:go_default_library",
"//library/log/infoc:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/auth:go_default_library",
"//library/net/http/blademaster/middleware/verify:go_default_library",
"//library/net/rpc:go_default_library",
"//library/net/trace:go_default_library",
"//library/queue/databus: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,100 @@
package conf
import (
"flag"
"go-common/library/conf"
"go-common/library/log"
"go-common/library/log/infoc"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/auth"
"go-common/library/net/http/blademaster/middleware/verify"
"go-common/library/net/rpc"
"go-common/library/net/trace"
"go-common/library/queue/databus"
"github.com/BurntSushi/toml"
)
const (
configKey = "report-click.toml"
)
// global conf
var (
confPath string
Conf *Config
)
// Infoc2 Infoc2.
type Infoc2 struct {
RealTime *infoc.Config
Statistics *infoc.Config
}
// Config config .
type Config struct {
Infoc2 *Infoc2
Env string
Tracer *trace.Config
Xlog *log.Config
App *bm.App
BM *bm.ServerConfig
Auth *auth.Config
Verify *verify.Config
AccRPC *rpc.ClientConfig
HisRPC *rpc.ClientConfig
DataBus *Databus
Click *Click
}
// Databus .
type Databus struct {
Merge *databus.Config
}
// Click click config.
type Click struct {
WebSecret string
OutSecret string
// aes
AesKey string
AesIv string
AesSalt string
// aes2
AesKey2 string
AesIv2 string
AesSalt2 string
From []int64
FromInline []int64
InlineDuration int64 // inline play duration line, 10s
}
func init() {
flag.StringVar(&confPath, "conf", "", "config path")
}
// Init init conf
func Init() (err error) {
if confPath == "" {
return configCenter()
}
_, err = toml.DecodeFile(confPath, &Conf)
return
}
func configCenter() (err error) {
var (
ok bool
value string
client *conf.Client
)
if client, err = conf.New(); err != nil {
return
}
if value, ok = client.Value(configKey); !ok {
panic(err)
}
_, err = toml.Decode(value, &Conf)
return
}

View File

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

View File

@@ -0,0 +1,43 @@
package dao
import (
"bytes"
"sync"
"go-common/app/interface/main/report-click/conf"
"go-common/library/queue/databus"
)
// Dao report-click dao
type Dao struct {
c *conf.Config
merge *databus.Databus
msgs chan []byte
spliter []byte
bfp sync.Pool
}
// New dao.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
merge: databus.New(c.DataBus.Merge),
msgs: make(chan []byte, 1024),
spliter: []byte("\001"),
bfp: sync.Pool{
New: func() interface{} {
return bytes.NewBuffer([]byte{})
},
},
}
go d.pubproc()
return
}
// Close close kafka connection.
func (d *Dao) Close() {
d.msgs <- d.spliter
if d.merge != nil {
d.merge.Close()
}
}

View File

@@ -0,0 +1,33 @@
package dao
import (
"flag"
"os"
"testing"
"go-common/app/interface/main/report-click/conf"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.community.report-click")
flag.Set("conf_token", "09afcee4301f9ca250ddb0eccf7e0131")
flag.Set("tree_id", "2288")
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")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
os.Exit(m.Run())
}

View File

@@ -0,0 +1,110 @@
package dao
import (
"bytes"
"context"
"time"
"go-common/library/log"
)
// Play push databus .
func (d *Dao) Play(c context.Context, plat, aid, cid, part, mid, level, ftime, stime, did, ip, agent, buvid, cookieSid, refer, typeID, subType, sid, epid, playMode, platform, device, mobiAapp, autoPlay, session string) {
bf := d.bfp.Get().(*bytes.Buffer)
bf.WriteString(plat)
bf.Write(d.spliter)
bf.WriteString(aid)
bf.Write(d.spliter)
bf.WriteString(cid)
bf.Write(d.spliter)
bf.WriteString(part)
bf.Write(d.spliter)
bf.WriteString(mid)
bf.Write(d.spliter)
bf.WriteString(level)
bf.Write(d.spliter)
bf.WriteString(ftime)
bf.Write(d.spliter)
bf.WriteString(stime)
bf.Write(d.spliter)
bf.WriteString(did)
bf.Write(d.spliter)
bf.WriteString(ip)
bf.Write(d.spliter)
bf.WriteString(agent)
bf.Write(d.spliter)
bf.WriteString(buvid)
bf.Write(d.spliter)
bf.WriteString(cookieSid)
bf.Write(d.spliter)
bf.WriteString(refer)
bf.Write(d.spliter)
bf.WriteString(typeID)
bf.Write(d.spliter)
bf.WriteString(subType)
bf.Write(d.spliter)
bf.WriteString(sid)
bf.Write(d.spliter)
bf.WriteString(epid)
bf.Write(d.spliter)
bf.WriteString(playMode)
bf.Write(d.spliter)
bf.WriteString(platform)
bf.Write(d.spliter)
bf.WriteString(device)
bf.Write(d.spliter)
bf.WriteString(mobiAapp)
bf.Write(d.spliter)
bf.WriteString(autoPlay)
bf.Write(d.spliter)
bf.WriteString(session)
buf := make([]byte, len(bf.Bytes()))
copy(buf, bf.Bytes())
select {
case d.msgs <- buf:
default:
log.Warn("d.Play() msgs is full !")
}
bf.Reset()
d.bfp.Put(bf)
}
// pubproc send history to databus.
func (d *Dao) pubproc() {
var (
msg []byte
ms [][]byte
ticker = time.NewTicker(time.Second)
)
for {
select {
case msg = <-d.msgs:
if len(msg) == 0 {
continue
}
if d.spliter[0] != msg[0] {
ms = append(ms, msg)
if len(ms) < 100 {
continue
}
}
case <-ticker.C:
}
if len(ms) == 0 {
continue
}
d.mergePub(ms)
ms = make([][]byte, 0, 100)
}
}
func (d *Dao) mergePub(ms [][]byte) {
key := string(ms[0][:50])
for j := 0; j < 3; j++ {
if err := d.merge.Send(context.Background(), key, ms); err == nil {
break
}
log.Error("d.merge.Send(%+v)", ms)
}
}

View File

@@ -0,0 +1,74 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoPlay(t *testing.T) {
convey.Convey("Play", t, func(ctx convey.C) {
var (
c = context.Background()
plat = ""
aid = ""
cid = ""
part = ""
mid = ""
level = ""
ftime = ""
stime = ""
did = ""
ip = ""
agent = ""
buvid = ""
cookieSid = ""
refer = ""
typeID = ""
subType = ""
sid = ""
epid = ""
playMode = ""
platform = ""
device = ""
mobiAapp = ""
autoPlay = ""
session = ""
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
ctx.Convey("No return values", func(ctx convey.C) {
d.Play(c, plat, aid, cid, part, mid, level, ftime, stime, did, ip, agent, buvid, cookieSid, refer, typeID, subType, sid, epid, playMode, platform, device, mobiAapp, autoPlay, session)
ctx.SkipSo(" 丹丹让这么写的")
})
})
})
}
func TestDaopubproc(t *testing.T) {
convey.Convey("pubproc", t, func(ctx convey.C) {
ctx.Convey("No return values", func(ctx convey.C) {
d.pubproc()
ctx.SkipSo(" 丹丹让这么写的")
})
})
}
func TestDaomergePub(t *testing.T) {
var (
ms = [][]byte{}
)
for i := 0; i < 100; i++ {
var tt = []byte{}
for j := 0; j < 100; j++ {
tt = append(tt, []byte("1")...)
}
ms = append(ms, tt)
}
convey.Convey("mergePub", t, func(ctx convey.C) {
ctx.Convey("No return values", func(ctx convey.C) {
d.mergePub(ms)
ctx.SkipSo(" 丹丹让这么写的")
})
})
}

View File

@@ -0,0 +1,44 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"click.go",
"err_report.go",
"http.go",
"player.go",
],
importpath = "go-common/app/interface/main/report-click/http",
tags = ["automanaged"],
deps = [
"//app/interface/main/report-click/conf:go_default_library",
"//app/interface/main/report-click/model:go_default_library",
"//app/interface/main/report-click/service:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/log/infoc:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/auth:go_default_library",
"//library/net/http/blademaster/middleware/verify:go_default_library",
"//library/net/metadata:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,271 @@
package http
import (
"io/ioutil"
"net/http"
"strconv"
"time"
"go-common/app/interface/main/report-click/conf"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/metadata"
)
const (
_platWeb = "0"
_platH5 = "1"
_platOuter = "2"
_platIos = "3"
_platAndroid = "4"
_platAndroidTV = "5"
)
var _expireCookie = time.Date(2022, time.November, 10, 23, 0, 0, 0, time.UTC)
// webClick write the archive data.
func webClick(c *bm.Context) {
err := flashPlay(c, _platWeb, conf.Conf.Click.WebSecret)
c.JSON(nil, err)
}
// outerClick write the archive data.
func outerClick(c *bm.Context) {
err := flashPlay(c, _platOuter, conf.Conf.Click.OutSecret)
c.JSON(nil, err)
}
// iosClick write the archive data.
func iosClick(c *bm.Context) {
err := mobilePlay(c, conf.Conf.Click.AesKey, conf.Conf.Click.AesIv, conf.Conf.Click.AesSalt, _platIos)
c.JSON(nil, err)
}
// androidClick write the archive data.
func androidClick(c *bm.Context) {
err := mobilePlay(c, conf.Conf.Click.AesKey, conf.Conf.Click.AesIv, conf.Conf.Click.AesSalt, _platAndroid)
c.JSON(nil, err)
}
// android2Click write the archive data.
func android2Click(c *bm.Context) {
err := mobilePlay(c, conf.Conf.Click.AesKey2, conf.Conf.Click.AesIv2, conf.Conf.Click.AesSalt2, _platAndroid)
c.JSON(nil, err)
}
// androidTV == android2Click write the archive data.
func androidTV(c *bm.Context) {
err := mobilePlay(c, conf.Conf.Click.AesKey2, conf.Conf.Click.AesIv2, conf.Conf.Click.AesSalt2, _platAndroidTV)
c.JSON(nil, err)
}
// outerClickH5 h5 outer click same to flash plat .
func outerClickH5(c *bm.Context) {
c.JSON(nil, h5Play(c, _platOuter))
}
// h5Click write the archive data.
func h5Click(c *bm.Context) {
c.JSON(nil, h5Play(c, _platH5))
}
// webH5Click write the archive data.
func webH5Click(c *bm.Context) {
c.JSON(nil, h5Play(c, _platWeb))
}
// flashPlay.
func flashPlay(c *bm.Context, plat, secret string) (err error) {
var (
buvid string
mid int64
ck *http.Cookie
params = c.Request.Form
unix = time.Now()
)
if midInter, ok := c.Get("mid"); ok {
mid = midInter.(int64)
}
if ck, err = c.Request.Cookie("buvid3"); err == nil {
buvid = ck.Value
}
userAgent := c.Request.Header.Get("User-Agent")
refer := c.Request.Header.Get("Referer")
sign := params.Get("sign")
if err = clickSvr.FlashSigned(params, secret, unix); err != nil {
log.Error("clickSvr.FlashSigned() error(%v)", err)
if err == ecode.ClickQuerySignErr {
log.Warn("click sign error(%s,%s,%s,%s)", sign, refer, userAgent, c.Request.Header.Get("Origin"))
}
return
}
midStr := params.Get("mid")
if mid != 0 && midStr != strconv.FormatInt(mid, 10) {
log.Warn("flashPlay stat mid(%d) not equal stat mid(%s)", mid, midStr)
return
}
midStr = strconv.FormatInt(mid, 10)
aid := params.Get("aid")
var cookieSid string
if ck, err := c.Request.Cookie("sid"); err == nil {
cookieSid = ck.Value
}
typeID := params.Get("type")
subType := params.Get("sub_type")
sid := params.Get("sid")
epid := params.Get("epid")
// service.
ip := metadata.String(c, metadata.RemoteIP)
clickSvr.Play(c, plat, aid, params.Get("cid"), params.Get("part"),
midStr, params.Get("lv"), params.Get("ftime"), params.Get("stime"),
params.Get("did"), ip, userAgent, buvid, cookieSid, refer, typeID, subType, sid, epid, "", "", "", "", "", "")
return
}
// mobilePlay.
func mobilePlay(c *bm.Context, aesKey, aesIv, aesSalt, plat string) (err error) {
// check params.
req := c.Request
unix := time.Now()
bs, err := ioutil.ReadAll(req.Body)
if err != nil {
log.Error("ioutil.ReadAll error(%v)", err)
err = ecode.ServerErr
return
}
req.Body.Close()
bs, err = clickSvr.Decrypt(bs, aesKey, aesIv)
if err != nil {
log.Error("clickSvr.Decrypt(%s) error(%d)", bs, err)
return
}
p, err := clickSvr.Verify(bs, aesSalt, unix)
if err != nil {
log.Error("clickSvr.Verify(%s) error(%d)", bs, err)
return
}
req.Form = p // for log
typeID := p.Get("type")
subType := p.Get("sub_type")
sid := p.Get("sid")
epid := p.Get("epid")
playMode := p.Get("play_mode")
platform := p.Get("platform")
device := p.Get("device")
mobiAapp := p.Get("mobi_app")
autoPlay := p.Get("auto_play")
ap, _ := strconv.ParseInt(autoPlay, 10, 64)
// service.
aidStr := p.Get("aid")
var (
accessKey string
midStr = p.Get("mid")
noAccess bool
)
paasMid, _ := strconv.ParseInt(midStr, 10, 64)
accessKey = p.Get("access_key")
if paasMid > 0 && accessKey == "" {
noAccess = true
}
if accessKey != "" {
c.Request.Form.Set("access_key", accessKey)
authSvc.User(c)
mid, ok := c.Get("mid")
if !ok {
log.Warn("idfSvc.Access() access_key", accessKey)
if paasMid > 0 {
noAccess = true
}
}
if mid != nil {
midStr = strconv.FormatInt(mid.(int64), 10)
}
}
refer := c.Request.Header.Get("Referer")
userAgent := c.Request.Header.Get("User-Agent")
if noAccess {
userAgent = userAgent + " (no_accesskey)"
}
if ap == 1 || ap == 2 { // abandon the logic that transforms the plat to 6/7/8/9, keep the plat and modify the UA
userAgent += " (inline_play_begin)"
}
buvid := req.Header.Get("buvid")
var cookieSid string
if ck, err := c.Request.Cookie("sid"); err == nil {
cookieSid = ck.Value
}
ip := metadata.String(c, metadata.RemoteIP)
clickSvr.Play(c, plat, aidStr, p.Get("cid"), p.Get("part"), midStr, p.Get("lv"),
p.Get("ftime"), p.Get("stime"), p.Get("did"), ip, userAgent, buvid,
cookieSid, refer, typeID, subType, sid, epid, playMode, platform, device, mobiAapp, autoPlay, "")
return
}
func h5Play(c *bm.Context, plat string) (err error) {
var (
buvid string
mid int64
ck *http.Cookie
params = c.Request.Form
unix = time.Now()
)
if midInter, ok := c.Get("mid"); ok {
mid = midInter.(int64)
}
if ck, err = c.Request.Cookie("buvid3"); err == nil {
buvid = ck.Value
}
// check params.
st := params.Get("stime")
stime, err := strconv.ParseInt(st, 10, 64)
if err != nil {
err = ecode.ClickQueryFormatErr
return
}
if unix.Unix()-stime > 60 {
err = ecode.ClickServerTimeout
return
}
typeID := params.Get("type")
subType := params.Get("sub_type")
sid := params.Get("sid")
epid := params.Get("epid")
var ft string
// check cookie did
var (
did string
ip = metadata.String(c, metadata.RemoteIP)
)
cookie, err := c.Request.Cookie("rpdid")
if err != nil || cookie.Value == "" {
did = clickSvr.GenDid(ip, unix)
http.SetCookie(c.Writer, &http.Cookie{Name: "rpdid", Value: did, Path: "/", Domain: ".bilibili.com", Expires: _expireCookie})
err = nil
} else {
did = cookie.Value
}
_, ft = clickSvr.CheckDid(did)
if ft == "" {
log.Error("ft null ft:%s,did:%s", ft, did)
return
}
midStr := params.Get("mid")
if mid != 0 && midStr != strconv.FormatInt(mid, 10) {
log.Warn("h5 stat mid(%d) not equal stat mid(%s)", mid, midStr)
return
}
midStr = strconv.FormatInt(mid, 10)
aid := params.Get("aid")
userAgent := c.Request.Header.Get("User-Agent")
var cookieSid string
if ck, err := c.Request.Cookie("sid"); err == nil {
cookieSid = ck.Value
}
refer := c.Request.Header.Get("Referer")
// service.
clickSvr.Play(c, plat, aid, params.Get("cid"), params.Get("part"),
midStr, params.Get("lv"), ft, params.Get("stime"), did,
ip, userAgent, buvid, cookieSid, refer, typeID, subType, sid, epid, "", "", "", "", "", "")
return
}

View File

@@ -0,0 +1,15 @@
package http
import (
"go-common/app/interface/main/report-click/model"
bm "go-common/library/net/http/blademaster"
)
func errReport(c *bm.Context) {
v := new(model.ErrReport)
if err := c.Bind(v); err != nil {
return
}
clickSvr.ErrReport(c, v)
c.JSON(nil, nil)
}

View File

@@ -0,0 +1,90 @@
package http
import (
"time"
"go-common/app/interface/main/report-click/conf"
"go-common/app/interface/main/report-click/service"
"go-common/library/log"
"go-common/library/log/infoc"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/auth"
"go-common/library/net/http/blademaster/middleware/verify"
)
var (
clickSvr *service.Service
authSvc *auth.Auth
verifySvc *verify.Verify
infocRealTime *infoc.Infoc
infocStatistics *infoc.Infoc
fromMap = make(map[int64]bool)
fromInlineMap = make(map[int64]bool)
inlineDuration int64
)
// New http init.
func New(c *conf.Config) (engine *bm.Engine) {
clickSvr = service.New(c)
authSvc = auth.New(c.Auth)
verifySvc = verify.New(c.Verify)
infocRealTime = infoc.New(c.Infoc2.RealTime)
infocStatistics = infoc.New(c.Infoc2.Statistics)
for _, v := range c.Click.From {
fromMap[v] = true
}
for _, v := range c.Click.FromInline { // init inline play "from"
fromInlineMap[v] = true
}
inlineDuration = c.Click.InlineDuration // inline play duration line
engine = bm.DefaultServer(c.BM)
engine.Use(bm.Recovery(), bm.Logger())
outerRouter(engine)
if err := engine.Start(); err != nil {
log.Error("engine.Start() error(%v)", err)
panic(err)
}
return
}
func outerRouter(e *bm.Engine) {
e.GET("/monitor/ping", ping)
e.POST("/x/report/click/web", authSvc.GuestWeb, webClick)
e.POST("/x/report/click/outer", authSvc.GuestWeb, outerClick)
e.POST("/x/stat/web", authSvc.GuestWeb, webClick)
e.POST("/x/stat/outer", authSvc.GuestWeb, outerClick)
click := e.Group("/x/report/click")
{
click.GET("/now", serverNow)
click.POST("/h5", authSvc.Guest, h5Click)
click.POST("/h5/outer", authSvc.Guest, outerClickH5) // nocsrf
click.POST("/ios", authSvc.Guest, iosClick)
click.POST("/android", authSvc.Guest, androidClick)
click.POST("/android2", authSvc.Guest, android2Click)
click.POST("/web/h5", authSvc.Guest, webH5Click)
click.POST("/android/tv", authSvc.Guest, androidTV)
}
report := e.Group("/x/report/")
{
report.POST("/player", verifySvc.Verify, reportPlayer) // old 30s heart
report.POST("/heartbeat", verifySvc.Verify, reportHeartbeat) // new app 30s heart
report.POST("/heartbeat/mobile", verifySvc.Verify, heartbeatMobile)
report.POST("/web/heartbeat", authSvc.Guest, webHeartbeat) // web 30s heart
}
stat := e.Group("/x/stat")
{
stat.GET("/now", serverNow)
stat.POST("/err_report", errReport)
stat.POST("/h5", authSvc.Guest, h5Click)
stat.POST("/ios", authSvc.Guest, iosClick)
stat.POST("/android", authSvc.Guest, androidClick)
stat.POST("/android2", authSvc.Guest, android2Click)
}
}
func ping(c *bm.Context) {}
func serverNow(c *bm.Context) {
data := map[string]int64{"now": time.Now().Unix()}
c.JSON(data, nil)
}

View File

@@ -0,0 +1,195 @@
package http
import (
"strconv"
"time"
"go-common/app/interface/main/report-click/model"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/metadata"
)
// reportPlayer write the archive data.
func reportPlayer(c *bm.Context) {
params := c.Request.Form
header := c.Request.Header
buvid := header.Get("Buvid")
displayid := header.Get("Display-ID")
ts := params.Get("ts")
aid := params.Get("aid")
cid := params.Get("cid")
playedTime := params.Get("played_time")
mid := params.Get("mid")
moAp := params.Get("mobi_app")
typeID := params.Get("type")
subType := params.Get("sub_type")
sid := params.Get("sid")
epid := params.Get("epid")
infocRealTime.Info(ts, buvid, displayid, mid, aid, cid, playedTime, strconv.FormatInt(time.Now().Unix(), 10), "1", moAp, "", typeID, subType, sid, epid, "")
c.JSON(nil, nil)
}
// reportHeartbeat write the archive data.
func reportHeartbeat(c *bm.Context) {
params := c.Request.Form
header := c.Request.Header
buvid := header.Get("Buvid")
displayid := header.Get("Display-ID")
sts := params.Get("start_ts")
aid := params.Get("aid")
if aid == "" {
aid = params.Get("avid")
}
cid := params.Get("cid")
playedTime := params.Get("played_time")
mid := params.Get("mid")
moAp := params.Get("mobi_app")
typeID := params.Get("type")
subType := params.Get("sub_type")
sid := params.Get("sid")
epid := params.Get("epid")
playType := params.Get("play_type")
if playType == "" {
playType = params.Get("playtype")
}
infocRealTime.Info(sts, buvid, displayid, mid, aid, cid, playedTime, strconv.FormatInt(time.Now().Unix(), 10), "2", moAp, "", typeID, subType, sid, epid, playType)
c.JSON(nil, nil)
}
func heartbeatMobile(c *bm.Context) {
params := c.Request.Form
header := c.Request.Header
sts := params.Get("start_ts")
build := params.Get("build")
buvid := header.Get("Buvid")
mobileApp := params.Get("mobi_app")
device := params.Get("device")
platform := params.Get("platform")
session := params.Get("session")
mid := params.Get("mid")
aid := params.Get("aid")
cid := params.Get("cid")
sid := params.Get("sid")
epid := params.Get("epid")
tp := params.Get("type")
subType := params.Get("sub_type")
quality := params.Get("quality")
totalTime := params.Get("total_time")
pausedTime := params.Get("paused_time")
playedTime := params.Get("played_time")
videoDuration := params.Get("video_duration")
playType := params.Get("play_type")
networkType := params.Get("network_type")
playProgressTimeLast := params.Get("last_play_progress_time")
playProgressTimeMax := params.Get("max_play_progress_time")
playMode := params.Get("play_mode")
from := params.Get("from")
epidStatus := params.Get("epid_status")
playStatus := params.Get("play_status")
userStatus := params.Get("user_status")
actualPlayedTime := params.Get("actual_played_time")
autoPlay := params.Get("auto_play")
detailPlayTime := params.Get("detail_play_time")
listPlayTime := params.Get("list_play_time")
userAgent := c.Request.Header.Get("User-Agent")
ts, err := strconv.ParseInt(sts, 10, 64)
if err != nil || ts <= 0 {
ts = time.Now().Unix()
sts = strconv.FormatInt(ts, 10)
}
// NOTE /x/report//heartbeat/mobile auto_play = 2 ===> /x/report/click/android2 & ios
// (自动播放的上报>> 2:天马feed流inline) 播放时长转成播放点击
autoPlayInt, _ := strconv.ParseInt(autoPlay, 10, 64)
fromInt, _ := strconv.ParseInt(from, 10, 64)
videoDurInt, _ := strconv.ParseInt(videoDuration, 10, 64)
playedTimeInt, _ := strconv.ParseInt(playedTime, 10, 64)
var needCompens bool
if (autoPlayInt == 2 || autoPlayInt == 1) && fromMap[fromInt] {
userAgent = userAgent + " (inline_play_to_view)" // change from auto_play to inline_play_heartbeat, then to inline_play_to_view
needCompens = true
}
if (autoPlayInt == 2 || autoPlayInt == 1) && fromInlineMap[fromInt] && playedTimeInt >= inlineDuration && (videoDurInt >= playedTimeInt) {
userAgent += " (played_time_enough)" // new logic, if inline play more than 10s, count it also
needCompens = true
}
if needCompens {
var cookieSid, plat string
if ck, err := c.Request.Cookie("sid"); err == nil {
cookieSid = ck.Value
}
ip := metadata.String(c, metadata.RemoteIP)
switch platform {
case "android":
plat = _platAndroid
case "ios":
plat = _platIos
}
clickSvr.Play(c, plat, aid, cid, params.Get("part"), mid, params.Get("lv"),
"0", sts, buvid, ip, userAgent, buvid,
cookieSid, c.Request.Header.Get("Referer"), tp,
subType, sid, epid, playMode, platform, device, mobileApp, autoPlay, session)
log.Warn("plat:%s,aid:%s,cid:%s,part:%s,mid:%s,lv:%s,0:%s,sts:%s,buvid:%s,ip:%s,userAgent:%s,"+
"buvid:%s,cookieSid:%s,Referer:%s,tp:%s,subType:%s,sid:%s,epid:%s,playMode:%s,"+
"platform:%s,device:%s,mobileApp:%s,autoPlay:%s,session:%s",
plat, aid, cid, params.Get("part"), mid, params.Get("lv"),
"0", sts, buvid, ip, userAgent, buvid,
cookieSid, c.Request.Header.Get("Referer"), tp,
subType, sid, epid, playMode, platform, device, mobileApp, autoPlay, session)
}
buildInt, _ := strconv.ParseInt(build, 10, 64)
clickSvr.SuccReport(c, &model.SuccReport{ // record the success by different build
MobiApp: mobileApp,
Build: buildInt,
})
infocStatistics.Info(sts, build, buvid, mobileApp, platform, session, mid, aid, cid, sid,
epid, tp, subType, quality, totalTime, pausedTime, playedTime, videoDuration,
playType, networkType, playProgressTimeLast, playProgressTimeMax, playMode, device, from, epidStatus, playStatus, userStatus, actualPlayedTime, autoPlay, detailPlayTime, listPlayTime)
data := make(map[string]interface{}, 1)
data["ts"] = ts
c.JSON(data, nil)
}
// webHeartbeat write the archive data.
func webHeartbeat(c *bm.Context) {
var (
buvid, mid, term string
params = c.Request.Form
)
if ck, err := c.Request.Cookie("buvid3"); err == nil {
buvid = ck.Value
}
sts := params.Get("start_ts")
aid := params.Get("aid")
cid := params.Get("cid")
pause := params.Get("pause")
playType := params.Get("play_type")
if playType == "" {
playType = params.Get("playtype")
}
playedTime := params.Get("played_time")
if midI, ok := c.Get("mid"); ok {
mid = strconv.FormatInt(midI.(int64), 10)
}
tp := params.Get("type")
subType := params.Get("sub_type")
sid := params.Get("sid")
if sid == "" {
sid = params.Get("seasonID")
}
epid := params.Get("epid")
dt := params.Get("dt")
if dt == "7" {
// count m.bilibili.com visits times.
term = "h5"
} else {
dt = "2"
term = "web"
}
realtime := params.Get("realtime")
ts := strconv.FormatInt(time.Now().Unix(), 10)
infocRealTime.Info(sts, buvid, "", mid, aid, cid, playedTime, ts, dt, term, pause, tp, subType, sid, epid, playType)
clickSvr.Report(c, playedTime, cid, tp, subType, realtime, aid, mid, sid, epid, dt, ts)
c.JSON(nil, nil)
}

View File

@@ -0,0 +1,28 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["model.go"],
importpath = "go-common/app/interface/main/report-click/model",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
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,30 @@
package model
import "fmt"
const (
_statFmt = "heartbeat_in_%s_%d"
)
// ErrReport def
type ErrReport struct {
MobiApp string `form:"mobi_app" validate:"required"`
Build int64 `form:"build" validate:"required"`
Ecode int `form:"error_code" validate:"required"`
}
// SuccReport def
type SuccReport struct {
MobiApp string `json:"mobi_app"`
Build int64 `json:"build"`
}
// ToProm def.
func (v *SuccReport) ToProm() string {
return fmt.Sprintf(_statFmt, v.MobiApp, v.Build)
}
// ToProm def.
func (v *ErrReport) ToProm() string {
return fmt.Sprintf(_statFmt, v.MobiApp, v.Build)
}

View File

@@ -0,0 +1,65 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/report-click/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"err_report.go",
"ip.go",
"service.go",
],
importpath = "go-common/app/interface/main/report-click/service",
tags = ["automanaged"],
deps = [
"//app/interface/main/history/model:go_default_library",
"//app/interface/main/history/rpc/client:go_default_library",
"//app/interface/main/report-click/conf:go_default_library",
"//app/interface/main/report-click/dao:go_default_library",
"//app/interface/main/report-click/model:go_default_library",
"//app/interface/main/report-click/service/crypto/aes:go_default_library",
"//app/interface/main/report-click/service/crypto/padding:go_default_library",
"//app/service/main/account/model:go_default_library",
"//app/service/main/account/rpc/client:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/metadata:go_default_library",
"//library/stat/prom:go_default_library",
"//library/sync/pipeline/fanout:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/interface/main/report-click/service/crypto/aes:all-srcs",
"//app/interface/main/report-click/service/crypto/cipher:all-srcs",
"//app/interface/main/report-click/service/crypto/padding:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,44 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["aes_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/report-click/service/crypto/padding:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["aes.go"],
importpath = "go-common/app/interface/main/report-click/service/crypto/aes",
tags = ["automanaged"],
deps = [
"//app/interface/main/report-click/service/crypto/cipher:go_default_library",
"//app/interface/main/report-click/service/crypto/padding: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,103 @@
package aes
import (
iaes "crypto/aes"
icipher "crypto/cipher"
"errors"
"go-common/app/interface/main/report-click/service/crypto/cipher"
"go-common/app/interface/main/report-click/service/crypto/padding"
)
var (
ErrAesBlockSize = errors.New("plaintext is not a multiple of the block size")
ErrAesSrcSize = errors.New("ciphertext too short")
ErrAesIVSize = errors.New("iv size is not a block size")
)
// ECBEncrypt aes ecb encrypt.
func ECBEncrypt(src, key []byte, p padding.Padding) ([]byte, error) {
if p == nil {
if len(src) < iaes.BlockSize || len(src)%iaes.BlockSize != 0 {
return nil, ErrAesBlockSize
}
} else {
src = p.Padding(src, iaes.BlockSize)
}
b, err := iaes.NewCipher(key)
if err != nil {
return nil, err
}
mode := cipher.NewECBEncrypter(b)
encryptText := make([]byte, len(src))
mode.CryptBlocks(encryptText, src)
return encryptText, nil
}
// ECBDecrypt aes ecb decrypt.
func ECBDecrypt(src, key []byte, p padding.Padding) ([]byte, error) {
if len(src) < iaes.BlockSize || len(src)%iaes.BlockSize != 0 {
return nil, ErrAesSrcSize
}
b, err := iaes.NewCipher(key)
if err != nil {
return nil, err
}
mode := cipher.NewECBDecrypter(b)
decryptText := make([]byte, len(src))
mode.CryptBlocks(decryptText, src)
if p == nil {
return decryptText, nil
} else {
return p.Unpadding(decryptText, iaes.BlockSize)
}
}
// CBCEncrypt aes cbc encrypt.
func CBCEncrypt(src, key, iv []byte, p padding.Padding) ([]byte, error) {
// check iv
if len(iv) != iaes.BlockSize {
return nil, ErrAesIVSize
}
if p == nil {
// if no padding check src
if len(src) < iaes.BlockSize || len(src)%iaes.BlockSize != 0 {
return nil, ErrAesSrcSize
}
} else {
// padding
src = p.Padding(src, iaes.BlockSize)
}
block, err := iaes.NewCipher(key)
if err != nil {
return nil, err
}
mode := icipher.NewCBCEncrypter(block, iv)
encryptText := make([]byte, len(src))
mode.CryptBlocks(encryptText, src)
return encryptText, nil
}
// CBCDecrypt aes cbc decrypt.
func CBCDecrypt(src, key, iv []byte, p padding.Padding) ([]byte, error) {
// check src
if len(src) < iaes.BlockSize || len(src)%iaes.BlockSize != 0 {
return nil, ErrAesSrcSize
}
// check iv
if len(iv) != iaes.BlockSize {
return nil, ErrAesIVSize
}
block, err := iaes.NewCipher(key)
if err != nil {
return nil, err
}
mode := icipher.NewCBCDecrypter(block, iv)
decryptText := make([]byte, len(src))
mode.CryptBlocks(decryptText, src)
if p == nil {
return decryptText, nil
} else {
return p.Unpadding(decryptText, iaes.BlockSize)
}
}

View File

@@ -0,0 +1,24 @@
package aes
import (
"testing"
"go-common/app/interface/main/report-click/service/crypto/padding"
. "github.com/smartystreets/goconvey/convey"
)
func TestAES(t *testing.T) {
var (
aesKey = ""
aesIv = ""
bs = []byte("this is test massage ")
)
Convey("aes test ", t, func() {
bs, _ = CBCDecrypt(bs, []byte(aesKey), []byte(aesIv), padding.PKCS5)
ECBDecrypt(bs, []byte(aesKey), padding.PKCS5)
bs = []byte("this is test massage ")
bs, _ = CBCEncrypt(bs, []byte(aesKey), []byte(aesIv), padding.PKCS5)
CBCDecrypt(bs, []byte(aesKey), []byte(aesIv), padding.PKCS5)
})
}

View File

@@ -0,0 +1,40 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["ecb_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/report-click/service/crypto/padding:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["ecb.go"],
importpath = "go-common/app/interface/main/report-click/service/crypto/cipher",
tags = ["automanaged"],
)
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,76 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Electronic Code Book (ECB) mode.
// ECB provides confidentiality by assigning a fixed ciphertext block to each
// plaintext block.
// See NIST SP 800-38A, pp 08-09
package cipher
import (
"crypto/cipher"
)
type ecb struct {
b cipher.Block
blockSize int
}
func newECB(b cipher.Block) *ecb {
return &ecb{
b: b,
blockSize: b.BlockSize(),
}
}
type ecbEncrypter ecb
// NewECBEncrypter returns a BlockMode which encrypts in electronic code book
// mode, using the given Block.
func NewECBEncrypter(b cipher.Block) cipher.BlockMode {
return (*ecbEncrypter)(newECB(b))
}
func (x *ecbEncrypter) BlockSize() int { return x.blockSize }
func (x *ecbEncrypter) CryptBlocks(dst, src []byte) {
if len(src)%x.blockSize != 0 {
panic("crypto/cipher: input not full blocks")
}
if len(dst) < len(src) {
panic("crypto/cipher: output smaller than input")
}
for len(src) > 0 {
x.b.Encrypt(dst, src[:x.blockSize])
src = src[x.blockSize:]
dst = dst[x.blockSize:]
}
}
type ecbDecrypter ecb
// NewECBDecrypter returns a BlockMode which decrypts in electronic code book
// mode, using the given Block.
func NewECBDecrypter(b cipher.Block) cipher.BlockMode {
return (*ecbDecrypter)(newECB(b))
}
func (x *ecbDecrypter) BlockSize() int { return x.blockSize }
func (x *ecbDecrypter) CryptBlocks(dst, src []byte) {
if len(src)%x.blockSize != 0 {
panic("crypto/cipher: input not full blocks")
}
if len(dst) < len(src) {
panic("crypto/cipher: output smaller than input")
}
for len(src) > 0 {
x.b.Decrypt(dst, src[:x.blockSize])
src = src[x.blockSize:]
dst = dst[x.blockSize:]
}
}

View File

@@ -0,0 +1,29 @@
package cipher
import (
iaes "crypto/aes"
"testing"
"go-common/app/interface/main/report-click/service/crypto/padding"
. "github.com/smartystreets/goconvey/convey"
)
func TestECB(t *testing.T) {
var (
aesKey = "903ef9925be1300f843b41df2ca55410"
bs = []byte("this is test massage ")
)
Convey("cipher test ", t, func() {
var p = padding.PKCS5
bs = p.Padding(bs, iaes.BlockSize)
b, _ := iaes.NewCipher([]byte(aesKey))
ecbe := NewECBEncrypter(b)
encryptText := make([]byte, len(bs))
ecbe.CryptBlocks(encryptText, bs)
ecbd := NewECBDecrypter(b)
decryptText := make([]byte, len(bs))
ecbd.CryptBlocks(decryptText, bs)
p.Unpadding(bs, iaes.BlockSize)
})
}

View File

@@ -0,0 +1,43 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["pkcs5_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/report-click/service/crypto/cipher:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"padding.go",
"pkcs5.go",
],
importpath = "go-common/app/interface/main/report-click/service/crypto/padding",
tags = ["automanaged"],
)
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,15 @@
package padding
import (
"errors"
)
var (
ErrPaddingSize = errors.New("pkcs5 padding size error")
)
// Padding is interface used for crypto.
type Padding interface {
Padding(src []byte, blockSize int) []byte
Unpadding(src []byte, blockSize int) ([]byte, error)
}

View File

@@ -0,0 +1,30 @@
package padding
var (
PKCS5 = &pkcs5{}
)
// pkcs5Padding is a pkcs5 padding struct.
type pkcs5 struct{}
// Padding implements the Padding interface Padding method.
func (p *pkcs5) Padding(src []byte, blockSize int) []byte {
srcLen := len(src)
padLen := byte(blockSize - (srcLen % blockSize))
pd := make([]byte, srcLen+int(padLen))
copy(pd, src)
for i := srcLen; i < len(pd); i++ {
pd[i] = padLen
}
return pd
}
// Unpadding implements the Padding interface Unpadding method.
func (p *pkcs5) Unpadding(src []byte, blockSize int) ([]byte, error) {
srcLen := len(src)
paddingLen := int(src[srcLen-1])
if paddingLen >= srcLen || paddingLen > blockSize {
return nil, ErrPaddingSize
}
return src[:srcLen-paddingLen], nil
}

View File

@@ -0,0 +1,29 @@
package padding
import (
iaes "crypto/aes"
"testing"
"go-common/app/interface/main/report-click/service/crypto/cipher"
. "github.com/smartystreets/goconvey/convey"
)
func TestECB(t *testing.T) {
var (
aesKey = "903ef9925be1300f843b41df2ca55410"
bs = []byte("this is test massage ")
)
Convey("cipher test ", t, func() {
var p = PKCS5
bs = p.Padding(bs, iaes.BlockSize)
b, _ := iaes.NewCipher([]byte(aesKey))
ecbe := cipher.NewECBEncrypter(b)
encryptText := make([]byte, len(bs))
ecbe.CryptBlocks(encryptText, bs)
ecbd := cipher.NewECBDecrypter(b)
decryptText := make([]byte, len(bs))
ecbd.CryptBlocks(decryptText, bs)
p.Unpadding(bs, iaes.BlockSize)
})
}

View File

@@ -0,0 +1,17 @@
package service
import (
"context"
"go-common/app/interface/main/report-click/model"
)
// ErrReport reports the failures of calling the api "heartbeat/mobile"
func (s *Service) ErrReport(ctx context.Context, req *model.ErrReport) {
s.promErr.Incr(req.ToProm())
}
// SuccReport reports the success of calling the api "heartbeat/mobile"
func (s *Service) SuccReport(ctx context.Context, req *model.SuccReport) {
s.promInfo.Incr(req.ToProm())
}

View File

@@ -0,0 +1,137 @@
package service
import (
"fmt"
"math"
"net"
)
const sixtyTwo uint64 = 62
func encode(num uint64) string {
var numStr string
for num != 0 {
r := num % sixtyTwo
if r <= 9 {
numStr = string(byte(r)+48) + numStr
} else if r <= 35 {
numStr = string(byte(r)+87) + numStr
} else {
numStr = string(byte(r)+29) + numStr
}
num = num / sixtyTwo
}
return numStr
}
func decode(bs []byte) uint64 {
f := 0.0
l := len(bs) - 1
for _, v := range bs {
if v >= 97 {
v -= 87
} else if v >= 65 {
v -= 29
} else {
v -= 48
}
f = f + float64(v)*math.Pow(float64(sixtyTwo), float64(l))
l = l - 1
}
return uint64(f)
}
// ntoIPv6 conver uint32 to ip addr.
func ntoIPv6(sip []string) string {
if len(sip) != 3 {
return ""
}
ip := make(net.IP, net.IPv6len)
sum := decode([]byte(sip[0]))
ip[0] = byte((sum >> 40) & 0xFF)
ip[1] = byte((sum >> 32) & 0xFF)
ip[2] = byte((sum >> 24) & 0xFF)
ip[3] = byte((sum >> 16) & 0xFF)
ip[4] = byte((sum >> 8) & 0xFF)
ip[5] = byte(sum & 0xFF)
sum = decode([]byte(sip[1]))
ip[6] = byte((sum >> 40) & 0xFF)
ip[7] = byte((sum >> 32) & 0xFF)
ip[8] = byte((sum >> 24) & 0xFF)
ip[9] = byte((sum >> 16) & 0xFF)
ip[10] = byte((sum >> 8) & 0xFF)
ip[11] = byte(sum & 0xFF)
sum = decode([]byte(sip[2]))
ip[12] = byte((sum >> 24) & 0xFF)
ip[13] = byte((sum >> 16) & 0xFF)
ip[14] = byte((sum >> 8) & 0xFF)
ip[15] = byte(sum & 0xFF)
return ip.String()
}
// ipv6AtoN conver ip addr to uint32.
func ipv6AtoN(ip net.IP) (sip string) {
ip = ip.To16()
if ip == nil {
return
}
sum := uint64(ip[0]) << 40
sum += uint64(ip[1]) << 32
sum += uint64(ip[2]) << 24
sum += uint64(ip[3]) << 16
sum += uint64(ip[4]) << 8
sum += uint64(ip[5])
sip = encode(sum)
sum = uint64(ip[6]) << 40
sum += uint64(ip[7]) << 32
sum += uint64(ip[8]) << 24
sum += uint64(ip[9]) << 16
sum += uint64(ip[10]) << 8
sum += uint64(ip[11])
sip = sip + ":" + encode(sum)
sum = uint64(ip[12]) << 24
sum += uint64(ip[13]) << 16
sum += uint64(ip[14]) << 8
sum += uint64(ip[15])
sip = sip + ":" + encode(sum)
fmt.Println(sip, "len:", len(sip))
return
}
// netAtoN conver ipv4 addr to uint32.
func netAtoN(ip net.IP) (sum uint32) {
ip = ip.To4()
if ip == nil {
return
}
sum += uint32(ip[0]) << 24
sum += uint32(ip[1]) << 16
sum += uint32(ip[2]) << 8
sum += uint32(ip[3])
return sum
}
// netNtoA conver uint32 to ipv4 addr.
func netNtoA(sum uint32) string {
ip := make(net.IP, net.IPv4len)
ip[0] = byte((sum >> 24) & 0xFF)
ip[1] = byte((sum >> 16) & 0xFF)
ip[2] = byte((sum >> 8) & 0xFF)
ip[3] = byte(sum & 0xFF)
return ip.String()
}
func parseIP(s string) (net.IP, bool) {
for i := 0; i < len(s); i++ {
switch s[i] {
case '.':
return net.ParseIP(s), true
case ':':
return net.ParseIP(s), false
}
}
return nil, false
}

View File

@@ -0,0 +1,260 @@
package service
import (
"bytes"
"context"
"crypto/md5"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"fmt"
"net/url"
"strconv"
"strings"
"time"
hmdl "go-common/app/interface/main/history/model"
hrpc "go-common/app/interface/main/history/rpc/client"
"go-common/app/interface/main/report-click/conf"
"go-common/app/interface/main/report-click/dao"
"go-common/app/interface/main/report-click/service/crypto/aes"
"go-common/app/interface/main/report-click/service/crypto/padding"
accmdl "go-common/app/service/main/account/model"
accrpc "go-common/app/service/main/account/rpc/client"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
"go-common/library/stat/prom"
"go-common/library/sync/pipeline/fanout"
)
// 0 1 2 3 4 5 6 7 8 9 : <-> d w o i k p s x m q l
// 48 49 50 51 52 53 54 55 56 57 58 <-> 100 119 111 105 107 112 115 120 109 113 108
var ecKeys = map[rune]rune{
48: 119,
49: 111,
50: 105,
51: 107,
52: 112,
53: 115,
54: 120,
55: 109,
56: 113,
57: 108,
58: 100,
119: 48,
111: 49,
105: 50,
107: 51,
112: 52,
115: 53,
120: 54,
109: 55,
113: 56,
108: 57,
100: 58,
}
// Service service struct info.
type Service struct {
c *conf.Config
d *dao.Dao
accRPC *accrpc.Service3
hisRPC *hrpc.Service
cache *fanout.Fanout
promErr *prom.Prom
promInfo *prom.Prom
}
// New service.
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
d: dao.New(c),
accRPC: accrpc.New3(c.AccRPC),
hisRPC: hrpc.New(c.HisRPC),
cache: fanout.New("cache", fanout.Worker(1), fanout.Buffer(1024)),
promErr: prom.BusinessErrCount,
promInfo: prom.BusinessInfoCount,
}
return
}
// FlashSigned flash Signed.
func (s *Service) FlashSigned(params url.Values, secret string, now time.Time) (err error) {
st := params.Get("stime")
stime, err := strconv.ParseInt(st, 10, 64)
if err != nil {
err = ecode.ClickQueryFormatErr
return
}
if now.Unix()-stime > 60 {
err = ecode.ClickServerTimeout
return
}
sign := params.Get("sign")
params.Del("sign")
mh := md5.Sum([]byte(strings.ToLower(params.Encode()) + secret))
if hex.EncodeToString(mh[:]) != sign {
err = ecode.ClickQuerySignErr
}
return
}
// Decrypt decrypt bytes by aes key and iv.
func (s *Service) Decrypt(src []byte, aesKey, aesIv string) (res []byte, err error) {
res, err = aes.CBCDecrypt(src, []byte(aesKey), []byte(aesIv), padding.PKCS5)
if err != nil {
log.Error("aes.CBCDecrypt(%s, %s, %s) error(%v)", base64.StdEncoding.EncodeToString(src), s.c.Click.AesKey, s.c.Click.AesIv, err)
err = ecode.ClickAesDecryptErr
}
return
}
// Verify verify bytes from post body.
func (s *Service) Verify(src []byte, aesSalt string, now time.Time) (p url.Values, err error) {
p, err = url.ParseQuery(string(src))
if err != nil {
err = ecode.ClickQueryFormatErr
return
}
// check server time
st := p.Get("stime")
stime, err := strconv.ParseInt(st, 10, 64)
if err != nil {
err = ecode.ClickQueryFormatErr
return
}
if now.Unix()-stime > 60*3 {
err = ecode.ClickServerTimeout
return
}
// verify sign
sign := p.Get("sign")
sbs, err := hex.DecodeString(sign)
if err != nil {
log.Error("hex.DecodeString(%s) error(%v)", sign, err)
err = ecode.ClickQuerySignErr
return
}
p.Del("sign")
// sha 256
h := sha256.New()
// h.Write([]byte(strings.ToLower(p.Encode())))
h.Write([]byte(p.Encode()))
h.Write([]byte(aesSalt))
bs := h.Sum(nil)
// bytes queal
if !bytes.Equal(sbs, bs) {
log.Error("hmac.Equal(%s, %x) params(%s) not equal", sign, bs, p.Encode())
err = ecode.ClickHmacSignErr
}
return
}
// Play send play count to kafka.
func (s *Service) Play(c context.Context, plat, aid, cid, part, mid, level, ftime, stime, did, ip, agent, buvid, cookieSid, refer, typeID, subType, sid, epid, playMode, platform, device, mobiAapp, autoPlay, session string) {
if aid == "" || aid == "0" {
return
}
m, errP := strconv.ParseInt(mid, 10, 64)
if errP != nil {
log.Warn("strconv.ParseInt(%s) error(%v)", mid, errP)
mid = "0"
}
if m != 0 {
arg := &accmdl.ArgMid{Mid: m}
res, err := s.accRPC.Card3(c, arg)
if err != nil {
log.Error("s.accRPC.UserInfo() error(%v)", err)
return
}
if res.Silence == 1 {
log.Warn("user mid(%d) spacesta(%d) too lower", m, res.Silence)
return
}
level = fmt.Sprintf("%d", res.Level)
}
s.cache.Do(c, func(ctx context.Context) {
s.d.Play(ctx, plat, aid, cid, part, mid, level, ftime, stime, did, ip, agent, buvid, cookieSid, refer, typeID, subType, sid, epid, playMode, platform, device, mobiAapp, autoPlay, session)
})
}
// GenDid gen did.
func (s *Service) GenDid(ip string, now time.Time) string {
var src string
ft := now.Unix() - int64(now.Second())
uip, ok := parseIP(ip)
if uip == nil {
return ""
}
if ok {
src = fmt.Sprintf("%d:%d", netAtoN(uip), ft)
return myEncryptDecrypt(src)
}
fs := encode(uint64(ft))
ipRes := ipv6AtoN(uip)
if len(ipRes) > 25 { // total 32, 25 for ip, 1 for :, 6 for ftime
ipRes = ipRes[:25]
}
return fmt.Sprintf("%s:%s", ipRes, fs)
}
// CheckDid check did.
func (s *Service) CheckDid(did string) (ip, ft string) {
params := strings.Split(did, ":")
if len(params) == 4 {
log.Warn("report click did:%s", did)
return ntoIPv6(params[:3]), fmt.Sprintf("%d", decode([]byte(params[3])))
}
dst := myEncryptDecrypt(did)
params = strings.Split(dst, ":")
if len(params) != 2 {
return
}
ipInt, _ := strconv.ParseInt(params[0], 10, 64)
ip = netNtoA(uint32(ipInt))
ft = params[1]
return
}
func myEncryptDecrypt(src string) (dst string) {
var tmp []rune
for _, k := range src {
if _, ok := ecKeys[k]; !ok {
return ""
}
tmp = append(tmp, ecKeys[k])
}
dst = string(tmp)
return
}
// Report report to history.
func (s *Service) Report(c context.Context, proStr, cidStr, tpStr, subType, realtimeStr, aidStr, midstr, sidStr, epidStr, dtStr, tsStr string) (err error) {
var (
tp, stp, dt int
)
if tp, err = strconv.Atoi(tpStr); err != nil {
log.Warn("Report type:%s", tpStr)
}
stp, _ = strconv.Atoi(subType)
mid, _ := strconv.ParseInt(midstr, 10, 64)
aid, _ := strconv.ParseInt(aidStr, 10, 64)
sid, _ := strconv.ParseInt(sidStr, 10, 64)
epid, _ := strconv.ParseInt(epidStr, 10, 64)
cid, _ := strconv.ParseInt(cidStr, 10, 64)
if aid == 0 && cid == 0 {
return ecode.RequestErr
}
pro, _ := strconv.ParseInt(proStr, 10, 64)
realtime, _ := strconv.ParseInt(realtimeStr, 10, 64)
if dt, err = strconv.Atoi(dtStr); err != nil {
dt = 2
}
ip := metadata.String(c, metadata.RemoteIP)
ts, _ := strconv.ParseInt(tsStr, 10, 64)
history := &hmdl.History{Aid: aid, Sid: sid, Epid: epid, TP: int8(tp), STP: int8(stp), Cid: cid, DT: int8(dt), Pro: pro, Unix: ts}
arg := &hmdl.ArgHistory{Mid: mid, Realtime: realtime, RealIP: ip, History: history}
return s.hisRPC.Add(c, arg)
}

View File

@@ -0,0 +1,55 @@
package service
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/report-click/conf"
. "github.com/smartystreets/goconvey/convey"
)
var svr *Service
func init() {
flag.Parse()
dir, _ := filepath.Abs("../cmd/report-click.toml")
flag.Set("conf", dir)
conf.Init()
svr = New(conf.Conf)
}
func TestReport(t *testing.T) {
var (
c = context.Background()
err error
aid = "11159485"
cid = "18464413"
mid = "35152246"
playedTime = "0"
realtime = "0"
tp = "3"
dt = "2"
bs = []byte("this is test massage ")
)
Convey("Decrypt Verify err should return nil", t, func() {
bs, _ = svr.Decrypt(bs, conf.Conf.Click.AesKey, conf.Conf.Click.AesIv)
svr.Verify(bs, conf.Conf.Click.AesSalt, time.Now())
})
Convey("Report err should return nil", t, func() {
err = svr.Report(c, playedTime, cid, tp, "", realtime, aid, mid, "", "", dt, "1516695880")
So(err, ShouldBeNil)
})
Convey("CheckDid err should return nil", t, func() {
svr.CheckDid("1516695880")
})
Convey("GenDid err should return nil", t, func() {
svr.GenDid("127.0.0.1", time.Now())
})
Convey("Play err should return nil", t, func() {
svr.Play(c, "web", "128546345", "12345", "", "14771787", "1", "", "", "", "127.0.0.1", "2", "1", "1212", "", "1", "3", "2", "4", "", "", "", "", "", "")
})
}