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

View File

@@ -0,0 +1,106 @@
#### favorite
### Version v7.4.1
> 1. web端html特殊字符转义移动端不做转义
### Version v7.4.0
> 1. 播单2.0
### Version v7.3.0
> 1. 代码优化 httpclient 下沉到Dao
### Version v7.2.0
> 1. medialist fix bug
### Version v7.0.0
> 1. medialist
### Version v6.0.1
> 1. del cover cache
### Version v5.4.0
> 1. migrate fav write to grpc
### Version v5.3.7
> 1. fix folder cover cache
### Version v5.3.6
> 1. fix folder cover
### Version v5.3.0
> 1. new search
### Version v5.2.21
> 1. fix del bug
### Version v5.2.19
> 1. upgrade to fav grpc
##### Version v5.2.18
> 1.remove initCol databus
##### Version v5.2.16
> 1.meta data ip
##### Version v5.2.14
> 1.grpc identify
##### Version v5.2.13
> 1.fix favtime order
##### Version v5.2.8
> 1.common config
##### Version v5.2.7
> 1.fix two same folder
##### Version v5.2.6
> 1.fix videofid cache err
##### Version v5.2.5
> 1. fix vmid's folders null
##### Version v5.2.4
> 1. fix fav video page
##### Version v5.2.3
> 1. isFaved migrate service
##### Version v5.2.2
> 1. del video folder redis
##### Version v5.2.1
> 1. add tlist api
##### Version v5.2.0
> 1. update infoc sdk
##### Version 5.1.10
> 1.support supervisor
##### Version 5.1.9
> 1.fix add fav and del fav
##### Version 5.1.8
> 1.fix add fav
##### Version 5.1.7
> 1.add videoFids cache
##### Version 5.1.6
> 1.add videoFids cache
##### Version 5.1.5
> 1.fix covers closure
##### Version 5.1.3
> 1.fix favorites old fid
##### Version 5.1.0
> 1.migrate read favorte service
##### Version 5.0.1
> 1.antispam limit ecode
##### Version 5.0.0
> 1.收藏夹interface 初始化

View File

@@ -0,0 +1,16 @@
# Owner
chenzhihui
caoguoliang
zhapuyu
# Author
libingqi
chenzhihui
zhangshengchao
lujinhui
caoguoliang
# Reviewer
chenzhihui
caoguoliang
zhangshengchao

View File

@@ -0,0 +1,21 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- caoguoliang
- chenzhihui
- libingqi
- lujinhui
- zhangshengchao
- zhapuyu
labels:
- interface
- interface/main/favorite
- main
options:
no_parent_owners: true
reviewers:
- caoguoliang
- chenzhihui
- libingqi
- lujinhui
- zhangshengchao

View File

@@ -0,0 +1,13 @@
#### favorite
##### 项目简介
> 1.用户收藏夹、视频收藏、话题收藏、专栏收藏、小视频收藏、相簿收藏
##### 编译环境
> 请只用golang v1.7.x以上版本编译执行。
##### 依赖包
> 1.公共包go-common
##### 特别说明
> 1.model目录可能会被其他项目引用请谨慎请改并通知各方。

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 = ["favorite-test.toml"],
importpath = "go-common/app/interface/main/favorite/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/favorite/conf:go_default_library",
"//app/interface/main/favorite/http:go_default_library",
"//app/interface/main/favorite/service:go_default_library",
"//library/ecode/tip:go_default_library",
"//library/log:go_default_library",
"//library/net/trace:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,220 @@
# This is a TOML document. Boom.
[log]
dir = "/data/log/favorite/"
#[infoc2]
#taskID = "000078"
#proto = "tcp"
#addr = "172.19.100.20:5401"
#chanSize = 1024
[supervisor]
on = true
begin = "2017-10-01T15:04:05+08:00"
end = "2017-10-22T11:10:05+08:00"
[antispam]
on=true
second=5
n=10
hour=1
m=5
[antispam.redis]
name = "favorite/favorite"
proto = "tcp"
addr = "172.16.33.54:6379"
idle = 100
active = 100
dialTimeout = "500ms"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
expire = "10m"
[fav]
maxFolders = 50
maxPagesize = 30
maxNameLen = 30
maxDescLen = 100
maxOperationNum = 30
expire = "24h"
[platform]
maxFolders = 100
maxNameLen = 60
maxDescLen = 250
[tracer]
proto = "unixgram"
addr = "/tmp/collect/dapper-collector.sock"
family = "favorite"
[httpClient]
key = "0dc647722719f2ea"
secret = "a3769b553680da10b40994265fb48d20"
dial = "1s"
timeout = "1s"
keepAlive = "60s"
timer = 1000
[httpClient.breaker]
window ="3s"
sleep ="100ms"
bucket = 10
ratio = 0.1
request = 100
[ecode]
domain = "172.16.33.248:6401"
all = "1h"
diff = "5m"
[ecode.clientconfig]
key = "test"
secret = "e6c4c252dc7e3d8a90805eecd7c73396"
dial = "2000ms"
timeout = "2s"
keepAlive = "10s"
timer = 128
[ecode.clientconfig.breaker]
window ="3s"
sleep ="100ms"
bucket = 10
ratio = 0.5
request = 100
[ecode.app]
key = "test"
secret = "e6c4c252dc7e3d8a90805eecd7c73396"
[bm]
addr = "0.0.0.0:6010"
maxListen = 1000
timeout = "100ms"
# readTimeout = "100ms"
# writeTimeout = "100ms"
[mysql]
[mysql.fav]
addr = "172.16.33.205:3308"
dsn = "test:test@tcp(172.16.33.205:3308)/bilibili_fav?timeout=2s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 20
idle = 10
idleTimeout ="4h"
queryTimeout = "200ms"
execTimeout = "200ms"
tranTimeout = "200ms"
[mysql.fav.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[redis]
name = "favorite/favorite"
proto = "tcp"
addr = "172.16.33.54:6379"
idle = 100
active = 100
dialTimeout = "500ms"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
expire = "10m"
coverExpire = "30m"
[memcache]
name = "favorite"
proto = "tcp"
addr = "172.16.33.54:11211"
idle = 10
active = 10
dialTimeout = "2s"
readTimeout = "2s"
writeTimeout = "2s"
idleTimeout = "7h"
expire = "15m"
[jobDatabus]
key = "0QEO9F8JuuIxZzNDvklH"
secret= "0QEO9F8JuuIxZzNDvklI"
group= "FavoriteJob-UGC-P"
topic= "FavoriteJob-T"
action="pub"
name = "favorite/job"
proto = "tcp"
addr = "172.16.33.158:6205"
idle = 100
active = 100
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "1h"
[rpcClient2]
[rpcClient2.account]
group = "groupapp"
pullInterval = "10s"
[rpcClient2.account.client]
token = "123456"
timeout = "1s"
timer = 1000
[rpcClient2.account.client.breaker]
window ="3s"
sleep ="100ms"
bucket = 10
ratio = 0.5
request = 100
[rpcClient2.account.zookeeper]
root = "/microservice/account-service/"
addrs = ["172.18.33.172:2181"]
timeout = "30s"
[rpcClient2.archive]
pullInterval = "10s"
group = "test"
[rpcClient2.archive.client]
token = "123456"
timeout = "1s"
timer = 1000
[rpcClient2.archive.client.breaker]
window ="3s"
sleep ="100ms"
bucket = 10
ratio = 0.5
request = 100
[rpcClient2.archive.zookeeper]
root = "/microservice/archive-service/"
addrs = ["172.18.33.172:2181"]
timeout = "30s"
[rpcClient2.filter]
pullInterval = "10s"
[rpcClient2.filter.client]
timeout = "1s"
timer = 1000
[rpcClient2.filter.client.breaker]
window ="3s"
sleep ="100ms"
bucket = 10
ratio = 0.5
request = 100
[rpcClient2.filter.zookeeper]
root = "/microservice/filter-service/"
addrs = ["172.18.33.172:2181"]
timeout = "30s"
[rpcClient2.favorite]
pullInterval = "10s"
[rpcClient2.favorite.client]
timeout = "1s"
timer = 1000
[rpcClient2.favorite.client.breaker]
window ="3s"
sleep ="100ms"
bucket = 10
ratio = 0.5
request = 100
[rpcClient2.favorite.zookeeper]
root = "/microservice/favorite/"
addrs = ["172.18.33.172:2181"]
timeout = "30s"

View File

@@ -0,0 +1,59 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"go-common/app/interface/main/favorite/conf"
"go-common/app/interface/main/favorite/http"
"go-common/app/interface/main/favorite/service"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
"go-common/library/net/trace"
)
var svc *service.Service
func main() {
flag.Parse()
if err := conf.Init(); err != nil {
log.Error("conf.Init() error(%v)", err)
panic(err)
}
// init log
log.Init(conf.Conf.Log)
trace.Init(conf.Conf.Tracer)
defer trace.Close()
defer log.Close()
log.Info("favorite start")
ecode.Init(conf.Conf.Ecode)
// service init
svc = service.New(conf.Conf)
http.Init(conf.Conf, svc)
signalHandler()
}
func signalHandler() {
var (
err error
ch = make(chan os.Signal, 1)
)
signal.Notify(ch, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
si := <-ch
switch si {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
log.Info("get a signal %s, stop the consume process", si.String())
svc.Close()
if err != nil {
log.Error("svc.Close() error(%v)", err)
}
return
case syscall.SIGHUP:
default:
return
}
}
}

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/favorite/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/cache/memcache:go_default_library",
"//library/cache/redis:go_default_library",
"//library/conf:go_default_library",
"//library/ecode/tip: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/antispam:go_default_library",
"//library/net/http/blademaster/middleware/auth:go_default_library",
"//library/net/http/blademaster/middleware/supervisor:go_default_library",
"//library/net/http/blademaster/middleware/verify: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,139 @@
package conf
import (
"flag"
"go-common/library/net/rpc/warden"
"go-common/library/cache/memcache"
"go-common/library/cache/redis"
"go-common/library/conf"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
"go-common/library/log/infoc"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/antispam"
"go-common/library/net/http/blademaster/middleware/auth"
"go-common/library/net/http/blademaster/middleware/supervisor"
"go-common/library/net/http/blademaster/middleware/verify"
"go-common/library/net/rpc"
"go-common/library/net/trace"
"go-common/library/queue/databus"
"go-common/library/time"
"github.com/BurntSushi/toml"
)
var (
confPath string
// Conf Config
Conf *Config
)
// Config is favorte conf
type Config struct {
// base
// log
Log *log.Config
App *bm.App
// favorite config
Fav *Fav
Platform *Platform
// BM blademaster
BM *bm.ServerConfig
// redis
Redis *Redis
// memcache
Memcache *Memcache
// databus
JobDatabus *databus.Config
// Verify
Verify *verify.Config
// Auth
Auth *auth.Config
// rpc client
RPCClient2 *RPC
// tracer
Tracer *trace.Config
// http client
HTTPClient *bm.ClientConfig
// ecode
Ecode *ecode.Config
// Antispam
Antispam *antispam.Config
// Supervisior
Supervisor *supervisor.Config
// collector
Infoc2 *infoc.Config
}
// RPC contain all rpc conf
type RPC struct {
Archive *rpc.ClientConfig
Favorite *rpc.ClientConfig
FavClient *warden.ClientConfig
}
// Fav config
type Fav struct {
// the max of the num of favorite folders
MaxFolders int
MaxPagesize int
MaxNameLen int
MaxDescLen int
// the num of operation
MaxOperationNum int
// the num of default favorite
DefaultFolderLimit int
NormalFolderLimit int
// cache expire
Expire time.Duration
}
// Platform config
type Platform struct {
MaxFolders int
MaxNameLen int
MaxDescLen int
}
// Redis redis conf
type Redis struct {
*redis.Config
Expire time.Duration
CoverExpire time.Duration
}
// Memcache memcache conf
type Memcache struct {
*memcache.Config
Expire time.Duration
}
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.Toml2(); !ok {
panic(err)
}
_, err = toml.Decode(value, &Conf)
return
}

View File

@@ -0,0 +1,49 @@
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/favorite/dao/music",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/favorite/conf:go_default_library",
"//app/interface/main/favorite/model: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/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 = ["dao_test.go"],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/interface/main/favorite/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,49 @@
package music
import (
"context"
"fmt"
"net/url"
"go-common/app/interface/main/favorite/conf"
"go-common/app/interface/main/favorite/model"
"go-common/library/ecode"
"go-common/library/log"
httpx "go-common/library/net/http/blademaster"
"go-common/library/net/metadata"
"go-common/library/xstr"
)
const _music = "http://api.bilibili.co/x/internal/v1/audio/songs/batch"
// Dao defeine fav Dao
type Dao struct {
httpClient *httpx.Client
}
// New return fav dao
func New(c *conf.Config) (d *Dao) {
d = &Dao{
httpClient: httpx.NewClient(c.HTTPClient),
}
return
}
// MusicMap return the music map data(all state).
func (d *Dao) MusicMap(c context.Context, musicIds []int64) (data map[int64]*model.Music, err error) {
params := url.Values{}
params.Set("level", "1")
params.Set("ids", xstr.JoinInts(musicIds))
res := new(model.MusicResult)
ip := metadata.String(c, metadata.RemoteIP)
if err = d.httpClient.Get(c, _music, ip, params, res); err != nil {
log.Error("d.HTTPClient.Get(%s?%s) error(%v)", _music, params.Encode())
return
}
if res.Code != ecode.OK.Code() {
log.Error("d.HTTPClient.Get(%s?%s) code:%d msg:%s", _music, params.Encode(), res.Code)
err = fmt.Errorf("Get Music failed!code:=%v", res.Code)
return
}
return res.Data, nil
}

View File

@@ -0,0 +1,45 @@
package music
import (
"context"
"flag"
"os"
"testing"
"go-common/app/interface/main/favorite/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.community.favorite")
flag.Set("conf_token", "929707200cf97646d1de7116e555dcfa")
flag.Set("tree_id", "2296")
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/favorite-test.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
os.Exit(m.Run())
}
func TestMusicMap(t *testing.T) {
Convey("MusicMap", t, func() {
_, err := d.MusicMap(context.Background(), []int64{0})
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,49 @@
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/favorite/dao/topic",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/favorite/conf:go_default_library",
"//app/interface/main/favorite/model: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/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 = ["dao_test.go"],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/interface/main/favorite/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,61 @@
package topic
import (
"context"
"net/url"
"strconv"
"go-common/app/interface/main/favorite/conf"
"go-common/app/interface/main/favorite/model"
"go-common/library/ecode"
"go-common/library/log"
httpx "go-common/library/net/http/blademaster"
"go-common/library/net/metadata"
"go-common/library/xstr"
)
const _topic = "http://matsuri.bilibili.co/activity/pages"
// Dao defeine fav Dao
type Dao struct {
httpClient *httpx.Client
}
// New return fav dao
func New(c *conf.Config) (d *Dao) {
d = &Dao{
httpClient: httpx.NewClient(c.HTTPClient),
}
return
}
// TopicMap return the user favorited topic's map data(all state).
func (d *Dao) TopicMap(c context.Context, tpIDs []int64, isNomal bool, appInfo *model.AppInfo) (data map[int64]*model.Topic, err error) {
params := url.Values{}
params.Set("mold", "1")
if !isNomal {
params.Set("all", "isOne")
}
params.Set("pids", xstr.JoinInts(tpIDs))
if appInfo != nil {
params.Set("http", strconv.Itoa(model.HttpMode4Https))
} else {
params.Set("http", strconv.Itoa(model.HttpMode4Both))
}
res := new(model.TopicsResult)
ip := metadata.String(c, metadata.RemoteIP)
if err = d.httpClient.Get(c, _topic, ip, params, res); err != nil {
log.Error("d.HTTPClient.Get(%s?%s) error(%v)", _topic, params.Encode())
return
}
if res.Code != ecode.OK.Code() {
log.Error("d.HTTPClient.Get(%s?%s) code:%d msg:%s", _topic, params.Encode(), res.Code)
err = model.ErrTopicRequest
return
}
data = make(map[int64]*model.Topic, len(res.Data.List))
for _, r := range res.Data.List {
data[r.ID] = r
}
return
}

View File

@@ -0,0 +1,45 @@
package topic
import (
"context"
"flag"
"os"
"testing"
"go-common/app/interface/main/favorite/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.community.favorite")
flag.Set("conf_token", "929707200cf97646d1de7116e555dcfa")
flag.Set("tree_id", "2296")
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/favorite-test.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
os.Exit(m.Run())
}
func TestTopicMap(t *testing.T) {
Convey("TopicMap", t, func() {
_, err := d.TopicMap(context.Background(), []int64{1}, false, nil)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,54 @@
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",
"redis_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/favorite/conf:go_default_library",
"//app/service/main/favorite/model:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"redis.go",
],
importpath = "go-common/app/interface/main/favorite/dao/video",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/favorite/conf:go_default_library",
"//app/service/main/favorite/model:go_default_library",
"//library/cache/redis:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,38 @@
package video
import (
"context"
"time"
"go-common/app/interface/main/favorite/conf"
xredis "go-common/library/cache/redis"
)
// Dao defeine fav Dao
type Dao struct {
redisPool *xredis.Pool
expireRedis int
coverExpireRedis int
}
// New return fav dao
func New(c *conf.Config) (d *Dao) {
d = &Dao{
redisPool: xredis.NewPool(c.Redis.Config),
expireRedis: int(time.Duration(c.Redis.Expire) / time.Second),
coverExpireRedis: int(time.Duration(c.Redis.CoverExpire) / time.Second),
}
return
}
// Close close all connection
func (d *Dao) Close() {
if d.redisPool != nil {
d.redisPool.Close()
}
}
// Ping check connection used in dao
func (d *Dao) Ping(c context.Context) (err error) {
return d.pingRedis(c)
}

View File

@@ -0,0 +1,45 @@
package video
import (
"context"
"flag"
"os"
"testing"
"go-common/app/interface/main/favorite/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.community.favorite")
flag.Set("conf_token", "929707200cf97646d1de7116e555dcfa")
flag.Set("tree_id", "2296")
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/favorite-test.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
os.Exit(m.Run())
}
func TestPing(t *testing.T) {
Convey("Ping", t, func() {
err := d.Ping(context.Background())
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,120 @@
package video
import (
"context"
"encoding/json"
"fmt"
"go-common/app/service/main/favorite/model"
"go-common/library/cache/redis"
"go-common/library/log"
)
const (
_covers = "fcs_"
)
func coversKey(mid, fid int64) string {
return fmt.Sprintf("%s%d_%d", _covers, mid, fid)
}
// pingRedis check redis connection
func (d *Dao) pingRedis(c context.Context) (err error) {
conn := d.redisPool.Get(c)
_, err = conn.Do("SET", "PING", "PONG")
conn.Close()
return
}
// SetNewCoverCache set fav's cover to cache
func (d *Dao) SetNewCoverCache(c context.Context, mid, fid int64, covers []*model.Cover) (err error) {
key := coversKey(mid, fid)
conn := d.redisPool.Get(c)
defer conn.Close()
for _, cover := range covers {
var bs []byte
if bs, err = json.Marshal(cover); err != nil {
log.Error("json.Marshal(%v) err(%v)", cover, err)
return
}
if err = conn.Send("RPUSH", key, bs); err != nil {
log.Error("conn.Send RPUSH error(%v)", err)
return
}
}
if err = conn.Send("EXPIRE", key, d.coverExpireRedis); err != nil {
log.Error("conn.Send(EXPIRE) err(%v)", err)
return
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush err(%v)", err)
return
}
for i := 0; i < len(covers)+1; i++ {
if _, err = conn.Receive(); err != nil {
log.Error("conn.Receive error(%v)", err)
}
}
return
}
// NewCoversCache get multi cover of fids by pipeline
func (d *Dao) NewCoversCache(c context.Context, mid int64, fids []int64) (fcvs map[int64][]*model.Cover, mis []int64, err error) {
conn := d.redisPool.Get(c)
defer conn.Close()
for _, fid := range fids {
key := coversKey(mid, fid)
if err = conn.Send("LRANGE", key, 0, 2); err != nil {
log.Error("conn.Send(LRANGE) err(%v)", err)
return
}
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush() err(%v)", err)
return
}
fcvs = make(map[int64][]*model.Cover, len(fids))
// receive lrange
for i := 0; i < len(fids); i++ {
var (
bbs [][]byte
cvs []*model.Cover
)
if bbs, err = redis.ByteSlices(conn.Receive()); err != nil {
if err == redis.ErrNil {
err = nil
mis = append(mis, fids[i])
continue
}
log.Error("redis.ByteSlices err(%v)", err)
return
}
if len(bbs) == 0 {
mis = append(mis, fids[i])
continue
}
for _, bs := range bbs {
cv := &model.Cover{}
if err = json.Unmarshal(bs, cv); err != nil {
log.Error("json.Unmarshal err(%v)", err)
return
}
cvs = append(cvs, cv)
}
fcvs[fids[i]] = cvs
}
return
}
// DelCoverCache delete folder cover
func (d *Dao) DelCoverCache(c context.Context, mid, fid int64) (err error) {
var (
key = coversKey(mid, fid)
conn = d.redisPool.Get(c)
)
defer conn.Close()
if _, err = conn.Do("DEL", key); err != nil {
log.Error("conn.Do(DEL, %s) error(%v)", key, err)
}
return
}

View File

@@ -0,0 +1,91 @@
package video
import (
"context"
"testing"
"go-common/app/service/main/favorite/model"
"github.com/smartystreets/goconvey/convey"
)
func TestVideocoversKey(t *testing.T) {
convey.Convey("coversKey", t, func(ctx convey.C) {
var (
mid = int64(1)
fid = int64(1)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := coversKey(mid, fid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func Test_pingRedis(t *testing.T) {
convey.Convey("pingRedis", t, func(ctx convey.C) {
var c = context.Background()
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.pingRedis(c)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestVideoSetNewCoverCache(t *testing.T) {
convey.Convey("SetNewCoverCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
fid = int64(1)
covers = []*model.Cover{{
Aid: 123,
Pic: "123",
Type: 2,
},
}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.SetNewCoverCache(c, mid, fid, covers)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestVideoNewCoversCache(t *testing.T) {
convey.Convey("NewCoversCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
fids = []int64{1}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
_, _, err := d.NewCoversCache(c, mid, fids)
ctx.Convey("Then err should be nil.fcvs,mis should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDelCoverCache(t *testing.T) {
convey.Convey("DelCoverCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
fid = int64(1)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.DelCoverCache(c, mid, fid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,61 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["http_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/favorite/conf:go_default_library",
"//app/interface/main/favorite/service:go_default_library",
"//library/net/http/blademaster:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"http.go",
"topic.go",
"video.go",
],
importpath = "go-common/app/interface/main/favorite/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/favorite/conf:go_default_library",
"//app/interface/main/favorite/model:go_default_library",
"//app/interface/main/favorite/service:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/log/anticheat:go_default_library",
"//library/log/infoc:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/antispam:go_default_library",
"//library/net/http/blademaster/middleware/auth:go_default_library",
"//library/net/http/blademaster/middleware/supervisor:go_default_library",
"//library/net/http/blademaster/middleware/verify: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,146 @@
package http
import (
"net/http"
"strconv"
"go-common/app/interface/main/favorite/conf"
"go-common/app/interface/main/favorite/service"
"go-common/library/log"
"go-common/library/log/anticheat"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/antispam"
"go-common/library/net/http/blademaster/middleware/auth"
"go-common/library/net/http/blademaster/middleware/supervisor"
"go-common/library/net/http/blademaster/middleware/verify"
)
var (
favSvc *service.Service
authSvc *auth.Auth
verifySvc *verify.Verify
antispamM *antispam.Antispam
supervisorM *supervisor.Supervisor
collector *anticheat.AntiCheat
)
// Init init router
func Init(c *conf.Config, svc *service.Service) {
verifySvc = verify.New(c.Verify)
authSvc = auth.New(c.Auth)
antispamM = antispam.New(c.Antispam)
supervisorM = supervisor.New(c.Supervisor)
favSvc = svc
if c.Infoc2 != nil {
collector = anticheat.New(c.Infoc2)
}
// init outer router
engineOut := bm.DefaultServer(c.BM)
outerRouter(engineOut)
internalRouter(engineOut)
// init Out serve
if err := engineOut.Start(); err != nil {
log.Error("engineOut.Start() error(%v)", err)
panic(err)
}
}
// outerRouter init outer router api path
func outerRouter(e *bm.Engine) {
// init api
e.GET("/monitor/ping", ping)
folderG := e.Group("/x/v2/fav/folder")
{
folderG.GET("", authSvc.Guest, videoFolders)
folderG.POST("/add", authSvc.User, antispamM.ServeHTTP, supervisorM.ServeHTTP, addVideoFolder)
folderG.POST("/del", authSvc.User, antispamM.ServeHTTP, delVideoFolder)
folderG.POST("/rename", authSvc.User, antispamM.ServeHTTP, supervisorM.ServeHTTP, renameVideoFolder)
folderG.POST("/public", authSvc.User, antispamM.ServeHTTP, upStateVideoFolder)
folderG.POST("/sort", authSvc.User, antispamM.ServeHTTP, sortVideoFolders)
}
videoG := e.Group("/x/v2/fav/video")
{
videoG.GET("", authSvc.Guest, favVideo)
videoG.GET("/tlist", authSvc.Guest, tidList)
videoG.GET("/newest", authSvc.User, favVideoNewest)
videoG.POST("/add", authSvc.User, antispamM.ServeHTTP, addFavVideo)
videoG.POST("/del", authSvc.User, antispamM.ServeHTTP, delFavVideo)
videoG.POST("/mdel", authSvc.User, antispamM.ServeHTTP, delFavVideos)
videoG.POST("/move", authSvc.User, antispamM.ServeHTTP, moveFavVideos)
videoG.POST("/copy", authSvc.User, antispamM.ServeHTTP, copyFavVideos)
videoG.GET("/favoureds", authSvc.User, isFavoureds)
videoG.GET("/favoured", authSvc.User, isFavoured)
videoG.GET("/default", authSvc.User, inDefaultFav)
videoG.GET("/cleaned", authSvc.User, isCleaned)
videoG.POST("/clean", authSvc.User, cleanInvalidArcs)
}
topicG := e.Group("/x/v2/fav/topic")
{
topicG.POST("/add", authSvc.User, antispamM.ServeHTTP, addFavTopic)
topicG.POST("/del", authSvc.User, antispamM.ServeHTTP, delFavTopic)
topicG.GET("/favoured", authSvc.User, isTopicFavoured)
topicG.GET("", authSvc.User, favTopics)
}
}
// internalRouter init internal router api path
func internalRouter(e *bm.Engine) {
// init api
folderG := e.Group("/x/internal/v2/fav/folder")
{
folderG.GET("", verifySvc.Verify, setMid, videoFolders)
folderG.POST("/add", verifySvc.VerifyUser, addVideoFolder)
folderG.POST("/del", verifySvc.VerifyUser, delVideoFolder)
folderG.POST("/rename", verifySvc.VerifyUser, renameVideoFolder)
folderG.POST("/public", verifySvc.VerifyUser, upStateVideoFolder)
folderG.POST("/sort", verifySvc.VerifyUser, sortVideoFolders)
}
videoG := e.Group("/x/internal/v2/fav/video")
{
videoG.GET("", verifySvc.Verify, setMid, favVideo)
videoG.GET("/tlist", verifySvc.Verify, setMid, tidList)
videoG.GET("/newest", verifySvc.VerifyUser, favVideoNewest)
videoG.POST("/add", verifySvc.VerifyUser, addFavVideo)
videoG.POST("/del", verifySvc.VerifyUser, delFavVideo)
videoG.POST("/mdel", verifySvc.VerifyUser, delFavVideos)
videoG.POST("/move", verifySvc.VerifyUser, moveFavVideos)
videoG.POST("/copy", verifySvc.VerifyUser, copyFavVideos)
videoG.GET("/favoureds", verifySvc.VerifyUser, isFavoureds)
videoG.GET("/favoured", verifySvc.VerifyUser, isFavoured)
videoG.GET("/default", verifySvc.VerifyUser, inDefaultFav)
videoG.GET("/cleaned", verifySvc.VerifyUser, isCleaned)
videoG.POST("/clean", verifySvc.VerifyUser, cleanInvalidArcs)
}
topicG := e.Group("/x/internal/v2/fav/topic")
{
topicG.POST("/add", verifySvc.VerifyUser, addFavTopic)
topicG.POST("/del", verifySvc.VerifyUser, delFavTopic)
topicG.GET("/favoured", verifySvc.VerifyUser, isTopicFavoured)
topicG.GET("", verifySvc.VerifyUser, favTopics)
}
}
func setMid(c *bm.Context) {
var (
err error
mid int64
)
req := c.Request
midStr := req.Form.Get("mid")
if midStr != "" {
if mid, err = strconv.ParseInt(midStr, 10, 64); err != nil {
c.JSON(nil, err)
c.Abort()
return
}
}
c.Set("mid", mid)
}
// ping check server ok.
func ping(c *bm.Context) {
if err := favSvc.Ping(c); err != nil {
log.Error("favorite http service ping error(%v)", err)
c.AbortWithStatus(http.StatusServiceUnavailable)
}
}

View File

@@ -0,0 +1,640 @@
package http
import (
"context"
"crypto/md5"
"encoding/hex"
"fmt"
"net/http"
"net/url"
"strconv"
"testing"
"time"
"go-common/app/interface/main/favorite/conf"
"go-common/app/interface/main/favorite/service"
xhttp "go-common/library/net/http/blademaster"
)
const (
_mid = 88888894
_vmid = 12345
_aid = 5463438
_aids = "5463438,5463439"
_fid = 1852
_delFid = 123
_oldFid = 1791
_newFid = 1792
_fidsSort = "1107,1852,1792,1791"
_name = "folder-name-test"
_rename = "folder-rename-test"
_public = 1
_tpid = 2659 // TopicID
_type = 1 // Article
_v3Fid = 0
_searchFid = 0
_oid = 123
_pn = 1
_ps = 30
// video folder
_videoFolders = "http://127.0.0.1:6010/x/internal/v2/fav/folder"
_addVideoFolder = "http://127.0.0.1:6010/x/internal/v2/fav/folder/add"
_delVideoFolder = "http://127.0.0.1:6010/x/internal/v2/fav/folder/del"
_renameVideoFolder = "http://127.0.0.1:6010/x/internal/v2/fav/folder/rename"
_upStateVideoFolder = "http://127.0.0.1:6010/x/internal/v2/fav/folder/public"
_sortVideoFolders = "http://127.0.0.1:6010/x/internal/v2/fav/folder/sort"
// video
_favVideo = "http://127.0.0.1:6010/x/internal/v2/fav/video"
_favVideoNewest = "http://127.0.0.1:6010/x/internal/v2/fav/video/newest"
_addFavVideo = "http://127.0.0.1:6010/x/internal/v2/fav/video/add"
_delFavVideo = "http://127.0.0.1:6010/x/internal/v2/fav/video/del"
_delFavVideos = "http://127.0.0.1:6010/x/internal/v2/fav/video/mdel"
_moveFavVideos = "http://127.0.0.1:6010/x/internal/v2/fav/video/move"
_copyFavVideos = "http://127.0.0.1:6010/x/internal/v2/fav/video/copy"
_isFavoureds = "http://127.0.0.1:6010/x/internal/v2/fav/video/favoureds"
_isFavoured = "http://127.0.0.1:6010/x/internal/v2/fav/video/favoured"
_inDefaultFav = "http://127.0.0.1:6010/x/internal/v2/fav/video/default"
// topic
_favTopics = "http://127.0.0.1:6010/x/internal/v2/fav/topic"
_addFavTopic = "http://127.0.0.1:6010/x/internal/v2/fav/topic/add"
_delFavTopic = "http://127.0.0.1:6010/x/internal/v2/fav/topic/del"
_isTopicFavoured = "http://127.0.0.1:6010/x/internal/v2/fav/topic/favoured"
// fav v3
_favorites = "http://127.0.0.1:6010/x/internal/v3/fav"
_addFav = "http://127.0.0.1:6010/x/internal/v3/fav/add"
_isFavored = "http://127.0.0.1:6010/x/internal/v3/fav/favored"
_delFav = "http://127.0.0.1:6010/x/internal/v3/fav/del"
)
func TestHttp(t *testing.T) {
if err := conf.Init(); err != nil {
t.Fatalf("conf.Init() error(%v)", err)
}
svr := service.New(conf.Conf)
client := xhttp.NewClient(conf.Conf.HTTPClient)
Init(conf.Conf, svr)
// video foler
testVideoFolders(client, t, _mid, _vmid, _aid)
testRenameVideoFolder(client, t, _mid, _fid, _rename)
testAddVideoFolder(client, t, _mid, _public, _name)
testSortVideoFolder(client, t, _mid, _fidsSort)
testUpStateVideoFolder(client, t, _mid, _fid, _public)
testDelVideoFolder(client, t, _mid, _delFid)
// video
testVideos(client, t, _mid, _vmid, _fid)
testFavVideoNewest(client, t, _mid, _vmid, _searchFid, _pn, _ps)
testAddFavVideo(client, t, _mid, _fid, _aid)
testMoveFavVideos(client, t, _mid, _oldFid, _newFid, _aids)
testCopyFavVideos(client, t, _mid, _oldFid, _newFid, _aids)
testIsFavoured(client, t, _mid, _aid)
testIsFavoureds(client, t, _mid, _aids)
testInDefaultFav(client, t, _mid, _aid)
testDelVideo(client, t, _mid, _fid, _aid)
testDelVideos(client, t, _mid, _fid, _aids)
// topic
testFavTopics(client, t, _mid, _pn, _ps)
testAddFavTopic(client, t, _mid, _tpid)
testIsTopicFavoured(client, t, _mid, _tpid)
testDelFavTopic(client, t, _mid, _tpid)
// fav v3
testFavorites(client, t, _type, _mid, _vmid, _v3Fid)
testAddFav(client, t, _type, _mid, _v3Fid, _oid)
testIsFavored(client, t, _type, _mid, _v3Fid, _oid)
testDelFav(client, t, _type, _mid, _v3Fid, _oid)
}
func testVideoFolders(client *xhttp.Client, t *testing.T, mid, vmid, aid int64) {
params := &url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("GET", _videoFolders+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("VideoFolders", t, res)
}
}
func testAddVideoFolder(client *xhttp.Client, t *testing.T, mid, public int64, name string) {
params := &url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("public", strconv.FormatInt(public, 10))
params.Set("name", name)
params.Set("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("POST", _addVideoFolder+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("DelVideoFolder", t, res)
}
}
func testRenameVideoFolder(client *xhttp.Client, t *testing.T, mid, fid int64, name string) {
params := &url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("fid", strconv.FormatInt(fid, 10))
params.Set("name", name)
params.Set("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("POST", _renameVideoFolder+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("RenameVideoFolder", t, res)
}
}
func testUpStateVideoFolder(client *xhttp.Client, t *testing.T, mid, fid, public int64) {
params := &url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("fid", strconv.FormatInt(fid, 10))
params.Set("public", strconv.FormatInt(public, 10))
params.Set("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("POST", _upStateVideoFolder+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("RenameVideoFolder", t, res)
}
}
func testSortVideoFolder(client *xhttp.Client, t *testing.T, mid int64, fids string) {
params := &url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("fids", fids)
params.Set("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("POST", _sortVideoFolders+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("RenameVideoFolder", t, res)
}
}
func testDelVideoFolder(client *xhttp.Client, t *testing.T, mid, fid int64) {
params := &url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("fid", strconv.FormatInt(fid, 10))
params.Set("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("POST", _delVideoFolder+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("DelVideoFolder", t, res)
}
}
func testVideos(client *xhttp.Client, t *testing.T, mid, vmid, fid int64) {
params := &url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("fid", strconv.FormatInt(fid, 10))
params.Set("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("GET", _favVideo+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("Videos", t, res)
}
}
func testFavVideoNewest(client *xhttp.Client, t *testing.T, mid, vmid, fid, pn, ps int64) {
params := &url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("fid", strconv.FormatInt(fid, 10))
params.Set("pn", strconv.FormatInt(pn, 10))
params.Set("ps", strconv.FormatInt(ps, 10))
params.Set("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("GET", _favVideoNewest+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("FavVideoNewest", t, res)
}
}
func testAddFavVideo(client *xhttp.Client, t *testing.T, mid, fid, aid int64) {
params := &url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("fid", strconv.FormatInt(fid, 10))
params.Set("aid", strconv.FormatInt(aid, 10))
params.Set("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("POST", _addFavVideo+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("AddFavVideo", t, res)
}
}
func testMoveFavVideos(client *xhttp.Client, t *testing.T, mid, oldFid, newFid int64, aids string) {
params := &url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("old_fid", strconv.FormatInt(oldFid, 10))
params.Set("new_fid", strconv.FormatInt(newFid, 10))
params.Set("aids", aids)
params.Set("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("POST", _moveFavVideos+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("MoveFavVideos", t, res)
}
}
func testCopyFavVideos(client *xhttp.Client, t *testing.T, mid, oldFid, newFid int64, aids string) {
params := &url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("old_fid", strconv.FormatInt(oldFid, 10))
params.Set("new_fid", strconv.FormatInt(newFid, 10))
params.Set("aids", aids)
params.Set("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("POST", _copyFavVideos+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("CopyFavVideos", t, res)
}
}
func testIsFavoured(client *xhttp.Client, t *testing.T, mid, aid int64) {
params := &url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("aid", strconv.FormatInt(aid, 10))
params.Set("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("GET", _isFavoured+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("IsFavoured", t, res)
}
}
func testIsFavoureds(client *xhttp.Client, t *testing.T, mid int64, aids string) {
params := &url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("aids", aids)
params.Set("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("GET", _isFavoureds+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("IsFavoureds", t, res)
}
}
func testInDefaultFav(client *xhttp.Client, t *testing.T, mid, aid int64) {
params := &url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("aid", strconv.FormatInt(aid, 10))
params.Set("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("GET", _inDefaultFav+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("IsFavoureds", t, res)
}
}
func testDelVideo(client *xhttp.Client, t *testing.T, mid, fid, aid int64) {
params := &url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("aid", strconv.FormatInt(aid, 10))
params.Set("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("POST", _delFavVideo+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("DelVideo", t, res)
}
}
func testDelVideos(client *xhttp.Client, t *testing.T, mid, fid int64, aids string) {
params := &url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("fid", strconv.FormatInt(fid, 10))
params.Set("aids", aids)
params.Set("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("POST", _delFavVideos+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("DelVideos", t, res)
}
}
func testFavTopics(client *xhttp.Client, t *testing.T, mid, pn, ps int64) {
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("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("GET", _favTopics+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("FavTopics", t, res)
}
}
func testAddFavTopic(client *xhttp.Client, t *testing.T, mid, tpid int64) {
params := &url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("tpid", strconv.FormatInt(tpid, 10))
params.Set("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("POST", _addFavTopic+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("AddFavTopic", t, res)
}
}
func testIsTopicFavoured(client *xhttp.Client, t *testing.T, mid, tpid int64) {
params := &url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("tpid", strconv.FormatInt(tpid, 10))
params.Set("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("GET", _isTopicFavoured+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("IsTopicFavoured", t, res)
}
}
func testDelFavTopic(client *xhttp.Client, t *testing.T, mid, tpid int64) {
params := &url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("tpid", strconv.FormatInt(tpid, 10))
params.Set("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("POST", _delFavTopic+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("DelFavTopic", t, res)
}
}
func testFavorites(client *xhttp.Client, t *testing.T, tp, mid, vmid, fid int64) {
params := &url.Values{}
params.Set("type", strconv.FormatInt(tp, 10))
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("fid", strconv.FormatInt(fid, 10))
params.Set("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("GET", _favorites+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("Favorites", t, res)
}
}
func testAddFav(client *xhttp.Client, t *testing.T, tp, mid, fid, oid int64) {
params := &url.Values{}
params.Set("type", strconv.FormatInt(tp, 10))
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("fid", strconv.FormatInt(fid, 10))
params.Set("oid", strconv.FormatInt(oid, 10))
params.Set("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("POST", _addFav+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("AddFav", t, res)
}
}
func testIsFavored(client *xhttp.Client, t *testing.T, tp, mid, fid, oid int64) {
params := &url.Values{}
params.Set("type", strconv.FormatInt(tp, 10))
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("fid", strconv.FormatInt(fid, 10))
params.Set("oid", strconv.FormatInt(oid, 10))
params.Set("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("GET", _isFavored+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("IsFavored", t, res)
}
}
func testDelFav(client *xhttp.Client, t *testing.T, tp, mid, fid, oid int64) {
params := &url.Values{}
params.Set("type", strconv.FormatInt(tp, 10))
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("fid", strconv.FormatInt(fid, 10))
params.Set("oid", strconv.FormatInt(oid, 10))
params.Set("appkey", conf.Conf.App.Key)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("sign", createSign(params.Encode()))
// send
req, err := http.NewRequest("POST", _delFav+"?"+params.Encode(), nil)
t.Log(req.URL.String())
if err != nil {
t.Errorf("NewRequest() error(%v)", err)
}
res := map[string]interface{}{}
if err = client.Do(context.TODO(), req, &res); err != nil {
t.Errorf("client.Do() error(%v)", err)
} else {
result("DelFav", t, res)
}
}
func createSign(params string) string {
mh := md5.Sum([]byte(params + conf.Conf.App.Secret))
return hex.EncodeToString(mh[:])
}
func result(name string, t *testing.T, res map[string]interface{}) {
t.Log("[==========" + name + " Testing Result==========]")
if rs, ok := res["code"]; ok {
t.Log(fmt.Sprintf("code:%v, message:%s, data:%v", rs, res["message"], res["data"]))
}
t.Log("[↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑]\r\n")
}

View File

@@ -0,0 +1,93 @@
package http
import (
"strconv"
"go-common/app/interface/main/favorite/conf"
"go-common/app/interface/main/favorite/model"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
func addFavTopic(c *bm.Context) {
params := c.Request.Form
midIfc, _ := c.Get("mid")
tpStr := params.Get("tpid")
tp, err := strconv.ParseInt(tpStr, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%s)", tpStr)
c.JSON(nil, ecode.RequestErr)
return
}
err = favSvc.AddFavTopic(c, midIfc.(int64), tp, c.Request.Header.Get("Cookie"), params.Get("access_key"))
c.JSON(nil, err)
}
func delFavTopic(c *bm.Context) {
params := c.Request.Form
mid, _ := c.Get("mid")
tpStr := params.Get("tpid")
tp, err := strconv.ParseInt(tpStr, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%s)", tpStr)
c.JSON(nil, ecode.RequestErr)
return
}
err = favSvc.DelFavTopic(c, mid.(int64), tp)
c.JSON(nil, err)
}
// isTopicFavouried determine topic whether or not favouried by mid
func isTopicFavoured(c *bm.Context) {
params := c.Request.Form
mid, _ := c.Get("mid")
tpStr := params.Get("tpid")
tp, err := strconv.ParseInt(tpStr, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%s)", tpStr)
c.JSON(nil, ecode.RequestErr)
return
}
faved, err := favSvc.IsTopicFavoured(c, mid.(int64), tp)
if err != nil {
c.JSON(nil, err)
return
}
data := map[string]interface{}{"favoured": faved}
c.JSON(data, nil)
}
func favTopics(c *bm.Context) {
var appInfo *model.AppInfo
params := c.Request.Form
mid, _ := c.Get("mid")
pnStr := params.Get("pn")
psStr := params.Get("ps")
pn, err := strconv.Atoi(pnStr)
if err != nil || pn < 1 {
pn = 1
}
ps, err := strconv.Atoi(psStr)
if err != nil || ps >= conf.Conf.Fav.MaxPagesize || ps <= 0 {
ps = conf.Conf.Fav.MaxPagesize
}
platformStr := params.Get("platform")
buildStr := params.Get("build")
mobiAppStr := params.Get("mobi_app")
deviceStr := params.Get("device")
if platformStr != "" && buildStr != "" {
appInfo = &model.AppInfo{
Platform: platformStr,
Build: buildStr,
MobiApp: mobiAppStr,
Device: deviceStr,
}
}
data, err := favSvc.FavTopics(c, mid.(int64), pn, ps, appInfo)
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(data, nil)
}

View File

@@ -0,0 +1,647 @@
package http
import (
"strconv"
"strings"
"go-common/app/interface/main/favorite/conf"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/log/infoc"
bm "go-common/library/net/http/blademaster"
"go-common/library/xstr"
)
// videoFolders get all favorite folders
func videoFolders(c *bm.Context) {
var (
uid int64
mid int64
vmid int64
aid int64
err error
isSelf bool
mediaList bool
fromWeb bool
)
req := c.Request
if midI, ok := c.Get("mid"); ok {
mid = midI.(int64)
}
if req.Form.Get("medialist") == "1" {
mediaList = true
}
params := req.URL.Query()
app := params.Get("mobi_app")
build, _ := strconv.ParseInt(params.Get("build"), 10, 64)
device := params.Get("device")
if (app == "android" && build >= 5360001 && build <= 5361000) || (app == "iphone" && build == 8300 && device == "phone") {
mediaList = true
}
if app == "" {
fromWeb = true
}
vmidStr := req.Form.Get("vmid")
if vmidStr != "" {
uid, err = strconv.ParseInt(vmidStr, 10, 64)
if err != nil {
c.JSON(nil, err)
return
}
if uid <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
isSelf = mid == uid
vmid = uid
} else if mid != 0 {
uid = mid
isSelf = true
} else {
c.JSON(nil, ecode.RequestErr)
return
}
aidStr := req.Form.Get("aid")
if aidStr != "" {
if aid, err = strconv.ParseInt(aidStr, 10, 64); err != nil {
log.Error("strconv.ParseInt(aid:%s)", aidStr)
return
}
}
data, err := favSvc.FavFolders(c, mid, vmid, uid, aid, isSelf, mediaList, fromWeb)
c.JSON(data, err)
}
// addVideoFolder add a folder.
func addVideoFolder(c *bm.Context) {
mid, _ := c.Get("mid")
params := c.Request.Form
name := params.Get("name")
pubStr := params.Get("public")
if name == "" || len([]rune(name)) > conf.Conf.Fav.MaxNameLen {
log.Warn("arg name(%s) is empty or it's length more than %d", name, conf.Conf.Fav.MaxNameLen)
c.JSON(nil, ecode.FavNameTooLong)
return
}
var (
pub int64
err error
)
if pubStr != "" {
if pub, err = strconv.ParseInt(pubStr, 10, 64); err != nil || pub < 0 || pub > 1 {
pub = 0
}
}
var fid int64
if fid, err = favSvc.AddFavFolder(c, mid.(int64), name, c.Request.Header.Get("Cookie"), params.Get("access_key"), int32(pub)); err != nil {
c.JSON(nil, err)
return
}
data := map[string]int64{
"fid": fid,
}
c.JSON(data, nil)
}
// renameVideoFolder rename folder.
func renameVideoFolder(c *bm.Context) {
mid, _ := c.Get("mid")
params := c.Request.Form
fidStr := params.Get("fid")
name := params.Get("name")
if fidStr == "" {
log.Warn("arg fid is empty")
c.JSON(nil, ecode.RequestErr)
return
}
if name == "" || len([]rune(name)) > conf.Conf.Fav.MaxNameLen {
log.Warn("arg name(%s) is empty or it's length more than %d", name, conf.Conf.Fav.MaxNameLen)
c.JSON(nil, ecode.FavNameTooLong)
return
}
fid, err := strconv.ParseInt(fidStr, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", fidStr, err)
c.JSON(nil, ecode.RequestErr)
return
}
err = favSvc.UpFavName(c, mid.(int64), fid, name, c.Request.Header.Get("Cookie"), params.Get("access_key"))
c.JSON(nil, err)
}
// upStateVideoFolder update folder's state.
func upStateVideoFolder(c *bm.Context) {
mid, _ := c.Get("mid")
params := c.Request.Form
fidStr := params.Get("fid")
pubStr := params.Get("public")
if fidStr == "" || pubStr == "" {
log.Warn("method fid(%s) public(%s) is empty", fidStr, pubStr)
c.JSON(nil, ecode.RequestErr)
return
}
fid, err := strconv.ParseInt(fidStr, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", fidStr, err)
c.JSON(nil, ecode.RequestErr)
return
}
public, err := strconv.Atoi(pubStr)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", pubStr, err)
c.JSON(nil, ecode.RequestErr)
return
}
err = favSvc.UpFavState(c, mid.(int64), fid, int32(public), c.Request.Header.Get("Cookie"), params.Get("access_key"))
c.JSON(nil, err)
}
// delVideoFolder delete folder.
func delVideoFolder(c *bm.Context) {
mid, _ := c.Get("mid")
params := c.Request.Form
fidStr := params.Get("fid")
if fidStr == "" {
log.Warn("method fid(%s) is empty", fidStr)
c.JSON(nil, ecode.RequestErr)
return
}
fid, err := strconv.ParseInt(fidStr, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", fidStr, err)
c.JSON(nil, ecode.RequestErr)
return
}
err = favSvc.DelVideoFolder(c, mid.(int64), fid)
c.JSON(nil, err)
}
// sortFavFolders sort all favorite folders
func sortVideoFolders(c *bm.Context) {
var (
fids []int64
err error
)
params := c.Request.Form
fidStr := params.Get("fids")
mid, _ := c.Get("mid")
if fidStr == "" {
log.Error("arg fids is empty")
c.JSON(nil, ecode.RequestErr)
return
}
fids, err = xstr.SplitInts(fidStr)
if err != nil {
log.Error("xstr.SplitInts(%s) error(%v)", fidStr, err)
c.JSON(nil, ecode.RequestErr)
return
}
err = favSvc.SetVideoFolderSort(c, mid.(int64), fids)
c.JSON(nil, err)
}
// favVideo return all videos in the fid folder.
func favVideo(c *bm.Context) {
// params
params := c.Request.Form
vmidStr := params.Get("vmid")
fidStr := params.Get("fid")
tidStr := params.Get("tid")
keywordStr := params.Get("keyword")
orderStr := params.Get("order")
pnStr := params.Get("pn")
psStr := params.Get("ps")
var (
err error
mid int64
vmid int64
uid int64
)
if midI, ok := c.Get("mid"); ok {
mid = midI.(int64)
}
if vmidStr != "" {
if uid, err = strconv.ParseInt(vmidStr, 10, 64); err != nil || uid <= 0 {
log.Error("vmid(%s) need a number > 0 error(%v)", vmidStr, err)
c.JSON(nil, ecode.RequestErr)
return
}
vmid = uid
} else if mid != 0 {
uid = mid
} else {
log.Warn("mid(%d) && vmidStr(%s)) is empty", mid, vmidStr)
c.JSON(nil, ecode.RequestErr)
return
}
fid, _ := strconv.ParseInt(fidStr, 10, 64)
tid, err := strconv.Atoi(tidStr)
if err != nil {
tid = 0
}
pn, err := strconv.Atoi(pnStr)
if err != nil || pn < 1 {
pn = 1
}
ps, err := strconv.Atoi(psStr)
if err != nil || ps > conf.Conf.Fav.MaxPagesize || ps <= 0 {
ps = conf.Conf.Fav.MaxPagesize
}
// fav video
data, err := favSvc.FavVideo(c, mid, vmid, uid, fid, keywordStr, orderStr, tid, pn, ps)
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(data, nil)
}
// tidList return all tids in the fid folder.
func tidList(c *bm.Context) {
// params
params := c.Request.Form
vmidStr := params.Get("vmid")
fidStr := params.Get("fid")
var (
err error
mid int64
vmid int64
uid int64
)
if midI, ok := c.Get("mid"); ok {
mid = midI.(int64)
}
if vmidStr != "" {
if uid, err = strconv.ParseInt(vmidStr, 10, 64); err != nil || uid <= 0 {
log.Error("vmid(%s) need a number > 0 error(%v)", vmidStr, err)
c.JSON(nil, ecode.RequestErr)
return
}
vmid = uid
} else if mid != 0 {
uid = mid
} else {
log.Warn("mid(%d) && vmidStr(%s)) is empty", mid, vmidStr)
c.JSON(nil, ecode.RequestErr)
return
}
fid, _ := strconv.ParseInt(fidStr, 10, 64)
// fav video
data, err := favSvc.TidList(c, mid, vmid, uid, fid)
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(data, nil)
}
// favVideoNewest return the newest videos in the all folder.
func favVideoNewest(c *bm.Context) {
midIf, _ := c.Get("mid")
mid := midIf.(int64)
params := c.Request.URL.Query()
pnStr := params.Get("pn")
psStr := params.Get("ps")
pn, err := strconv.Atoi(pnStr)
if err != nil || pn < 1 {
pn = 1
}
ps, err := strconv.Atoi(psStr)
if err != nil || ps > conf.Conf.Fav.MaxPagesize || ps <= 0 {
ps = conf.Conf.Fav.MaxPagesize
}
data, err := favSvc.RecentArcs(c, mid, pn, ps)
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(data, nil)
}
// addFavVideo add a video into folder.
func addFavVideo(c *bm.Context) {
midIf, _ := c.Get("mid")
mid := midIf.(int64)
params := c.Request.Form
fidsStr := params.Get("fid")
aidStr := params.Get("aid")
if aidStr == "" {
log.Warn("params aid(%s) is empty", aidStr)
c.JSON(nil, ecode.RequestErr)
return
}
fids, err := xstr.SplitInts(fidsStr)
if err != nil {
log.Warn("xstr.PlitInts(fids:%s) err(%v)", fidsStr, err)
}
aid, err := strconv.ParseInt(aidStr, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", aidStr, err)
c.JSON(nil, ecode.RequestErr)
return
}
if len(fids) == 0 {
if err = favSvc.AddArc(c, mid, 0, aid, c.Request.Header.Get("Cookie"), params.Get("access_key")); err != nil {
c.JSON(nil, err)
return
}
}
for _, fid := range fids {
if err = favSvc.AddArc(c, mid, fid, aid, c.Request.Header.Get("Cookie"), params.Get("access_key")); err != nil {
c.JSON(nil, err)
return
}
}
if collector != nil {
collector.InfoAntiCheat2(c, "", aidStr, strconv.FormatInt(mid, 10), fidsStr, infoc.ItemTypeAv, infoc.ActionFav, "")
}
c.JSON(nil, err)
}
// delFavVideo delete a video from folder.
func delFavVideo(c *bm.Context) {
midIf, _ := c.Get("mid")
mid := midIf.(int64)
params := c.Request.Form
fidsStr := params.Get("fid")
aidStr := params.Get("aid")
if aidStr == "" {
log.Warn("method aid(%s) is empty", aidStr)
c.JSON(nil, ecode.RequestErr)
return
}
fids, err := xstr.SplitInts(fidsStr)
if err != nil {
log.Warn("xstr.SplitInts(fidsStr:%v) err(%v)", fidsStr, err)
}
aid, err := strconv.ParseInt(aidStr, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", aidStr, err)
c.JSON(nil, ecode.RequestErr)
return
}
if len(fids) == 0 {
err = favSvc.DelArc(c, mid, 0, aid)
c.JSON(nil, err)
return
}
for _, fid := range fids {
err = favSvc.DelArc(c, mid, fid, aid)
}
c.JSON(nil, err)
}
// moveFavVideos move some video into other folder.
func moveFavVideos(c *bm.Context) {
mid, _ := c.Get("mid")
params := c.Request.Form
ofidStr := params.Get("old_fid")
nfidStr := params.Get("new_fid")
aidsStr := params.Get("aids")
if aidsStr == "" || ofidStr == "" || nfidStr == "" {
log.Warn("method aids(%s) old_fid(%s) new_fid(%s) is empty", aidsStr, ofidStr, nfidStr)
c.JSON(nil, ecode.RequestErr)
return
}
if ofidStr == nfidStr {
log.Warn("move videos to the same folder...")
c.JSON(nil, ecode.FavFolderSame)
return
}
ofid, err := strconv.ParseInt(ofidStr, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", ofidStr, err)
c.JSON(nil, ecode.RequestErr)
return
}
nfid, err := strconv.ParseInt(nfidStr, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", nfidStr, err)
c.JSON(nil, ecode.RequestErr)
return
}
aidArr := strings.Split(aidsStr, ",")
if len(aidArr) == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if len(aidArr) > conf.Conf.Fav.MaxOperationNum {
c.JSON(nil, ecode.FavMaxOperNum)
return
}
aids := make([]int64, len(aidArr))
var aid int64
for i, aidStr := range aidArr {
aid, err = strconv.ParseInt(aidStr, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", aidStr, err)
c.JSON(nil, ecode.RequestErr)
return
}
aids[i] = aid
}
err = favSvc.MoveArcs(c, mid.(int64), ofid, nfid, aids)
c.JSON(nil, err)
}
// copyFavVideos move some video into other folder.
func copyFavVideos(c *bm.Context) {
midIf, _ := c.Get("mid")
mid := midIf.(int64)
params := c.Request.Form
omidStr := params.Get("old_mid")
ofidStr := params.Get("old_fid")
nfidStr := params.Get("new_fid")
aidsStr := params.Get("aids")
if aidsStr == "" || ofidStr == "" || nfidStr == "" {
log.Warn("method aids(%s) old_fid(%s) new_mid(%s) is empty", aidsStr, ofidStr, nfidStr)
c.JSON(nil, ecode.RequestErr)
return
}
if ofidStr == nfidStr {
log.Warn("copy videos to the same folder...")
c.JSON(nil, ecode.FavFolderSame)
return
}
omid, err := strconv.ParseInt(omidStr, 10, 64)
if err != nil {
log.Warn("strconv.ParseInt(%s) error(%v)", omidStr, err)
omid = mid
}
ofid, err := strconv.ParseInt(ofidStr, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", ofidStr, err)
c.JSON(nil, ecode.RequestErr)
return
}
nfid, err := strconv.ParseInt(nfidStr, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", nfidStr, err)
c.JSON(nil, ecode.RequestErr)
return
}
aidArr := strings.Split(aidsStr, ",")
if len(aidArr) == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if len(aidArr) > conf.Conf.Fav.MaxOperationNum {
c.JSON(nil, ecode.FavMaxOperNum)
return
}
aids := make([]int64, len(aidArr))
var aid int64
for i, aidStr := range aidArr {
aid, err = strconv.ParseInt(aidStr, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", aidStr, err)
c.JSON(nil, ecode.RequestErr)
return
}
aids[i] = aid
}
err = favSvc.CopyArcs(c, mid, omid, ofid, nfid, aids)
c.JSON(nil, err)
}
// delVideos delete some video from folder.
func delFavVideos(c *bm.Context) {
mid, _ := c.Get("mid")
params := c.Request.Form
fidStr := params.Get("fid")
aidsStr := params.Get("aids")
if aidsStr == "" {
log.Warn("method aid(%s) is empty", aidsStr)
c.JSON(nil, ecode.RequestErr)
return
}
fid, err := strconv.ParseInt(fidStr, 10, 64)
if err != nil {
log.Warn("strconv.ParseInt(%s) error(%v)", fidStr, err)
}
aidArr := strings.Split(aidsStr, ",")
if len(aidArr) == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if len(aidArr) > conf.Conf.Fav.MaxOperationNum {
c.JSON(nil, ecode.FavMaxOperNum)
return
}
aids := make([]int64, len(aidArr))
var aid int64
for i, aidStr := range aidArr {
aid, err = strconv.ParseInt(aidStr, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", aidStr, err)
c.JSON(nil, ecode.RequestErr)
return
}
aids[i] = aid
}
err = favSvc.DelArcs(c, mid.(int64), fid, aids)
c.JSON(nil, err)
}
// isFavoured detemine video whether or not favoured by mid.
func isFavoured(c *bm.Context) {
mid, _ := c.Get("mid")
params := c.Request.URL.Query()
aidStr := params.Get("aid")
aid, err := strconv.ParseInt(aidStr, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", aidStr, err)
c.JSON(nil, ecode.RequestErr)
return
}
faved, count, err := favSvc.IsFaved(c, mid.(int64), aid)
if err != nil {
log.Error("favSvr.IsFaved() err(%v)", err)
return
}
data := map[string]interface{}{"favoured": faved, "count": count}
c.JSON(data, nil)
}
// isFavoureds detemine video whether or not favoured by mid.
func isFavoureds(c *bm.Context) {
var (
aids []int64
err error
)
mid, _ := c.Get("mid")
params := c.Request.URL.Query()
aidStr := params.Get("aids")
if aidStr == "" {
log.Warn("method aid(%s) is empty", aidStr)
c.JSON(nil, ecode.RequestErr)
return
}
aids, err = xstr.SplitInts(aidStr)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", aidStr, err)
c.JSON(nil, ecode.RequestErr)
return
}
faved, _ := favSvc.IsFaveds(c, mid.(int64), aids)
c.JSON(faved, nil)
}
// inDefaultFav detemine video whether or not favoured in default folder.
func inDefaultFav(c *bm.Context) {
mid, _ := c.Get("mid")
params := c.Request.URL.Query()
aidStr := params.Get("aid")
if aidStr == "" {
log.Warn("method aid(%s) is empty", aidStr)
c.JSON(nil, ecode.RequestErr)
return
}
aid, err := strconv.ParseInt(aidStr, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", aidStr, err)
c.JSON(nil, ecode.RequestErr)
return
}
var isIn bool
isIn, err = favSvc.InDef(c, mid.(int64), aid)
data := map[string]bool{"default": isIn}
c.JSON(data, err)
}
// isCleaned check the clean action's cool down time and access
func isCleaned(c *bm.Context) {
mid, _ := c.Get("mid")
params := c.Request.URL.Query()
fidStr := params.Get("fid")
fid, err := strconv.ParseInt(fidStr, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", fidStr, err)
c.JSON(nil, ecode.RequestErr)
return
}
cleanState, err := favSvc.CleanState(c, mid.(int64), fid)
if err != nil {
log.Error("favSvc.IsCleaned(%d,%d) error(%v)", mid, fid, err)
c.JSON(nil, err)
return
}
data := map[string]interface{}{"state": cleanState}
c.JSON(data, nil)
}
func cleanInvalidArcs(c *bm.Context) {
mid, _ := c.Get("mid")
params := c.Request.Form
fidStr := params.Get("fid")
fid, err := strconv.ParseInt(fidStr, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", fidStr, err)
c.JSON(nil, ecode.RequestErr)
return
}
if err = favSvc.CleanInvalidArcs(c, mid.(int64), fid); err != nil {
log.Error("favSvc.CleanInvalidArcs(%d,%d) error(%v)", mid, fid, err)
}
c.JSON(nil, err)
}

View File

@@ -0,0 +1,38 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"archive.go",
"job.go",
"music.go",
"topic.go",
"video.go",
],
importpath = "go-common/app/interface/main/favorite/model",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/archive/api:go_default_library",
"//library/time:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,60 @@
package model
import (
"go-common/app/service/main/archive/api"
xtime "go-common/library/time"
)
type Archive struct {
Id int64 `json:"id"`
Mid int64 `json:"mid"`
Fid int64 `json:"fid"`
Aid int64 `json:"aid"`
CTime xtime.Time `json:"-"`
MTime xtime.Time `json:"-"`
}
type SearchArchive struct {
Code int `json:"code,omitempty"`
Seid string `json:"seid"`
Page int `json:"page"`
PageSize int `json:"pagesize"`
NumPages int `json:"numPages,omitempty"`
PageCount int `json:"pagecount"`
NumResults int `json:"numResults,omitempty"`
Total int `json:"total"`
SuggestKeyword string `json:"suggest_keyword"`
Mid int64 `json:"mid"`
Fid int64 `json:"fid"`
Tid int `json:"tid"`
Order string `json:"order"`
Keyword string `json:"keyword"`
TList []struct {
Tid int `json:"tid"`
Name string `json:"name"`
Count int `json:"count"`
} `json:"tlist,omitempty"`
Result []*SearchArchiveResult `json:"result,omitempty"`
Archives []*FavArchive `json:"archives"`
}
type SearchArchiveResult struct {
ID int64 `json:"id"`
Title string `json:"title"`
Play string `json:"play"`
FavTime int64 `json:"fav_time"`
}
type FavArchive struct {
*api.Arc
FavAt int64 `json:"fav_at"`
PlayNum string `json:"play_num"`
HighlightTitle string `json:"highlight_title"`
}
type AppInfo struct {
Platform string
Build string
MobiApp string
Device string
}

View File

@@ -0,0 +1,47 @@
package model
const (
// type
FieldFav = "folder"
FieldArc = "video"
FieldResource = "resource"
// action
ActionAdd = "add"
ActionDel = "del"
ActionMove = "move"
ActionCopy = "copy"
ActionMdel = "mdel"
ActionIndef = "indef"
ActionIncol = "incol"
ActionClean = "clean"
ActionInitRelationFids = "initRelationFids"
ActionInitFolderRelations = "initFolderRelations"
ActionMultiAdd = "multiAdd"
ActionMultiDel = "multiDel"
ActionFolderAdd = "folderAdd"
ActionFolderDel = "folderDel"
)
type Message struct {
Field string `json:"field"`
Action string `json:"action"`
Oid int64 `json:"oid"`
Type int8 `json:"type"`
Mid int64 `json:"mid"`
OldMid int64 `json:"old_mid"`
Fid int64 `json:"fid"`
FidState int8 `json:"fid_state"`
FolderAttr int8 `json:"folder_attr"`
OldFolderAttr int8 `json:"old_folder_attr"`
NewFolderAttr int8 `json:"new_folder_attr"`
Aid int64 `json:"aid"`
OldFid int64 `json:"old_fid"`
OldFidState int8 `json:"old_fid_state"`
NewFid int64 `json:"new_fid"`
NewFidState int8 `json:"new_fid_state"`
Affected int64 `json:"affected"`
Aids []int64 `json:"aids"`
Oids []int64 `json:"oids"`
Mids []int64 `json:"mids"`
FTime int64 `json:"ftime"`
}

View File

@@ -0,0 +1,12 @@
package model
type MusicResult struct {
Code int `json:"code"`
Data map[int64]*Music `json:"data"`
}
type Music struct {
ID int64 `json:"song_id"`
Cover string `json:"cover_url"`
Title string `json:"title"`
}

View File

@@ -0,0 +1,67 @@
package model
import (
"errors"
"go-common/library/time"
)
const (
TopicCacheMiss = -1
// http mode
HttpMode4Http = 1 // eg "http://a.bilibili.com"
HttpMode4Https = 2 // eg "https://a.bilibili.com"
HttpMode4Both = 3 // eg "//a.bilibili.com"
)
var ErrTopicRequest = errors.New("Get topic info request error")
// TopicsResult topics.
type TopicsResult struct {
Code int `json:"code"`
Data struct {
List []*Topic `json:"list"`
} `json:"data"`
}
type TopicFav struct {
ID int64 `json:"id"`
Mid int64 `json:"mid"`
TpID int64 `json:"tpid"`
Ctime time.Time `json:"ctime"`
Mtime time.Time `json:"mtime"`
}
type Topic struct {
ID int64 `json:"id"`
TpID int64 `json:"tp_id"`
MID int64 `json:"mid"`
FavAt time.Time `json:"fav_at"`
State int64 `json:"state"`
Stime string `json:"stime"`
Etime string `json:"etime"`
Ctime string `json:"ctime"`
Mtime string `json:"mtime"`
Name string `json:"name"`
Author string `json:"author"`
PCUrl string `json:"pc_url"`
H5Url string `json:"h5_url"`
PCCover string `json:"pc_cover"`
H5Cover string `json:"h5_cover"`
Rank int64 `json:"rank"`
PageName string `json:"page_name"`
Plat int64 `json:"plat"`
Desc string `json:"desc"`
Click int64 `json:"click"`
TPType int64 `json:"type"`
Mold int64 `json:"mold"`
Series int64 `json:"series"`
Dept int64 `json:"dept"`
ReplyID int64 `json:"reply_id"`
}
type TopicList struct {
PageNum int `json:"page"`
PageSize int `json:"pagesize"`
Total int64 `json:"total"`
List []*Topic `json:"list"`
}

View File

@@ -0,0 +1,206 @@
package model
import (
"fmt"
"sort"
xtime "go-common/library/time"
)
const (
bit1 = int8(1)
bit2 = int8(1) << 1
StateDefaultPublic = int8(0) // binary 00 / int 0
StateDefaultNoPublic = int8(0) | bit1 // binary 01 / int 1
StateNormalPublic = bit2 | int8(0) // binary 10 / int 2
StateNormalNoPublic = bit2 | bit1 // binary 11 / int 3
// DefaultFolderName default name of favorite folder
DefaultFolderName = "默认收藏夹"
// AllFidFlag all folder id flag
AllFidFlag = -1
// CDFlag cool down flag
CDFlag = -1
// search error code
SearchErrWordIllegal = -110 // 非法搜索词错误
// clean state
StateAllowToClean = 0
StateCleaning = 1
StateCleanCD = 2
)
type VideoFolder struct {
Fid int64 `json:"fid"`
Mid int64 `json:"mid"`
Name string `json:"name"`
MaxCount int `json:"max_count"`
CurCount int `json:"cur_count"`
AttenCount int `json:"atten_count"`
Favoured int8 `json:"favoured"`
State int8 `json:"state"`
CTime xtime.Time `json:"ctime"`
MTime xtime.Time `json:"mtime"`
Cover []*Cover `json:"cover,omitempty"`
}
// IsPublic return true if folder is public.
func (f *VideoFolder) IsPublic() bool {
return f.State&bit1 == int8(0)
}
// IsDefault return true if folder is default.
func (f *VideoFolder) IsDefault() bool {
return f.State&bit2 == int8(0)
}
// StatePub return folder's public state.
func (f *VideoFolder) StatePub() int8 {
return f.State & bit1
}
// StateDef return folder's default state.
func (f *VideoFolder) StateDef() int8 {
return f.State & bit2
}
// IsDefault return true if state is default state.
func IsDefault(state int8) bool {
return (state&(int8(1)<<1) == int8(0))
}
// CheckPublic check user update public value in [0, 1].
func CheckPublic(state int8) bool {
return state == int8(0) || state == bit1
}
type VideoFolders []*VideoFolder
func (f VideoFolders) Len() int { return len(f) }
func (f VideoFolders) Less(i, j int) bool {
if f[i].IsDefault() {
return true
}
if f[j].IsDefault() {
return false
}
if f[i].Fid > f[j].Fid {
return true
}
return false
}
func (f VideoFolders) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
// Cover image
type Cover struct {
Aid int64 `json:"aid"`
Pic string `json:"pic"`
}
// VideoFolderSort folder index.
type VideoFolderSort struct {
ID int64 `json:"id"`
Mid int64 `json:"mid"`
Sort []int64 `json:"sort"`
Map map[int64]struct{} `json:"map"`
CTime xtime.Time `json:"ctime"`
MTime xtime.Time `json:"mtime"`
}
// Index return index for fids.
func (f *VideoFolderSort) Index() []byte {
var (
i int
v int64
fs = f.Sort
n = len(fs) * 8
b = make([]byte, n)
)
for i = 0; i < n; i += 8 {
v = fs[i/8]
b[i] = byte(v >> 56)
b[i+1] = byte(v >> 48)
b[i+2] = byte(v >> 40)
b[i+3] = byte(v >> 32)
b[i+4] = byte(v >> 24)
b[i+5] = byte(v >> 16)
b[i+6] = byte(v >> 8)
b[i+7] = byte(v)
}
return b
}
// SetIndex set sort fids.
func (f *VideoFolderSort) SetIndex(b []byte) (err error) {
var (
i int
id int64
n = len(b)
ids = make([]int64, n)
)
if len(b)%8 != 0 {
err = fmt.Errorf("invalid sort index:%v", b)
return
}
f.Map = make(map[int64]struct{}, n)
for i = 0; i < n; i += 8 {
id = int64(b[i+7]) |
int64(b[i+6])<<8 |
int64(b[i+5])<<16 |
int64(b[i+4])<<24 |
int64(b[i+3])<<32 |
int64(b[i+2])<<40 |
int64(b[i+1])<<48 |
int64(b[i])<<56
ids[i/8] = id
f.Map[id] = struct{}{}
}
f.Sort = ids
return
}
// SortFavs sort the favorites by index.
func (f *VideoFolderSort) SortFavs(fs map[int64]*VideoFolder, isSelf bool) (res []*VideoFolder, update bool) {
var (
ok bool
id int64
sorted []int64
fav *VideoFolder
idx = f.Sort
)
res = make([]*VideoFolder, 0, len(fs))
if len(f.Sort) == 0 {
for _, fav = range fs {
if !isSelf && !fav.IsPublic() {
continue
}
res = append(res, fav)
}
sort.Sort(VideoFolders(res))
return
}
if len(idx) != len(fs) {
sorted = append(sorted, idx[0])
for id = range fs {
if _, ok = f.Map[id]; !ok {
sorted = append(sorted, id)
}
}
for _, id := range idx[1:] {
if _, ok = fs[id]; ok {
sorted = append(sorted, id)
}
}
update = true
f.Sort = sorted
}
for _, id = range f.Sort {
if fav, ok = fs[id]; ok {
if !isSelf && !fav.IsPublic() {
continue
}
res = append(res, fav)
}
}
return
}

View File

@@ -0,0 +1,69 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"rpc_test.go",
"service_test.go",
"topic_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/favorite/conf:go_default_library",
"//library/ecode:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"rpc.go",
"service.go",
"topic.go",
"video.go",
],
importpath = "go-common/app/interface/main/favorite/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/favorite/conf:go_default_library",
"//app/interface/main/favorite/dao/music:go_default_library",
"//app/interface/main/favorite/dao/topic:go_default_library",
"//app/interface/main/favorite/dao/video:go_default_library",
"//app/interface/main/favorite/model: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",
"//app/service/main/favorite/api:go_default_library",
"//app/service/main/favorite/model:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/metadata:go_default_library",
"//library/stat/prom:go_default_library",
"//library/sync/pipeline/fanout:go_default_library",
"//library/time:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,198 @@
package service
import (
"context"
"go-common/app/service/main/archive/api"
arcmdl "go-common/app/service/main/archive/model/archive"
favpb "go-common/app/service/main/favorite/api"
favmdl "go-common/app/service/main/favorite/model"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/time"
)
// ArcRPC find archive by rpc
func (s *Service) ArcRPC(c context.Context, aid int64) (a *api.Arc, err error) {
argAid := &arcmdl.ArgAid2{
Aid: aid,
}
if a, err = s.arcRPC.Archive3(c, argAid); err != nil {
log.Error("s.arcRPC.Archive3(%v), error(%v)", argAid, err)
}
if !a.IsNormal() {
err = ecode.ArchiveNotExist
}
return
}
// ArcsRPC find archives by rpc
func (s *Service) ArcsRPC(c context.Context, aids []int64) (as map[int64]*api.Arc, err error) {
if len(aids) == 0 {
return
}
argAids := &arcmdl.ArgAids2{
Aids: aids,
}
if as, err = s.arcRPC.Archives3(c, argAids); err != nil {
log.Error("s.arcRPC.Archives3(%v, archives), err(%v)", argAids, err)
}
return
}
// AddFavRPC add favorite .
func (s *Service) AddFavRPC(c context.Context, typ int8, mid, aid, fid int64) (err error) {
arg := &favpb.AddFavReq{Tp: int32(typ), Mid: mid, Oid: aid, Fid: fid}
_, err = s.favClient.AddFav(c, arg)
if err != nil {
log.Error("s.favClient.AddFav(%+v) error(%v)", arg, err)
}
return
}
// DelFavRPC del favorite .
func (s *Service) DelFavRPC(c context.Context, typ int8, mid, aid, fid int64) (err error) {
arg := &favpb.DelFavReq{Tp: int32(typ), Mid: mid, Oid: aid, Fid: fid}
if _, err = s.favClient.DelFav(c, arg); err != nil {
log.Error("s.favClient.DelFavRPC(%+v) error(%v)", arg, err)
}
return
}
// FavoritesRPC favorites list.
func (s *Service) FavoritesRPC(c context.Context, typ int8, mid, vmid, fid int64, tid int, keyword, order string, pn, ps int) (favs *favmdl.Favorites, err error) {
arg := &favpb.FavoritesReq{Tp: int32(typ), Mid: mid, Uid: vmid, Fid: fid, Tid: int32(tid), Keyword: keyword, Order: order, Pn: int32(pn), Ps: int32(ps)}
var reply *favpb.FavoritesReply
if reply, err = s.favClient.Favorites(c, arg); err != nil {
log.Error("s.favClient.Favorites(%+v) error(%v)", arg, err)
return
}
favs = &favmdl.Favorites{}
favs.Page.Count = int(reply.Res.Page.Count)
favs.Page.Num = int(reply.Res.Page.Num)
favs.Page.Size = int(reply.Res.Page.Size_)
for _, data := range reply.Res.List {
favs.List = append(favs.List, &favmdl.Favorite{
ID: data.Id,
Oid: data.Oid,
Mid: data.Mid,
Fid: data.Fid,
Type: int8(data.Type),
State: int8(data.State),
CTime: time.Time(data.Ctime),
MTime: time.Time(data.Mtime),
})
}
return
}
// IsFavByFidRPC return user whether favored
func (s *Service) IsFavByFidRPC(c context.Context, typ int8, mid, aid int64, fid int64) (res bool, err error) {
arg := &favpb.IsFavoredByFidReq{Type: int32(typ), Mid: mid, Oid: aid, Fid: fid}
var reply *favpb.IsFavoredReply
if reply, err = s.favClient.IsFavoredByFid(c, arg); err != nil {
log.Error("s.favClient.IsFavoredByFid(%+v) error(%v)", arg, err)
return
}
res = reply.Faved
return
}
// IsFavRPC return user whether favored
func (s *Service) IsFavRPC(c context.Context, typ int8, mid, aid int64) (res bool, err error) {
arg := &favpb.IsFavoredReq{Typ: int32(typ), Mid: mid, Oid: aid}
var reply *favpb.IsFavoredReply
if reply, err = s.favClient.IsFavored(c, arg); err != nil {
log.Error("s.favClient.IsFavored(%+v) error(%v)", arg, err)
return
}
res = reply.Faved
return
}
// InDefaultRPC return aid whether in default fodler.
func (s *Service) InDefaultRPC(c context.Context, typ int8, mid, aid int64) (res bool, err error) {
arg := &favpb.InDefaultFolderReq{Typ: int32(typ), Mid: mid, Oid: aid}
var reply *favpb.InDefaultFolderReply
if reply, err = s.favClient.InDefault(c, arg); err != nil {
log.Error("s.favClient.IsFavored(%+v) error(%v)", arg, err)
return
}
res = reply.IsIn
return
}
// IsFavsRPC return user's oids whether favored
func (s *Service) IsFavsRPC(c context.Context, typ int8, mid int64, aids []int64) (res map[int64]bool, err error) {
arg := &favpb.IsFavoredsReq{Typ: int32(typ), Mid: mid, Oids: aids}
var reply *favpb.IsFavoredsReply
if reply, err = s.favClient.IsFavoreds(c, arg); err != nil {
log.Error("s.favClient.IsFavoreds(%+v) error(%v)", arg, err)
return
}
res = reply.Faveds
return
}
// AllFoldersRPC user's folders list.
func (s *Service) AllFoldersRPC(c context.Context, typ int8, mid, vmid, oid int64, ip string) (fs []*favmdl.Folder, err error) {
arg := &favpb.UserFoldersReq{Typ: int32(typ), Mid: mid, Vmid: vmid, Oid: oid}
var reply *favpb.UserFoldersReply
if reply, err = s.favClient.UserFolders(c, arg); err != nil {
log.Error("s.favClient.UserFolders(%+v) error(%v)", arg, err)
return
}
fs = reply.GetRes()
return
}
// FolderRPC user's folder .
func (s *Service) FolderRPC(c context.Context, typ int8, fid, mid, vmid int64) (f *favmdl.Folder, err error) {
arg := &favpb.UserFolderReq{Typ: int32(typ), Mid: mid, Vmid: vmid, Fid: fid}
var reply *favpb.UserFolderReply
if reply, err = s.favClient.UserFolder(c, arg); err != nil {
log.Error("s.favClient.UserFolder(%+v) error(%v)", arg, err)
return
}
f = reply.GetRes()
return
}
// TlistsRPC archive type list.
func (s *Service) TlistsRPC(c context.Context, typ int8, mid, vmid, fid int64) (ps []*favmdl.Partition, err error) {
arg := &favpb.TlistsReq{Tp: int32(typ), Mid: mid, Uid: vmid, Fid: fid}
var reply *favpb.TlistsReply
if reply, err = s.favClient.Tlists(c, arg); err != nil {
log.Error("s.favClient.Tlists(%+v) error(%v)", arg, err)
return
}
ps = make([]*favmdl.Partition, 0)
for _, v := range reply.Res {
ps = append(ps, &favmdl.Partition{
Tid: int(v.Tid),
Name: v.Name,
Count: int(v.Count),
})
}
return
}
// RecentsRPC recent favs .
func (s *Service) RecentsRPC(c context.Context, typ int8, mid int64, size int) (aids []int64, err error) {
arg := &favpb.RecentFavsReq{Tp: int32(typ), Mid: mid, Size_: int32(size)}
var reply *favpb.RecentFavsReply
if reply, err = s.favClient.RecentFavs(c, arg); err != nil {
log.Error("s.favClient.RecentFavs(%+v) error(%v)", arg, err)
return
}
aids = reply.GetRes()
return
}
// TypesRPC find all archives's type by rpc
func (s *Service) TypesRPC(c context.Context) (ats map[int16]*arcmdl.ArcType, err error) {
if ats, err = s.arcRPC.Types2(c); err != nil {
log.Error("s.arcRPC.Types2(), error(%v)", err)
}
return
}

View File

@@ -0,0 +1,21 @@
package service
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func Test_ArcsRPC(t *testing.T) {
Convey("ArcsRPC", t, func() {
var (
aids = []int64{123, 345}
)
res, err := s.ArcsRPC(context.TODO(), aids)
t.Logf("res:%+v", res)
t.Logf("err:%+v", err)
So(res, ShouldNotBeNil)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,70 @@
package service
import (
"context"
"go-common/app/interface/main/favorite/conf"
musicDao "go-common/app/interface/main/favorite/dao/music"
topicDao "go-common/app/interface/main/favorite/dao/topic"
videoDao "go-common/app/interface/main/favorite/dao/video"
arcrpc "go-common/app/service/main/archive/api/gorpc"
favpb "go-common/app/service/main/favorite/api"
"go-common/library/log"
"go-common/library/stat/prom"
"go-common/library/sync/pipeline/fanout"
)
// Service define fav service
type Service struct {
conf *conf.Config
// dao
videoDao *videoDao.Dao
topicDao *topicDao.Dao
musicDao *musicDao.Dao
// cache chan
cache *fanout.Fanout
// prom
prom *prom.Prom
// rpc
favClient favpb.FavoriteClient
arcRPC *arcrpc.Service2
}
// New return fav service
func New(c *conf.Config) (s *Service) {
s = &Service{
conf: c,
// dao
videoDao: videoDao.New(c),
topicDao: topicDao.New(c),
musicDao: musicDao.New(c),
// cache
cache: fanout.New("cache"),
// prom
prom: prom.New().WithTimer("fav_add_video", []string{"method"}),
// rpc
arcRPC: arcrpc.New2(c.RPCClient2.Archive),
}
favClient, err := favpb.New(c.RPCClient2.FavClient)
if err != nil {
panic(err)
}
s.favClient = favClient
return
}
// Ping check service health
func (s *Service) Ping(c context.Context) (err error) {
return s.videoDao.Ping(c)
}
// Close close service
func (s *Service) Close() {
s.videoDao.Close()
}
// PromError stat and log.
func (s *Service) PromError(name string, format string, args ...interface{}) {
prom.BusinessErrCount.Incr(name)
log.Error(format, args...)
}

View File

@@ -0,0 +1,22 @@
package service
import (
"flag"
"fmt"
"path/filepath"
"go-common/app/interface/main/favorite/conf"
)
var (
s *Service
)
func init() {
dir, _ := filepath.Abs("../cmd/favorite-test.toml")
flag.Set("conf", dir)
if err := conf.Init(); err != nil {
fmt.Printf("conf.Init() error(%v)", err)
}
s = New(conf.Conf)
}

View File

@@ -0,0 +1,82 @@
package service
import (
"context"
"go-common/app/interface/main/favorite/model"
favmdl "go-common/app/service/main/favorite/model"
"go-common/library/ecode"
"go-common/library/log"
)
var _emptyTopics = []*model.Topic{}
// AddFavTopic add fav topic
func (s *Service) AddFavTopic(c context.Context, mid, tpID int64, ck, ak string) (err error) {
tpIDs := []int64{tpID}
tps, err := s.topicDao.TopicMap(c, tpIDs, false, nil)
if err != nil {
log.Error("s.topic.Get(%v)", err)
return
}
if len(tps) == 0 {
err = ecode.TopicNotExist
return
}
if err = s.AddFavRPC(c, favmdl.TypeTopic, mid, tpID, 0); err != nil {
log.Error(" s.AddFavRPC(%d,%d) error(%v)", mid, tpID, err)
}
return
}
// DelFavTopic del fav topic
func (s *Service) DelFavTopic(c context.Context, mid, tpID int64) (err error) {
if err = s.DelFavRPC(c, favmdl.TypeTopic, mid, tpID, 0); err != nil {
log.Error("s.DelFavRPC(%d,%d) error(%v)", mid, tpID, err)
}
return
}
// IsTopicFavoured topic is favoured.
func (s *Service) IsTopicFavoured(c context.Context, mid, tpID int64) (faved bool, err error) {
typ := favmdl.TypeTopic
if faved, err = s.IsFavRPC(c, typ, mid, tpID); err != nil {
log.Error("s.IsFavRPC(%d,%d,%d) error(%v)", typ, mid, tpID, err)
}
return
}
// FavTopics get fav topics
func (s *Service) FavTopics(c context.Context, mid int64, pn, ps int, appInfo *model.AppInfo) (res *model.TopicList, err error) {
res = &model.TopicList{}
res.PageNum = pn
res.PageSize = ps
typ := favmdl.TypeTopic
favs, err := s.FavoritesRPC(c, typ, mid, mid, 0, 0, "", "", pn, ps)
if err != nil {
log.Error("s.Favorites(%d,%d,%d,%d,%d,%d,%s) error(%v)", typ, mid, 0, pn, ps, err)
return
}
res.Total = int64(favs.Page.Count)
var oids []int64
for _, fav := range favs.List {
oids = append(oids, fav.Oid)
}
if res.Total == 0 {
res.List = _emptyTopics
return
}
topics, err := s.topicDao.TopicMap(c, oids, false, appInfo)
if err != nil {
log.Error("s.topic.MuliGet error(%v)", err)
return
}
for _, fav := range favs.List {
if topic, ok := topics[fav.Oid]; ok {
topic.FavAt = fav.MTime
topic.MID = mid
res.List = append(res.List, topic)
}
}
return
}

View File

@@ -0,0 +1,61 @@
package service
import (
"context"
"go-common/library/ecode"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func Test_FavTopics(t *testing.T) {
Convey("FavTopics", t, func() {
var (
mid int64 = 88888894
pn = 1
ps = 30
)
res, err := s.FavTopics(context.TODO(), mid, pn, ps, nil)
t.Logf("res:%v", res)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}
func Test_IsTopicFavoured(t *testing.T) {
Convey("IsTopicFavoured", t, func() {
var (
mid int64 = 88888894
tpID int64 = 3456
)
res, err := s.IsTopicFavoured(context.TODO(), mid, tpID)
t.Logf("res:%v", res)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}
func Test_AddFavTopic(t *testing.T) {
Convey("AddFavTopic", t, func() {
var (
mid int64 = 88888894
tpID int64 = 3456
ck, ak string
)
err := s.AddFavTopic(context.TODO(), mid, tpID, ck, ak)
t.Logf("err:%v", err)
So(err, ShouldEqual, ecode.FavTopicExist)
})
}
func Test_DelFavTopic(t *testing.T) {
Convey("DelFavTopic", t, func() {
var (
mid int64 = 88888894
tpID int64 = 3457
)
err := s.DelFavTopic(context.TODO(), mid, tpID)
t.Logf("err:%v", err)
So(err, ShouldEqual, ecode.FavVideoAlreadyDel)
})
}

View File

@@ -0,0 +1,606 @@
package service
import (
"context"
"html/template"
"math"
musicmdl "go-common/app/interface/main/favorite/model"
"go-common/app/service/main/archive/api"
pb "go-common/app/service/main/favorite/api"
"go-common/app/service/main/favorite/model"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
)
var (
_emptyArchives = []*model.FavArchive{}
_emptyVideoFolders = []*model.VideoFolder{}
)
// newCovers get three cover of each fid
func (s *Service) newCovers(c context.Context, mid int64, recents map[int64][]*model.Resource) (fcvs map[int64][]*model.Cover, err error) {
var (
fids, misFids []int64
)
for fid := range recents {
fids = append(fids, fid)
}
if fcvs, misFids, err = s.videoDao.NewCoversCache(c, mid, fids); err != nil {
log.Error("s.videoDao.NewCoversCache(fids %v) err(%v)", fids, err)
return
}
// get miss cover from db
if len(misFids) > 0 {
var (
allAids []int64
allMids []int64
as map[int64]*api.Arc
ms map[int64]*musicmdl.Music
)
for _, fid := range misFids {
if resources, ok := recents[fid]; ok {
for _, res := range resources {
if int8(res.Typ) == model.TypeVideo {
allAids = append(allAids, res.Oid)
} else {
allMids = append(allMids, res.Oid)
}
}
}
}
if len(allAids) > 0 {
if as, err = s.arcsRPC(c, allAids); err != nil {
log.Error("s.arcsRPC(aids %v),err(%v)", allAids, err)
return
}
}
if len(allMids) > 0 {
if ms, err = s.musicDao.MusicMap(c, allMids); err != nil {
log.Error("s.musicMap(allMids %v),err(%v)", allMids, err)
return
}
}
// set miss fid's cover
for _, misFid := range misFids {
fid := misFid
cvs := make([]*model.Cover, 0)
for _, res := range recents[fid] {
cv := &model.Cover{}
cv.Aid = res.Oid
cv.Type = res.Typ
if int8(res.Typ) == model.TypeVideo {
if arc, ok := as[res.Oid]; ok {
if !arc.IsNormal() {
continue
}
cv.Pic = arc.Pic
cvs = append(cvs, cv)
}
} else {
if music, ok := ms[res.Oid]; ok {
cv.Pic = music.Cover
cvs = append(cvs, cv)
}
}
}
if err := s.videoDao.SetNewCoverCache(c, mid, fid, cvs); err != nil {
log.Error("s.videoDao.SetNewCoverCache(%d,%d,%v) error(%v)", mid, fid, cvs, err)
}
fcvs[fid] = cvs
}
}
return
}
func (s *Service) arcsRPC(c context.Context, aids []int64) (arcsMap map[int64]*api.Arc, err error) {
var (
batch = s.conf.Fav.MaxPagesize
arcs map[int64]*api.Arc
)
arcsMap = make(map[int64]*api.Arc, len(aids))
for len(aids) > 0 {
if len(aids) < batch {
batch = len(aids)
}
arcs, err = s.ArcsRPC(c, aids[:batch])
if err != nil {
log.Error("s.ArcsRPC(%v) error(%v)", aids[:batch], err)
return
}
for k, v := range arcs {
arcsMap[k] = v
}
aids = aids[batch:]
}
return
}
func (s *Service) normalArcs(c context.Context, aids []int64) (as []*api.Arc, err error) {
arcs, err := s.ArcsRPC(c, aids)
if err != nil {
log.Error("s.ArcsRPC(%v) error(%v)", aids, err)
return
}
as = make([]*api.Arc, 0, len(aids))
for _, v := range aids {
if a, ok := arcs[v]; ok {
as = append(as, a)
}
}
return
}
// FavVideo get fav videos from search or db
func (s *Service) FavVideo(c context.Context, mid, vmid, uid, fid int64, keyword, order string, tid, pn, ps int) (sv *model.SearchArchive, err error) {
if order != "click" && order != "pubdate" {
order = model.SortMtime
}
if order == "pubdate" {
order = model.SortPubtime
}
sv = new(model.SearchArchive)
var favs *model.Favorites
if favs, err = s.FavoritesRPC(c, model.TypeVideo, mid, vmid, fid, tid, keyword, order, pn, ps); err != nil || favs == nil {
log.Error("s.FavoritesRPC(%d,%d,%d,%d,%d,%d) error(%v)", model.TypeVideo, mid, vmid, fid, pn, ps, err)
return
}
if len(favs.List) == 0 {
sv.Result = nil
sv.Archives = _emptyArchives
return
}
if err = s.newFillArchives(c, favs.List, sv); err != nil {
log.Error("s.newFillArchives error(%v)", err)
}
sv.Mid = uid
sv.Fid = fid
sv.Tid = tid
sv.Order = order
sv.Keyword = keyword
sv.PageCount = int(math.Ceil(float64(favs.Page.Count) / float64(s.conf.Fav.MaxPagesize)))
sv.PageSize = s.conf.Fav.MaxPagesize
sv.Total = favs.Page.Count
sv.NumPages = 0
sv.NumResults = 0
return
}
// TidList get video folder type names from search.
func (s *Service) TidList(c context.Context, mid, vmid, uid, fid int64) (res []*model.Partition, err error) {
tidCounts, err := s.TlistsRPC(c, model.TypeVideo, mid, vmid, fid)
if err != nil {
log.Error("s.TlistsRPC(%d,%d,%d,%d) error(%v)", model.TypeVideo, mid, vmid, fid, err)
return
}
types, err := s.TypesRPC(c)
if err != nil {
log.Error("s.TypesRPC() error(%v)", err)
return
}
for _, t := range tidCounts {
if t.Tid == 0 {
continue
}
if v, ok := types[int16(t.Tid)]; ok {
t.Name = v.Name
}
res = append(res, t)
}
return
}
func (s *Service) archive(c context.Context, aid int64) (arc *api.Arc, err error) {
arc, err = s.ArcRPC(c, aid)
if err != nil {
log.Error("s.ArcRPC(%d), error(%v)", aid, err)
}
if !arc.IsNormal() {
err = ecode.ArchiveNotExist
}
return
}
// FavFolders get mid user's favorites.
func (s *Service) FavFolders(c context.Context, mid, vmid, uid, aid int64, isSelf bool, mediaList bool, fromWeb bool) (res []*model.VideoFolder, err error) {
var fs []*model.Folder
typ := model.TypeVideo
ip := metadata.String(c, metadata.RemoteIP)
if fs, err = s.AllFoldersRPC(c, typ, mid, vmid, aid, ip); err != nil {
log.Error("s.AllFoldersRPC(%d,%d,%d,%d,%s) error(%v)", typ, mid, vmid, ip, err)
return
}
if len(fs) == 0 {
res = _emptyVideoFolders
return
}
faids := make(map[int64][]*model.Resource, len(fs))
for _, f := range fs {
faids[f.ID] = f.RecentRes
}
var covers map[int64][]*model.Cover
if covers, err = s.newCovers(c, uid, faids); err != nil {
log.Error("s.newCovers(%d,%v) error(%v)", uid, faids, err)
err = nil
}
//兼容老的缓存,后期下掉
for _, cover := range covers {
for _, co := range cover {
if co.Type == 0 {
co.Type = int32(model.TypeVideo)
}
}
}
for _, f := range fs {
maxCount := model.DefaultFolderLimit
if !f.IsDefault() {
maxCount = model.NormalFolderLimit
}
name := f.Name
if fromWeb { // web端html转义
name = template.HTMLEscapeString(name)
}
if mediaList {
if f.IsDefault() && name == "默认收藏夹" {
name = "默认播单"
}
}
cover := []*model.Cover{}
if mediaList {
if f.Cover != "" {
cover = []*model.Cover{{
Type: 0,
Pic: f.Cover,
}}
} else {
cover = covers[f.ID]
}
} else {
for _, co := range covers[f.ID] {
if int8(co.Type) == model.TypeVideo {
cover = append(cover, co)
}
}
}
vf := &model.VideoFolder{
MediaId: f.ID*100 + f.Mid%100,
Fid: f.ID,
Mid: f.Mid,
Name: name,
MaxCount: maxCount,
CurCount: f.Count,
Favoured: f.Favored,
State: int8(f.Attr & 3),
CTime: f.CTime,
MTime: f.MTime,
Cover: cover,
}
res = append(res, vf)
}
return
}
// AddFavFolder add a new favorite folder
func (s *Service) AddFavFolder(c context.Context, mid int64, name, cookie, accessKey string, state int32) (fid int64, err error) {
var reply *pb.AddFolderReply
reply, err = s.favClient.AddFolder(c, &pb.AddFolderReq{
Typ: int32(model.TypeVideo),
Mid: mid,
Name: name,
Cookie: cookie,
AccessKey: accessKey,
Public: state,
})
if err != nil {
return
}
fid = reply.Fid
return
}
// UpFavName update favorite name.
func (s *Service) UpFavName(c context.Context, mid, fid int64, name, cookie, accessKey string) (err error) {
_, err = s.favClient.UpFolderName(c, &pb.UpFolderNameReq{
Typ: int32(model.TypeVideo),
Fid: fid,
Mid: mid,
Name: name,
Cookie: cookie,
AccessKey: accessKey,
})
return
}
// SetVideoFolderSort set folder sort.
func (s *Service) SetVideoFolderSort(c context.Context, mid int64, fids []int64) (err error) {
_, err = s.favClient.SetFolderSort(c, &pb.SetFolderSortReq{
Typ: int32(model.TypeVideo),
Mid: mid,
Fids: fids,
})
return
}
// UpFavState update folder state.
func (s *Service) UpFavState(c context.Context, mid, fid int64, public int32, cookie string, accessKey string) (err error) {
_, err = s.favClient.UpFolderAttr(c, &pb.UpFolderAttrReq{
Typ: int32(model.TypeVideo),
Fid: fid,
Mid: mid,
Public: public,
})
return
}
// DelVideoFolder delete favFolder and push databus msg to del videos in folder.
func (s *Service) DelVideoFolder(c context.Context, mid, fid int64) (err error) {
_, err = s.favClient.DelFolder(c, &pb.DelFolderReq{
Typ: int32(model.TypeVideo),
Mid: mid,
Fid: fid,
})
return
}
// RecentArcs return the newest archives in all folder.
func (s *Service) RecentArcs(c context.Context, mid int64, pageNum, pageSize int) (sv *model.SearchArchive, err error) {
aids, err := s.RecentsRPC(c, model.TypeVideo, mid, pageSize)
if err != nil {
return
}
sv = new(model.SearchArchive)
if len(aids) == 0 {
sv.Result = nil
sv.Archives = _emptyArchives
return
}
archives, err := s.normalArcs(c, aids)
if err != nil {
log.Error("s.NormalArchives(%v) error(%v)", sv, err)
return
}
if err = s.fillArchives(c, sv); err != nil {
log.Error("s.RecentArcs err(%v)", err)
}
farchives := make([]*model.FavArchive, 0, len(archives))
for _, arc := range archives {
farchive := new(model.FavArchive)
farchive.Arc = arc
farchives = append(farchives, farchive)
}
sv.Result = nil
sv.Archives = farchives
sv.Mid = mid
sv.PageCount = sv.NumPages
sv.Total = sv.NumResults
sv.NumPages = 0
sv.NumResults = 0
return
}
func (s *Service) fillArchives(c context.Context, sv *model.SearchArchive) (err error) {
aids := make([]int64, 0, len(sv.Result))
searchArcs := make(map[int64]*model.SearchArchiveResult, len(sv.Result))
for _, v := range sv.Result {
aids = append(aids, v.ID)
searchArcs[v.ID] = &model.SearchArchiveResult{
FavTime: v.FavTime,
Title: v.Title,
Play: v.Play,
}
}
archives, err := s.normalArcs(c, aids)
if err != nil {
log.Error("s.NormalArchives(%v) error(%v)", sv, err)
return
}
farchives := make([]*model.FavArchive, 0, len(archives))
for _, arc := range archives {
var farchive = &model.FavArchive{}
farchive.Arc = arc
farchive.FavAt = searchArcs[arc.Aid].FavTime
farchive.HighlightTitle = searchArcs[arc.Aid].Title
farchive.PlayNum = searchArcs[arc.Aid].Play
farchives = append(farchives, farchive)
}
sv.Result = nil
sv.Archives = farchives
return
}
func (s *Service) newFillArchives(c context.Context, favorites []*model.Favorite, sv *model.SearchArchive) (err error) {
aids := make([]int64, 0, len(sv.Result))
favoriteArcs := make(map[int64]*model.Favorite, len(sv.Result))
for _, v := range favorites {
aids = append(aids, v.Oid)
favoriteArcs[v.Oid] = v
}
archives, err := s.normalArcs(c, aids)
if err != nil {
log.Error("s.normalArcs(%v) error(%v)", aids, err)
return
}
farchives := make([]*model.FavArchive, 0, len(archives))
for _, arc := range archives {
var farchive = &model.FavArchive{}
farchive.Arc = arc
farchive.FavAt = int64(favoriteArcs[arc.Aid].MTime)
farchive.HighlightTitle = arc.Title
farchives = append(farchives, farchive)
}
sv.Result = nil
sv.Archives = farchives
return
}
// AddArc add a archive into folder.
func (s *Service) AddArc(c context.Context, mid, fid, aid int64, ck, ak string) (err error) {
if _, err = s.archive(c, aid); err != nil {
return
}
_, err = s.favClient.AddFav(c, &pb.AddFavReq{
Tp: int32(model.TypeVideo),
Mid: mid,
Fid: fid,
Oid: aid,
})
if err != nil {
return
}
s.cache.Do(c, func(c context.Context) {
if err := s.videoDao.DelCoverCache(c, mid, fid); err != nil {
log.Error("s.videoDao.DelCoverCache(%d,%d) error(%v)", mid, fid, err)
}
})
return
}
// AddArcToFolders add a archive into multi folders.
func (s *Service) AddArcToFolders(c context.Context, mid, aid int64, fids []int64, ck, ak string) (err error) {
if len(fids) == 0 {
err = s.AddArc(c, mid, 0, aid, ck, ak)
}
for _, fid := range fids {
err = s.AddArc(c, mid, fid, aid, ck, ak)
}
return
}
// DelArc delete a archive from favorite.
func (s *Service) DelArc(c context.Context, mid, fid, aid int64) (err error) {
_, err = s.favClient.DelFav(c, &pb.DelFavReq{
Tp: int32(model.TypeVideo),
Mid: mid,
Fid: fid,
Oid: aid,
})
if err != nil {
return
}
s.cache.Do(c, func(c context.Context) {
if err := s.videoDao.DelCoverCache(c, mid, fid); err != nil {
log.Error("s.videoDao.DelCoverCache(%d,%d) error(%v)", mid, fid, err)
}
})
return
}
// DelArcs delete some archives from favorite.
func (s *Service) DelArcs(c context.Context, mid, fid int64, aids []int64) (err error) {
_, err = s.favClient.MultiDel(c, &pb.MultiDelReq{
Typ: int32(model.TypeVideo),
Mid: mid,
Fid: fid,
Oids: aids,
})
if err != nil {
return
}
s.cache.Do(c, func(c context.Context) {
if err := s.videoDao.DelCoverCache(c, mid, fid); err != nil {
log.Error("s.videoDao.DelCoverCache(%d,%d) error(%v)", mid, fid, err)
}
})
return
}
// MoveArcs move archives from old favorite to new favorite
func (s *Service) MoveArcs(c context.Context, mid, oldfid, newfid int64, aids []int64) (err error) {
if len(aids) == 0 || oldfid == newfid {
return
}
_, err = s.favClient.MoveFavs(c, &pb.MoveFavsReq{
Typ: int32(model.TypeVideo),
Mid: mid,
OldFid: oldfid,
NewFid: newfid,
Oids: aids,
})
if err != nil {
return
}
s.cache.Do(c, func(c context.Context) {
if err := s.videoDao.DelCoverCache(c, mid, newfid); err != nil {
log.Error("s.videoDao.DelCoverCache(%d,%d) error(%v)", mid, newfid, err)
}
if err := s.videoDao.DelCoverCache(c, mid, oldfid); err != nil {
log.Error("s.videoDao.DelCoverCache(%d,%d) error(%v)", mid, oldfid, err)
}
})
return
}
// CopyArcs copy archives to other favorite.
func (s *Service) CopyArcs(c context.Context, mid, oldmid, oldfid, newfid int64, aids []int64) (err error) {
if len(aids) == 0 || oldfid == newfid {
return
}
_, err = s.favClient.CopyFavs(c, &pb.CopyFavsReq{
Typ: int32(model.TypeVideo),
OldMid: oldmid,
Mid: mid,
OldFid: oldfid,
NewFid: newfid,
Oids: aids,
})
if err != nil {
return
}
s.cache.Do(c, func(c context.Context) {
if err := s.videoDao.DelCoverCache(c, mid, newfid); err != nil {
log.Error("s.videoDao.DelCoverCache(%d,%d) error(%v)", mid, newfid, err)
}
})
return
}
// IsFaveds check if aids faved by user
func (s *Service) IsFaveds(c context.Context, mid int64, aids []int64) (m map[int64]bool, err error) {
if m, err = s.IsFavsRPC(c, model.TypeVideo, mid, aids); err != nil {
log.Error("s.IsFavsRPC(%d,%d,%v) error(%v)", model.TypeVideo, mid, aids, err)
}
return
}
// IsFaved check if aid faved by user
func (s *Service) IsFaved(c context.Context, mid, aid int64) (faved bool, count int, err error) {
if faved, err = s.IsFavRPC(c, model.TypeVideo, mid, aid); err != nil {
log.Error("s.IsFavsRPC(%d,%d,%d) error(%v)", model.TypeVideo, mid, aid, err)
}
count = 1
return
}
// InDef detemine aid whether or not archive in default folder.
func (s *Service) InDef(c context.Context, mid, aid int64) (isin bool, err error) {
if isin, err = s.InDefaultRPC(c, model.TypeVideo, mid, aid); err != nil {
log.Error("s.InDefaultRPC(%d,%d,%d) error(%v)", model.TypeVideo, mid, aid, err)
}
return
}
// CleanState return this folder clean state.
func (s *Service) CleanState(c context.Context, mid, fid int64) (cleanState int, err error) {
reply, err := s.favClient.CleanState(c, &pb.CleanStateReq{
Typ: int32(model.TypeVideo),
Mid: mid,
Fid: fid,
})
if err != nil {
return
}
cleanState = int(reply.CleanState)
return
}
// CleanInvalidArcs clean invalid archives.
func (s *Service) CleanInvalidArcs(c context.Context, mid, fid int64) (err error) {
_, err = s.favClient.CleanInvalidFavs(c, &pb.CleanInvalidFavsReq{
Typ: int32(model.TypeVideo),
Mid: mid,
Fid: fid,
})
return
}