├── .prettierignore ├── database.png ├── cmd ├── chat │ ├── kitex.yaml │ ├── dal │ │ ├── init.go │ │ └── db │ │ │ ├── init.go │ │ │ └── chat.go │ ├── main.go │ ├── build.sh │ ├── script │ │ └── bootstrap.sh │ ├── pack │ │ └── chat.go │ ├── chatservice │ │ ├── post_msg.go │ │ └── get_msg.go │ └── handler.go ├── user │ ├── kitex.yaml │ ├── dal │ │ ├── init.go │ │ └── db │ │ │ ├── init.go │ │ │ ├── user.go │ │ │ └── video.go │ ├── build.sh │ ├── script │ │ └── bootstrap.sh │ ├── userService │ │ ├── user_publish_action.go │ │ ├── user_publish_list.go │ │ ├── user_login.go │ │ ├── user_info.go │ │ ├── user_register.go │ │ └── user_get_feed.go │ ├── benchmark │ │ ├── user_register_test.go │ │ ├── user_publish_list_test.go │ │ ├── user_login_test.go │ │ ├── user_get_feed_test.go │ │ ├── user_info_test.go │ │ └── user_publish_action_test.go │ ├── main.go │ ├── pack │ │ ├── user.go │ │ └── video.go │ ├── test │ │ ├── user_publish_action_test.go │ │ ├── user_publish_list_test.go │ │ └── user_register_test.go │ └── handler.go ├── useruser │ ├── kitex.yaml │ ├── dal │ │ ├── init.go │ │ └── db │ │ │ └── init.go │ ├── build.sh │ ├── script │ │ └── bootstrap.sh │ ├── main.go │ ├── uuservice │ │ ├── follow_list.go │ │ ├── follower_list.go │ │ ├── friend_list.go │ │ └── action.go │ ├── benchmark │ │ ├── follower_list_test.go │ │ ├── follow_list_test.go │ │ ├── friend_list_test.go │ │ └── action_test.go │ ├── pack │ │ └── user.go │ └── handler.go ├── userplat │ ├── kitex.yaml │ ├── dal │ │ ├── init.go │ │ └── db │ │ │ ├── init.go │ │ │ ├── comment.go │ │ │ └── like.go │ ├── build.sh │ ├── script │ │ └── bootstrap.sh │ ├── pack │ │ ├── comment.go │ │ └── video.go │ ├── main.go │ ├── userplatService │ │ ├── userplat_favorite_list.go │ │ ├── userplat_comment_list.go │ │ ├── userplat_favorite_action.go │ │ └── userplat_comment_action.go │ ├── benchmark │ │ ├── userplat_comment_list_test.go │ │ ├── userplat_favorite_list_test.go │ │ ├── userplat_favorite_action_test.go │ │ └── userplat_comment_action_test.go │ ├── test │ │ ├── userplat_favorite_action_test.go │ │ ├── userplat_comment_list_test.go │ │ └── userplat_favorite_list_test.go │ └── handler.go └── web │ ├── rpc │ ├── init.go │ ├── userplat.go │ ├── user.go │ └── useruser.go │ ├── main.go │ ├── controller │ ├── demo_data.go │ ├── feed.go │ ├── favorite.go │ ├── comment.go │ ├── common.go │ ├── relation.go │ ├── message.go │ ├── user.go │ └── publish.go │ └── router.go ├── package.json ├── pkg ├── salt │ ├── setting.go │ └── salt.go ├── jwt │ ├── setting.go │ └── jwt.go ├── middleware │ ├── server.go │ ├── client.go │ └── common.go ├── consts │ └── consts.go ├── cover │ └── cover.go ├── model.go └── allerrors │ └── allerrors.go ├── kitex_gen ├── chat │ ├── k-consts.go │ └── chatservice │ │ ├── server.go │ │ ├── invoker.go │ │ ├── client.go │ │ └── chatservice.go ├── user │ ├── k-consts.go │ ├── userservice │ │ ├── server.go │ │ ├── invoker.go │ │ └── client.go │ └── user_validator.go ├── userplat │ ├── k-consts.go │ ├── userplatservice │ │ ├── server.go │ │ ├── invoker.go │ │ └── client.go │ └── userplat_validator.go └── useruser │ ├── k-consts.go │ ├── useruserservice │ ├── server.go │ ├── invoker.go │ └── client.go │ └── uu_validator.go ├── 启动文档.md ├── .gitignore ├── .gitpod.yml ├── .github ├── codecov.yml └── workflows │ ├── lint.yaml │ ├── test.yaml │ └── lint-review.yaml ├── docker-compose.yaml ├── Taskfile.yaml ├── LICENSE ├── .devcontainer └── devcontainer.json ├── IDLs ├── chat.thrift ├── useruser.thrift ├── userplat.thrift └── user.thrift ├── README.md └── go.mod /.prettierignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | .idea/ 3 | 4 | **/.go -------------------------------------------------------------------------------- /database.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/808-not-found/tik_duck/HEAD/database.png -------------------------------------------------------------------------------- /cmd/chat/kitex.yaml: -------------------------------------------------------------------------------- 1 | kitexinfo: 2 | ServiceName: "chat" 3 | ToolVersion: "v0.4.4" 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "prettier": "2.8.3" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /cmd/user/kitex.yaml: -------------------------------------------------------------------------------- 1 | kitexinfo: 2 | ServiceName: "UserService" 3 | ToolVersion: "v0.4.4" 4 | -------------------------------------------------------------------------------- /cmd/useruser/kitex.yaml: -------------------------------------------------------------------------------- 1 | kitexinfo: 2 | ServiceName: "useruser" 3 | ToolVersion: "v0.4.4" 4 | -------------------------------------------------------------------------------- /pkg/salt/setting.go: -------------------------------------------------------------------------------- 1 | package salt 2 | 3 | // Define salt size. 4 | const DefaultsaltSize = 32 5 | -------------------------------------------------------------------------------- /cmd/userplat/kitex.yaml: -------------------------------------------------------------------------------- 1 | kitexinfo: 2 | ServiceName: "UserPlatService" 3 | ToolVersion: "v0.4.4" 4 | -------------------------------------------------------------------------------- /cmd/web/rpc/init.go: -------------------------------------------------------------------------------- 1 | package rpc 2 | 3 | func InitRPC() { 4 | initUserRPC() 5 | initUserPlatRPC() 6 | initUserUserRPC() 7 | } 8 | -------------------------------------------------------------------------------- /cmd/chat/dal/init.go: -------------------------------------------------------------------------------- 1 | package dal 2 | 3 | import "github.com/808-not-found/tik_duck/cmd/chat/dal/db" 4 | 5 | func Init() { 6 | db.Init() 7 | } 8 | -------------------------------------------------------------------------------- /cmd/user/dal/init.go: -------------------------------------------------------------------------------- 1 | package dal 2 | 3 | import "github.com/808-not-found/tik_duck/cmd/user/dal/db" 4 | 5 | func Init() { 6 | db.Init() 7 | } 8 | -------------------------------------------------------------------------------- /cmd/useruser/dal/init.go: -------------------------------------------------------------------------------- 1 | package dal 2 | 3 | import "github.com/808-not-found/tik_duck/cmd/useruser/dal/db" 4 | 5 | func Init() { 6 | db.Init() 7 | } 8 | -------------------------------------------------------------------------------- /kitex_gen/chat/k-consts.go: -------------------------------------------------------------------------------- 1 | package chat 2 | 3 | // KitexUnusedProtection is used to prevent 'imported and not used' error. 4 | var KitexUnusedProtection = struct{}{} //nolint:all 5 | -------------------------------------------------------------------------------- /kitex_gen/user/k-consts.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | // KitexUnusedProtection is used to prevent 'imported and not used' error. 4 | var KitexUnusedProtection = struct{}{} // nolint:all 5 | -------------------------------------------------------------------------------- /cmd/userplat/dal/init.go: -------------------------------------------------------------------------------- 1 | package dal 2 | 3 | import "github.com/808-not-found/tik_duck/cmd/userplat/dal/db" 4 | 5 | // Init init dal. 6 | func Init() { 7 | db.Init() // mysql init 8 | } 9 | -------------------------------------------------------------------------------- /kitex_gen/userplat/k-consts.go: -------------------------------------------------------------------------------- 1 | package userplat 2 | 3 | // KitexUnusedProtection is used to prevent 'imported and not used' error. 4 | // nolint 5 | var KitexUnusedProtection = struct{}{} 6 | -------------------------------------------------------------------------------- /kitex_gen/useruser/k-consts.go: -------------------------------------------------------------------------------- 1 | package useruser 2 | 3 | // KitexUnusedProtection is used to prevent 'imported and not used' error. 4 | // nolint 5 | var KitexUnusedProtection = struct{}{} 6 | -------------------------------------------------------------------------------- /cmd/chat/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | 6 | chat "github.com/808-not-found/tik_duck/kitex_gen/chat/chatservice" 7 | ) 8 | 9 | func main() { 10 | svr := chat.NewServer(new(ChatServiceImpl)) 11 | 12 | err := svr.Run() 13 | 14 | if err != nil { 15 | log.Println(err.Error()) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /cmd/chat/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | RUN_NAME="chat" 3 | 4 | mkdir -p output/bin 5 | cp script/* output/ 6 | chmod +x output/bootstrap.sh 7 | 8 | if [ "$IS_SYSTEM_TEST_ENV" != "1" ]; then 9 | go build -o output/bin/${RUN_NAME} 10 | else 11 | go test -c -covermode=set -o output/bin/${RUN_NAME} -coverpkg=./... 12 | fi 13 | -------------------------------------------------------------------------------- /cmd/user/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | RUN_NAME="UserService" 3 | 4 | mkdir -p output/bin 5 | cp script/* output/ 6 | chmod +x output/bootstrap.sh 7 | 8 | if [ "$IS_SYSTEM_TEST_ENV" != "1" ]; then 9 | go build -o output/bin/${RUN_NAME} 10 | else 11 | go test -c -covermode=set -o output/bin/${RUN_NAME} -coverpkg=./... 12 | fi 13 | -------------------------------------------------------------------------------- /cmd/useruser/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | RUN_NAME="useruser" 3 | 4 | mkdir -p output/bin 5 | cp script/* output/ 6 | chmod +x output/bootstrap.sh 7 | 8 | if [ "$IS_SYSTEM_TEST_ENV" != "1" ]; then 9 | go build -o output/bin/${RUN_NAME} 10 | else 11 | go test -c -covermode=set -o output/bin/${RUN_NAME} -coverpkg=./... 12 | fi 13 | -------------------------------------------------------------------------------- /cmd/userplat/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | RUN_NAME="UserPlatService" 3 | 4 | mkdir -p output/bin 5 | cp script/* output/ 6 | chmod +x output/bootstrap.sh 7 | 8 | if [ "$IS_SYSTEM_TEST_ENV" != "1" ]; then 9 | go build -o output/bin/${RUN_NAME} 10 | else 11 | go test -c -covermode=set -o output/bin/${RUN_NAME} -coverpkg=./... 12 | fi 13 | -------------------------------------------------------------------------------- /启动文档.md: -------------------------------------------------------------------------------- 1 | # 运行测试文档 2 | 3 | ## 修改配置文件 4 | 5 | 在 pkg/consts/consts.go 中第 18 行,将 WebServerPublicIP 改为自己服务器的 ip 6 | 7 | ## docker 8 | 9 | 先讲 docker 容器运行起来 10 | 11 | ```bash 12 | docker compose up -d 13 | ``` 14 | 15 | 或者 16 | 17 | ```bash 18 | docker-compose up -d 19 | ``` 20 | 21 | ## web 22 | 23 | ```bash 24 | cd cmd/web 25 | go run . 26 | ``` 27 | 28 | ## user/userplat/useruser 同理 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .vscode 3 | .DS_Store 4 | 5 | .env 6 | .envrc 7 | 8 | source.sh 9 | dev-env/ 10 | *.exe 11 | .air.toml 12 | coverage.out 13 | .bin/ 14 | bin/ 15 | dist/ 16 | tmp/ 17 | public/ 18 | 19 | # bug of idea openapi plugin, see https://youtrack.jetbrains.com/issue/IDEA-285879 20 | /gen/ 21 | 22 | node_modules/ 23 | pnpm-lock.yaml 24 | yarn.lock 25 | .task/ 26 | 27 | config.yaml 28 | -------------------------------------------------------------------------------- /pkg/jwt/setting.go: -------------------------------------------------------------------------------- 1 | // 本文件放置jwt的配置信息 2 | package jwt 3 | 4 | import ( 5 | "time" 6 | 7 | jwt "github.com/dgrijalva/jwt-go" 8 | ) 9 | 10 | const ( 11 | JWTSecret = "password_tik_duck" 12 | 13 | JWTOverTime = time.Hour * 2 14 | ) 15 | 16 | // 目前jwt的claims中 只记录了用户名一个信息. 17 | type MyClaims struct { 18 | ID int64 19 | Username string `json:"username"` 20 | jwt.StandardClaims 21 | } 22 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | tasks: 2 | - before: go mod tidy && go install github.com/go-task/task/v3/cmd/task@latest && go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.50.1 && go install github.com/vektra/mockery/v2@latest && go install github.com/cloudwego/kitex/tool/cmd/kitex@latest && go install github.com/cloudwego/thriftgo@latest 3 | - init: npm install 4 | 5 | vscode: 6 | extensions: 7 | - golang.go 8 | - usernamehw.errorlens 9 | -------------------------------------------------------------------------------- /.github/codecov.yml: -------------------------------------------------------------------------------- 1 | ignore: 2 | - "**/mock_*.go" 3 | - "**/*_test.go" 4 | - "**/*.gen.go" 5 | - "kitex_gen/" 6 | - "cmd/web/" # web only used to connect to rpc 7 | comment: # this is a top-level key 8 | layout: "reach, diff, flags, files" 9 | behavior: default 10 | require_changes: false # if true: only post the comment if coverage changes 11 | require_base: no # [yes :: must have a base report to post] 12 | require_head: yes # [yes :: must have a head report to post] 13 | -------------------------------------------------------------------------------- /cmd/chat/script/bootstrap.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | CURDIR=$(cd $(dirname $0); pwd) 3 | 4 | if [ "X$1" != "X" ]; then 5 | RUNTIME_ROOT=$1 6 | else 7 | RUNTIME_ROOT=${CURDIR} 8 | fi 9 | 10 | export KITEX_RUNTIME_ROOT=$RUNTIME_ROOT 11 | export KITEX_LOG_DIR="$RUNTIME_ROOT/log" 12 | 13 | if [ ! -d "$KITEX_LOG_DIR/app" ]; then 14 | mkdir -p "$KITEX_LOG_DIR/app" 15 | fi 16 | 17 | if [ ! -d "$KITEX_LOG_DIR/rpc" ]; then 18 | mkdir -p "$KITEX_LOG_DIR/rpc" 19 | fi 20 | 21 | exec "$CURDIR/bin/chat" 22 | -------------------------------------------------------------------------------- /cmd/user/script/bootstrap.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | CURDIR=$(cd $(dirname $0); pwd) 3 | 4 | if [ "X$1" != "X" ]; then 5 | RUNTIME_ROOT=$1 6 | else 7 | RUNTIME_ROOT=${CURDIR} 8 | fi 9 | 10 | export KITEX_RUNTIME_ROOT=$RUNTIME_ROOT 11 | export KITEX_LOG_DIR="$RUNTIME_ROOT/log" 12 | 13 | if [ ! -d "$KITEX_LOG_DIR/app" ]; then 14 | mkdir -p "$KITEX_LOG_DIR/app" 15 | fi 16 | 17 | if [ ! -d "$KITEX_LOG_DIR/rpc" ]; then 18 | mkdir -p "$KITEX_LOG_DIR/rpc" 19 | fi 20 | 21 | exec "$CURDIR/bin/UserService" 22 | -------------------------------------------------------------------------------- /cmd/useruser/script/bootstrap.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | CURDIR=$(cd $(dirname $0); pwd) 3 | 4 | if [ "X$1" != "X" ]; then 5 | RUNTIME_ROOT=$1 6 | else 7 | RUNTIME_ROOT=${CURDIR} 8 | fi 9 | 10 | export KITEX_RUNTIME_ROOT=$RUNTIME_ROOT 11 | export KITEX_LOG_DIR="$RUNTIME_ROOT/log" 12 | 13 | if [ ! -d "$KITEX_LOG_DIR/app" ]; then 14 | mkdir -p "$KITEX_LOG_DIR/app" 15 | fi 16 | 17 | if [ ! -d "$KITEX_LOG_DIR/rpc" ]; then 18 | mkdir -p "$KITEX_LOG_DIR/rpc" 19 | fi 20 | 21 | exec "$CURDIR/bin/useruser" 22 | -------------------------------------------------------------------------------- /cmd/userplat/script/bootstrap.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | CURDIR=$(cd $(dirname $0); pwd) 3 | 4 | if [ "X$1" != "X" ]; then 5 | RUNTIME_ROOT=$1 6 | else 7 | RUNTIME_ROOT=${CURDIR} 8 | fi 9 | 10 | export KITEX_RUNTIME_ROOT=$RUNTIME_ROOT 11 | export KITEX_LOG_DIR="$RUNTIME_ROOT/log" 12 | 13 | if [ ! -d "$KITEX_LOG_DIR/app" ]; then 14 | mkdir -p "$KITEX_LOG_DIR/app" 15 | fi 16 | 17 | if [ ! -d "$KITEX_LOG_DIR/rpc" ]; then 18 | mkdir -p "$KITEX_LOG_DIR/rpc" 19 | fi 20 | 21 | exec "$CURDIR/bin/UserPlatService" 22 | -------------------------------------------------------------------------------- /kitex_gen/chat/chatservice/server.go: -------------------------------------------------------------------------------- 1 | // Code generated by Kitex v0.4.4. DO NOT EDIT. 2 | package chatservice 3 | 4 | import ( 5 | chat "github.com/808-not-found/tik_duck/kitex_gen/chat" 6 | server "github.com/cloudwego/kitex/server" 7 | ) 8 | 9 | // NewServer creates a server.Server with the given handler and options. 10 | func NewServer(handler chat.ChatService, opts ...server.Option) server.Server { 11 | var options []server.Option 12 | 13 | options = append(options, opts...) 14 | 15 | svr := server.NewServer(options...) 16 | if err := svr.RegisterService(serviceInfo(), handler); err != nil { 17 | panic(err) 18 | } 19 | return svr 20 | } 21 | -------------------------------------------------------------------------------- /kitex_gen/user/userservice/server.go: -------------------------------------------------------------------------------- 1 | // Code generated by Kitex v0.4.4. DO NOT EDIT. 2 | package userservice 3 | 4 | import ( 5 | user "github.com/808-not-found/tik_duck/kitex_gen/user" 6 | server "github.com/cloudwego/kitex/server" 7 | ) 8 | 9 | // NewServer creates a server.Server with the given handler and options. 10 | func NewServer(handler user.UserService, opts ...server.Option) server.Server { 11 | var options []server.Option 12 | 13 | options = append(options, opts...) 14 | 15 | svr := server.NewServer(options...) 16 | if err := svr.RegisterService(serviceInfo(), handler); err != nil { 17 | panic(err) 18 | } 19 | return svr 20 | } 21 | -------------------------------------------------------------------------------- /kitex_gen/userplat/userplatservice/server.go: -------------------------------------------------------------------------------- 1 | // Code generated by Kitex v0.4.4. DO NOT EDIT. 2 | package userplatservice 3 | 4 | import ( 5 | userplat "github.com/808-not-found/tik_duck/kitex_gen/userplat" 6 | server "github.com/cloudwego/kitex/server" 7 | ) 8 | 9 | // NewServer creates a server.Server with the given handler and options. 10 | func NewServer(handler userplat.UserPlatService, opts ...server.Option) server.Server { 11 | var options []server.Option 12 | 13 | options = append(options, opts...) 14 | 15 | svr := server.NewServer(options...) 16 | if err := svr.RegisterService(serviceInfo(), handler); err != nil { 17 | panic(err) 18 | } 19 | return svr 20 | } 21 | -------------------------------------------------------------------------------- /kitex_gen/useruser/useruserservice/server.go: -------------------------------------------------------------------------------- 1 | // Code generated by Kitex v0.4.4. DO NOT EDIT. 2 | package useruserservice 3 | 4 | import ( 5 | useruser "github.com/808-not-found/tik_duck/kitex_gen/useruser" 6 | server "github.com/cloudwego/kitex/server" 7 | ) 8 | 9 | // NewServer creates a server.Server with the given handler and options. 10 | func NewServer(handler useruser.UserUserService, opts ...server.Option) server.Server { 11 | var options []server.Option 12 | 13 | options = append(options, opts...) 14 | 15 | svr := server.NewServer(options...) 16 | if err := svr.RegisterService(serviceInfo(), handler); err != nil { 17 | panic(err) 18 | } 19 | return svr 20 | } 21 | -------------------------------------------------------------------------------- /cmd/web/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "os" 6 | 7 | "github.com/808-not-found/tik_duck/cmd/web/rpc" 8 | "github.com/808-not-found/tik_duck/pkg/consts" 9 | "github.com/cloudwego/hertz/pkg/app/server" 10 | "github.com/cloudwego/hertz/pkg/network/standard" 11 | ) 12 | 13 | func main() { 14 | rpc.InitRPC() 15 | err := os.Mkdir("public", os.ModePerm) 16 | if err != nil { 17 | log.Println(err) 18 | } 19 | h := server.Default( 20 | server.WithStreamBody(true), server.WithTransport(standard.NewTransporter), 21 | server.WithHostPorts("0.0.0.0:"+consts.WebServerPort), 22 | server.WithMaxRequestBodySize(consts.HTTPMaxBodySize)) 23 | 24 | InitRouter(h) 25 | h.Spin() 26 | } 27 | -------------------------------------------------------------------------------- /kitex_gen/userplat/userplat_validator.go: -------------------------------------------------------------------------------- 1 | package userplat 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "reflect" 7 | "regexp" 8 | "strings" 9 | "time" 10 | ) 11 | 12 | // unused protection. 13 | var ( 14 | _ = fmt.Formatter(nil) 15 | _ = (*bytes.Buffer)(nil) 16 | _ = (*strings.Builder)(nil) 17 | _ = reflect.Type(nil) 18 | _ = (*regexp.Regexp)(nil) 19 | _ = time.Nanosecond 20 | ) 21 | 22 | func (p *FavoriteActionRequest) IsValid() error { 23 | return nil 24 | } 25 | 26 | func (p *FavoriteListRequest) IsValid() error { 27 | return nil 28 | } 29 | 30 | func (p *CommentActionRequest) IsValid() error { 31 | return nil 32 | } 33 | 34 | func (p *CommentListRequest) IsValid() error { 35 | return nil 36 | } 37 | -------------------------------------------------------------------------------- /kitex_gen/chat/chatservice/invoker.go: -------------------------------------------------------------------------------- 1 | // Code generated by Kitex v0.4.4. DO NOT EDIT. 2 | 3 | package chatservice 4 | 5 | import ( 6 | chat "github.com/808-not-found/tik_duck/kitex_gen/chat" 7 | server "github.com/cloudwego/kitex/server" 8 | ) 9 | 10 | // NewInvoker creates a server.Invoker with the given handler and options. 11 | func NewInvoker(handler chat.ChatService, opts ...server.Option) server.Invoker { 12 | var options []server.Option 13 | 14 | options = append(options, opts...) 15 | 16 | s := server.NewInvoker(options...) 17 | if err := s.RegisterService(serviceInfo(), handler); err != nil { 18 | panic(err) 19 | } 20 | if err := s.Init(); err != nil { 21 | panic(err) 22 | } 23 | return s 24 | } 25 | -------------------------------------------------------------------------------- /kitex_gen/user/userservice/invoker.go: -------------------------------------------------------------------------------- 1 | // Code generated by Kitex v0.4.4. DO NOT EDIT. 2 | 3 | package userservice 4 | 5 | import ( 6 | user "github.com/808-not-found/tik_duck/kitex_gen/user" 7 | server "github.com/cloudwego/kitex/server" 8 | ) 9 | 10 | // NewInvoker creates a server.Invoker with the given handler and options. 11 | func NewInvoker(handler user.UserService, opts ...server.Option) server.Invoker { 12 | var options []server.Option 13 | 14 | options = append(options, opts...) 15 | 16 | s := server.NewInvoker(options...) 17 | if err := s.RegisterService(serviceInfo(), handler); err != nil { 18 | panic(err) 19 | } 20 | if err := s.Init(); err != nil { 21 | panic(err) 22 | } 23 | return s 24 | } 25 | -------------------------------------------------------------------------------- /pkg/middleware/server.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/cloudwego/kitex/pkg/endpoint" 7 | "github.com/cloudwego/kitex/pkg/klog" 8 | "github.com/cloudwego/kitex/pkg/rpcinfo" 9 | ) 10 | 11 | var _ endpoint.Middleware = ServerMiddleware 12 | 13 | // ServerMiddleware server middleware print client address. 14 | func ServerMiddleware(next endpoint.Endpoint) endpoint.Endpoint { 15 | return func(ctx context.Context, req, resp any) (err error) { 16 | ri := rpcinfo.GetRPCInfo(ctx) 17 | // get client information 18 | klog.Infof("client address: %v\n", ri.From().Address()) 19 | if err = next(ctx, req, resp); err != nil { 20 | return err 21 | } 22 | return nil 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /kitex_gen/useruser/uu_validator.go: -------------------------------------------------------------------------------- 1 | package useruser 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "reflect" 7 | "regexp" 8 | "strings" 9 | "time" 10 | ) 11 | 12 | // unused protection. 13 | var ( 14 | _ = fmt.Formatter(nil) 15 | _ = (*bytes.Buffer)(nil) 16 | _ = (*strings.Builder)(nil) 17 | _ = reflect.Type(nil) 18 | _ = (*regexp.Regexp)(nil) 19 | _ = time.Nanosecond 20 | ) 21 | 22 | func (p *RelationActionRequest) IsValid() error { 23 | return nil 24 | } 25 | 26 | func (p *RelationFollowListRequest) IsValid() error { 27 | return nil 28 | } 29 | 30 | func (p *RelationFollowerListRequest) IsValid() error { 31 | return nil 32 | } 33 | 34 | func (p *RelationFriendListRequest) IsValid() error { 35 | return nil 36 | } 37 | -------------------------------------------------------------------------------- /kitex_gen/userplat/userplatservice/invoker.go: -------------------------------------------------------------------------------- 1 | // Code generated by Kitex v0.4.4. DO NOT EDIT. 2 | 3 | package userplatservice 4 | 5 | import ( 6 | userplat "github.com/808-not-found/tik_duck/kitex_gen/userplat" 7 | server "github.com/cloudwego/kitex/server" 8 | ) 9 | 10 | // NewInvoker creates a server.Invoker with the given handler and options. 11 | func NewInvoker(handler userplat.UserPlatService, opts ...server.Option) server.Invoker { 12 | var options []server.Option 13 | 14 | options = append(options, opts...) 15 | 16 | s := server.NewInvoker(options...) 17 | if err := s.RegisterService(serviceInfo(), handler); err != nil { 18 | panic(err) 19 | } 20 | if err := s.Init(); err != nil { 21 | panic(err) 22 | } 23 | return s 24 | } 25 | -------------------------------------------------------------------------------- /kitex_gen/useruser/useruserservice/invoker.go: -------------------------------------------------------------------------------- 1 | // Code generated by Kitex v0.4.4. DO NOT EDIT. 2 | 3 | package useruserservice 4 | 5 | import ( 6 | useruser "github.com/808-not-found/tik_duck/kitex_gen/useruser" 7 | server "github.com/cloudwego/kitex/server" 8 | ) 9 | 10 | // NewInvoker creates a server.Invoker with the given handler and options. 11 | func NewInvoker(handler useruser.UserUserService, opts ...server.Option) server.Invoker { 12 | var options []server.Option 13 | 14 | options = append(options, opts...) 15 | 16 | s := server.NewInvoker(options...) 17 | if err := s.RegisterService(serviceInfo(), handler); err != nil { 18 | panic(err) 19 | } 20 | if err := s.Init(); err != nil { 21 | panic(err) 22 | } 23 | return s 24 | } 25 | -------------------------------------------------------------------------------- /cmd/web/controller/demo_data.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | // nolint:all 4 | var DemoVideos = []Video{ 5 | { 6 | ID: 1, 7 | Author: DemoUser, 8 | PlayURL: "https://www.w3schools.com/html/movie.mp4", 9 | CoverURL: "https://cdn.pixabay.com/photo/2016/03/27/18/10/bear-1283347_1280.jpg", 10 | FavoriteCount: 0, 11 | CommentCount: 0, 12 | IsFavorite: false, 13 | }, 14 | } 15 | 16 | // nolint:all 17 | var DemoComments = []Comment{ 18 | { 19 | ID: 1, 20 | User: DemoUser, 21 | Content: "Test Comment", 22 | CreateDate: "05-01", 23 | }, 24 | } 25 | 26 | // nolint:all 27 | var DemoUser = User{ 28 | ID: 1, 29 | Name: "TestUser", 30 | FollowCount: 0, 31 | FollowerCount: 0, 32 | IsFollow: false, 33 | } 34 | -------------------------------------------------------------------------------- /cmd/chat/pack/chat.go: -------------------------------------------------------------------------------- 1 | package pack 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/808-not-found/tik_duck/cmd/chat/dal/db" 7 | "github.com/808-not-found/tik_duck/kitex_gen/chat" 8 | ) 9 | 10 | func Msg(ctx context.Context, m *db.Message) (res *chat.Message, err error) { 11 | t := m.CreatedAt.String() 12 | return &chat.Message{ 13 | Id: m.ID, 14 | ToUserId: m.ToUserID, 15 | FromUserId: m.FromUserID, 16 | Content: m.Content, 17 | CreateTime: &t, 18 | }, nil 19 | } 20 | 21 | func Msgs(ctx context.Context, ms []*db.Message) (res []*chat.Message, err error) { 22 | msgs := make([]*chat.Message, 0) 23 | for _, m := range ms { 24 | n, err := Msg(ctx, m) 25 | if err != nil { 26 | return nil, err 27 | } 28 | msgs = append(msgs, n) 29 | } 30 | return msgs, nil 31 | } 32 | -------------------------------------------------------------------------------- /pkg/consts/consts.go: -------------------------------------------------------------------------------- 1 | // Some consts for database 2 | 3 | package consts 4 | 5 | const ( 6 | CommentTableName = "comment" 7 | FollowTableName = "follow" 8 | LikeTableName = "like" 9 | MessageTableName = "message" 10 | UserTableName = "user" 11 | VideoTableName = "video" 12 | EtcdAddress = "127.0.0.1:2379" 13 | UserServiceName = "usersvr" 14 | UserUserServiceName = "useruser" 15 | UserPlatServiceName = "userplat" 16 | ChatService = "chat" 17 | 18 | WebServerPort = "8080" 19 | WebServerPublicIP = "192.168.0.106" 20 | StaticPort = "8081" 21 | 22 | MySQLDefaultDSN = "tik_duck:duck@tcp(localhost:9910)/tik_duck?charset=utf8mb4&parseTime=True" 23 | TCP = "tcp" 24 | Success = "success" 25 | HTTPMaxBodySize = 1024 * 1024 * 1024 // 1GB 26 | ) 27 | -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | nginx-static: 5 | image: flashspys/nginx-static 6 | container_name: nginx-static 7 | ports: 8 | - 8081:80 9 | volumes: 10 | - ./cmd/web/public:/static/public 11 | mysql: 12 | image: "mysql:latest" 13 | volumes: 14 | - ./pkg/initsql:/docker-entrypoint-initdb.d 15 | ports: 16 | - 9910:3306 17 | environment: 18 | - MYSQL_DATABASE=tik_duck 19 | - MYSQL_USER=tik_duck 20 | - MYSQL_PASSWORD=duck 21 | - MYSQL_RANDOM_ROOT_PASSWORD="yes" 22 | - TZ=Asia/Shanghai 23 | Etcd: 24 | image: "quay.io/coreos/etcd:v3.5.5" 25 | environment: 26 | - ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379 27 | - ETCD_ADVERTISE_CLIENT_URLS=http://0.0.0.0:2379 28 | - ETCDCTL_API=3 29 | ports: 30 | - 2379:2379 31 | -------------------------------------------------------------------------------- /pkg/middleware/client.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/cloudwego/kitex/pkg/endpoint" 7 | "github.com/cloudwego/kitex/pkg/klog" 8 | "github.com/cloudwego/kitex/pkg/rpcinfo" 9 | ) 10 | 11 | var _ endpoint.Middleware = ClientMiddleware 12 | 13 | // ClientMiddleware client middleware print server address 、rpc timeout and connection timeout. 14 | func ClientMiddleware(next endpoint.Endpoint) endpoint.Endpoint { 15 | return func(ctx context.Context, req, resp any) (err error) { 16 | ri := rpcinfo.GetRPCInfo(ctx) 17 | // get server information 18 | klog.Infof("server address: %v, rpc timeout: %v, readwrite timeout: %v\n", 19 | ri.To().Address(), ri.Config().RPCTimeout(), ri.Config().ConnectTimeout()) 20 | if err = next(ctx, req, resp); err != nil { 21 | return err 22 | } 23 | return nil 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /cmd/chat/dal/db/init.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/808-not-found/tik_duck/pkg/consts" 7 | "gorm.io/driver/mysql" 8 | "gorm.io/gorm" 9 | "gorm.io/gorm/logger" 10 | "gorm.io/plugin/opentelemetry/logging/logrus" 11 | "gorm.io/plugin/opentelemetry/tracing" 12 | ) 13 | 14 | var DB *gorm.DB 15 | 16 | func Init() { 17 | var err error 18 | gormlogrus := logger.New( 19 | logrus.NewWriter(), 20 | logger.Config{ 21 | SlowThreshold: time.Millisecond, 22 | Colorful: false, 23 | LogLevel: logger.Info, 24 | }, 25 | ) 26 | DB, err = gorm.Open(mysql.Open(consts.MySQLDefaultDSN), 27 | &gorm.Config{ 28 | PrepareStmt: true, 29 | Logger: gormlogrus, 30 | }, 31 | ) 32 | if err != nil { 33 | panic(err) 34 | } 35 | if err := DB.Use(tracing.NewPlugin()); err != nil { 36 | panic(err) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /cmd/user/dal/db/init.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/808-not-found/tik_duck/pkg/consts" 7 | "gorm.io/driver/mysql" 8 | "gorm.io/gorm" 9 | "gorm.io/gorm/logger" 10 | "gorm.io/plugin/opentelemetry/logging/logrus" 11 | "gorm.io/plugin/opentelemetry/tracing" 12 | ) 13 | 14 | var DB *gorm.DB 15 | 16 | func Init() { 17 | var err error 18 | gormlogrus := logger.New( 19 | logrus.NewWriter(), 20 | logger.Config{ 21 | SlowThreshold: time.Millisecond, 22 | Colorful: false, 23 | LogLevel: logger.Info, 24 | }, 25 | ) 26 | DB, err = gorm.Open(mysql.Open(consts.MySQLDefaultDSN), 27 | &gorm.Config{ 28 | PrepareStmt: true, 29 | Logger: gormlogrus, 30 | }, 31 | ) 32 | if err != nil { 33 | panic(err) 34 | } 35 | if err := DB.Use(tracing.NewPlugin()); err != nil { 36 | panic(err) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /cmd/user/userService/user_publish_action.go: -------------------------------------------------------------------------------- 1 | package userservice 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/808-not-found/tik_duck/cmd/user/dal/db" 7 | "github.com/808-not-found/tik_duck/kitex_gen/user" 8 | "github.com/808-not-found/tik_duck/pkg/jwt" 9 | ) 10 | 11 | func UserPublishActionService( 12 | ctx context.Context, 13 | req *user.PublishActionRequest, 14 | ) (*user.PublishActionResponse, error) { 15 | resp := user.PublishActionResponse{ 16 | StatusCode: 0, 17 | } 18 | // 用户鉴权 19 | claims, err := jwt.ParseToken(req.Token) 20 | if err != nil { 21 | resp.StatusCode = 1024 22 | return &resp, err 23 | } 24 | myID := claims.ID 25 | // 写入数据 26 | err = db.UserPublishAction(ctx, myID, req.FilePath, req.CoverPath, req.Title) 27 | if err != nil { 28 | resp.StatusCode = 1025 29 | return &resp, err 30 | } 31 | // 成功返回 32 | return &resp, nil 33 | } 34 | -------------------------------------------------------------------------------- /cmd/useruser/dal/db/init.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/808-not-found/tik_duck/pkg/consts" 7 | "gorm.io/driver/mysql" 8 | "gorm.io/gorm" 9 | "gorm.io/gorm/logger" 10 | "gorm.io/plugin/opentelemetry/logging/logrus" 11 | "gorm.io/plugin/opentelemetry/tracing" 12 | ) 13 | 14 | var DB *gorm.DB // nolint:all 15 | 16 | func Init() { 17 | var err error 18 | gormlogrus := logger.New( 19 | logrus.NewWriter(), 20 | logger.Config{ 21 | SlowThreshold: time.Millisecond, 22 | Colorful: false, 23 | LogLevel: logger.Info, 24 | }, 25 | ) 26 | DB, err = gorm.Open(mysql.Open(consts.MySQLDefaultDSN), 27 | &gorm.Config{ 28 | PrepareStmt: true, 29 | Logger: gormlogrus, 30 | }, 31 | ) 32 | if err != nil { 33 | panic(err) 34 | } 35 | if err := DB.Use(tracing.NewPlugin()); err != nil { 36 | panic(err) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /cmd/userplat/dal/db/init.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/808-not-found/tik_duck/pkg/consts" 7 | "gorm.io/driver/mysql" 8 | "gorm.io/gorm" 9 | "gorm.io/gorm/logger" 10 | "gorm.io/plugin/opentelemetry/logging/logrus" 11 | "gorm.io/plugin/opentelemetry/tracing" 12 | ) 13 | 14 | var DB *gorm.DB 15 | 16 | // Init init DB. 17 | func Init() { 18 | var err error 19 | gormlogrus := logger.New( 20 | logrus.NewWriter(), 21 | logger.Config{ 22 | SlowThreshold: time.Millisecond, 23 | Colorful: false, 24 | LogLevel: logger.Info, 25 | }, 26 | ) 27 | DB, err = gorm.Open(mysql.Open(consts.MySQLDefaultDSN), 28 | &gorm.Config{ 29 | PrepareStmt: true, 30 | Logger: gormlogrus, 31 | }, 32 | ) 33 | if err != nil { 34 | panic(err) 35 | } 36 | 37 | if err := DB.Use(tracing.NewPlugin()); err != nil { 38 | panic(err) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /pkg/cover/cover.go: -------------------------------------------------------------------------------- 1 | package cover 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "log" 7 | "os" 8 | 9 | "github.com/disintegration/imaging" 10 | ffmpeg "github.com/u2takey/ffmpeg-go" 11 | ) 12 | 13 | func GetSnapshot(videoPath, snapshotPath string, frameNum int) (err error) { 14 | buf := bytes.NewBuffer(nil) 15 | err = ffmpeg.Input(videoPath). 16 | Filter("select", ffmpeg.Args{fmt.Sprintf("gte(n,%d)", frameNum)}). 17 | Output("pipe:", ffmpeg.KwArgs{"vframes": 1, "format": "image2", "vcodec": "mjpeg"}). 18 | WithOutput(buf, os.Stdout). 19 | Run() 20 | if err != nil { 21 | log.Fatal("生成缩略图失败:", err) 22 | return err 23 | } 24 | 25 | img, err := imaging.Decode(buf) 26 | if err != nil { 27 | log.Fatal("生成缩略图失败:", err) 28 | return err 29 | } 30 | 31 | err = imaging.Save(img, snapshotPath) 32 | if err != nil { 33 | log.Fatal("生成缩略图失败:", err) 34 | return err 35 | } 36 | 37 | return 38 | } 39 | -------------------------------------------------------------------------------- /cmd/chat/chatservice/post_msg.go: -------------------------------------------------------------------------------- 1 | package chatservice 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/808-not-found/tik_duck/cmd/chat/dal/db" 7 | "github.com/808-not-found/tik_duck/kitex_gen/chat" 8 | "github.com/808-not-found/tik_duck/pkg/jwt" 9 | ) 10 | 11 | func PostMsgService( 12 | ctx context.Context, 13 | req *chat.RelationActionRequest, 14 | ) (resp *chat.RelationActionResponse, err error) { 15 | resp = &chat.RelationActionResponse{ 16 | StatusCode: 0, 17 | } 18 | var myID int64 19 | if req.Token == "" { 20 | resp.StatusCode = 4005 21 | return resp, err 22 | } 23 | claims, err := jwt.ParseToken(req.Token) 24 | if err != nil { 25 | resp.StatusCode = 4006 26 | return resp, err 27 | } 28 | myID = claims.ID 29 | 30 | err = db.PostMsg(ctx, myID, req.ToUserId, &req.Content) 31 | if err != nil { 32 | resp.StatusCode = 4007 33 | return resp, err 34 | } 35 | 36 | return resp, nil 37 | } 38 | -------------------------------------------------------------------------------- /pkg/middleware/common.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/cloudwego/kitex/pkg/endpoint" 7 | "github.com/cloudwego/kitex/pkg/klog" 8 | "github.com/cloudwego/kitex/pkg/rpcinfo" 9 | ) 10 | 11 | var _ endpoint.Middleware = CommonMiddleware 12 | 13 | // CommonMiddleware common middleware print some rpc info、real request and real response. 14 | func CommonMiddleware(next endpoint.Endpoint) endpoint.Endpoint { 15 | return func(ctx context.Context, req, resp any) (err error) { 16 | ri := rpcinfo.GetRPCInfo(ctx) 17 | // get real request 18 | klog.Infof("real request: %+v\n", req) 19 | // get remote service information 20 | klog.Infof("remote service name: %s, remote method: %s\n", ri.To().ServiceName(), ri.To().Method()) 21 | if err = next(ctx, req, resp); err != nil { 22 | return err 23 | } 24 | // get real response 25 | klog.Infof("real response: %+v\n", resp) 26 | return nil 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /cmd/user/benchmark/user_register_test.go: -------------------------------------------------------------------------------- 1 | package userservice_test 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | userservice "github.com/808-not-found/tik_duck/cmd/user/userService" 8 | user "github.com/808-not-found/tik_duck/kitex_gen/user" 9 | ) 10 | 11 | func BenchmarkUserRegisterService(b *testing.B) { 12 | b.ResetTimer() 13 | for i := 0; i < b.N; i++ { 14 | //设置传入参数 15 | req := user.UserRegisterRequest{ 16 | Username: "蒂萨久", 17 | Password: "114514", 18 | } 19 | _, _, _, _, _ = userservice.UserRegisterService(context.Background(), &req) 20 | } 21 | } 22 | func BenchmarkUserRegisterServiceParallel(b *testing.B) { 23 | b.ResetTimer() 24 | b.RunParallel(func(pb *testing.PB) { 25 | for pb.Next() { 26 | //设置传入参数 27 | req := user.UserRegisterRequest{ 28 | Username: "蒂萨久", 29 | Password: "114514", 30 | } 31 | _, _, _, _, _ = userservice.UserRegisterService(context.Background(), &req) 32 | } 33 | }) 34 | } 35 | -------------------------------------------------------------------------------- /cmd/web/controller/feed.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "net/http" 7 | "strconv" 8 | 9 | "github.com/808-not-found/tik_duck/cmd/web/rpc" 10 | "github.com/808-not-found/tik_duck/kitex_gen/user" 11 | "github.com/cloudwego/hertz/pkg/app" 12 | ) 13 | 14 | type FeedResponse struct { 15 | Response 16 | VideoList []Video `json:"video_list,omitempty"` 17 | NextTime int64 `json:"next_time,omitempty"` 18 | } 19 | 20 | func Feed(ctx context.Context, c *app.RequestContext) { 21 | var feedReq user.FeedRequest 22 | token := c.Query("token") 23 | latestTime, _ := strconv.ParseInt(c.Query("latest_time"), 10, 64) 24 | if token != "" { 25 | feedReq.Token = &token 26 | } else { 27 | feedReq.Token = nil 28 | } 29 | feedReq.LatestTime = &latestTime 30 | resp, err := rpc.GetFeed(context.Background(), &feedReq) 31 | // test video 32 | if err != nil { 33 | log.Println(err) 34 | return 35 | } 36 | c.JSON(http.StatusOK, resp) 37 | } 38 | -------------------------------------------------------------------------------- /Taskfile.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | dotenv: [".env", ".envrc"] 4 | 5 | tasks: 6 | default: 7 | silent: true 8 | cmds: 9 | - task --list 10 | 11 | run: 12 | desc: Run all service in local env 13 | cmds: 14 | - cd cmd/web && (go run ../user & go run ../useruser & go run ../userplat & go run .) 15 | 16 | lint: 17 | silent: true 18 | desc: Run 'golangci-lint'. 19 | cmds: 20 | - golangci-lint run --fix 21 | 22 | prettier: 23 | silent: true 24 | desc: Format config files. 25 | cmds: 26 | - npx prettier --write --list-different ./ 27 | 28 | test: 29 | silent: true 30 | desc: Run tests without coverage report. 31 | cmds: 32 | - go test -gcflags="all=-l -N" -v ./... 33 | 34 | coverage: 35 | desc: Run tests with coverage report, used in CI. 36 | cmds: 37 | - go test -gcflags="all=-l -N" -timeout 10s -tags test -race -coverpkg=./... -covermode=atomic -coverprofile=coverage.out ./... 38 | -------------------------------------------------------------------------------- /.github/workflows/lint.yaml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | on: 4 | push: 5 | branches-ignore: 6 | - renovate/** 7 | paths: 8 | - "**.go" 9 | - "**.go.json" 10 | - "go.mod" 11 | - "go.sum" 12 | - ".golangci.yaml" 13 | - ".github/workflows/lint.yaml" 14 | pull_request: 15 | branches: 16 | - master 17 | paths: 18 | - "**.go" 19 | - "**.go.json" 20 | - "go.mod" 21 | - "go.sum" 22 | - ".golangci.yaml" 23 | - ".github/workflows/lint.yaml" 24 | 25 | jobs: 26 | lint: 27 | runs-on: ubuntu-22.04 28 | steps: 29 | - uses: actions/checkout@v3 30 | 31 | - name: Install Go 32 | uses: actions/setup-go@v3 33 | with: 34 | go-version-file: "go.mod" 35 | 36 | - run: go mod tidy 37 | 38 | - name: Run linters 39 | uses: golangci/golangci-lint-action@v3 40 | with: 41 | version: v1.50.0 42 | skip-pkg-cache: true 43 | skip-build-cache: true 44 | -------------------------------------------------------------------------------- /cmd/chat/handler.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | 6 | chatservice "github.com/808-not-found/tik_duck/cmd/chat/chatservice" 7 | chat "github.com/808-not-found/tik_duck/kitex_gen/chat" 8 | ) 9 | 10 | // ChatServiceImpl implements the last service interface defined in the IDL. 11 | type ChatServiceImpl struct{} 12 | 13 | // GetMsg implements the ChatServiceImpl interface. 14 | func (s *ChatServiceImpl) GetMsg( 15 | ctx context.Context, 16 | req *chat.MessageChatRequest, 17 | ) (resp *chat.MessageChatResponse, err error) { 18 | // TODO: Your code here... 19 | resp, err = chatservice.GetMsgService(ctx, req) 20 | if err != nil { 21 | return resp, err 22 | } 23 | return 24 | } 25 | 26 | // PostMsg implements the ChatServiceImpl interface. 27 | func (s *ChatServiceImpl) PostMsg( 28 | ctx context.Context, 29 | req *chat.RelationActionRequest, 30 | ) (resp *chat.RelationActionResponse, err error) { 31 | // TODO: Your code here... 32 | resp, err = chatservice.PostMsgService(ctx, req) 33 | if err != nil { 34 | return resp, err 35 | } 36 | return 37 | } 38 | -------------------------------------------------------------------------------- /cmd/user/userService/user_publish_list.go: -------------------------------------------------------------------------------- 1 | package userservice 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/808-not-found/tik_duck/cmd/user/dal/db" 7 | "github.com/808-not-found/tik_duck/cmd/user/pack" 8 | "github.com/808-not-found/tik_duck/kitex_gen/user" 9 | "github.com/808-not-found/tik_duck/pkg/jwt" 10 | ) 11 | 12 | func UserPublishListService(ctx context.Context, req *user.PublishListRequest) (*user.PublishListResponse, error) { 13 | // 创建返回参数 14 | resp := user.PublishListResponse{ 15 | StatusCode: 0, 16 | } 17 | 18 | // 用户鉴权 19 | claims, err := jwt.ParseToken(req.Token) 20 | if err != nil { 21 | resp.StatusCode = 1026 22 | return &resp, nil 23 | } 24 | myID := claims.ID 25 | // 获取数据 26 | dbVideos, err := db.UserPublishList(ctx, int32(req.UserId)) 27 | if err != nil { 28 | resp.StatusCode = 1027 29 | return &resp, nil 30 | } 31 | // 封装数据 32 | rpcVideos, err := pack.Videos(ctx, dbVideos, myID) 33 | if err != nil { 34 | resp.StatusCode = 1028 35 | return &resp, nil 36 | } 37 | resp.VideoList = rpcVideos 38 | 39 | // 成功返回 40 | return &resp, nil 41 | } 42 | -------------------------------------------------------------------------------- /cmd/userplat/pack/comment.go: -------------------------------------------------------------------------------- 1 | package pack 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/808-not-found/tik_duck/cmd/userplat/dal/db" 7 | "github.com/808-not-found/tik_duck/kitex_gen/userplat" 8 | ) 9 | 10 | func Comment(ctx context.Context, m *db.Comment, myID int64) (*userplat.Comment, error) { 11 | var res *userplat.Comment 12 | if m == nil { 13 | return res, nil 14 | } 15 | dbUser, err := db.GetUser(ctx, m.UserID) 16 | if err != nil { 17 | return nil, err 18 | } 19 | rpcUser, err := DBUserToRPCUser(&dbUser, myID) 20 | if err != nil { 21 | return nil, err 22 | } 23 | return &userplat.Comment{ 24 | Id: m.ID, 25 | User: rpcUser, 26 | Content: m.Content, 27 | CreateDate: m.CommentTime.Format("mm-dd"), 28 | }, nil 29 | } 30 | 31 | func Comments(ctx context.Context, ms []*db.Comment, myID int64, vdID int64) ([]*userplat.Comment, error) { 32 | comments := make([]*userplat.Comment, 0) 33 | for _, m := range ms { 34 | n, err := Comment(ctx, m, myID) 35 | if err != nil { 36 | return nil, err 37 | } 38 | comments = append(comments, n) 39 | } 40 | return comments, nil 41 | } 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2023, 808-not-found. All rights reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /cmd/user/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net" 6 | 7 | db "github.com/808-not-found/tik_duck/cmd/user/dal/db" 8 | user "github.com/808-not-found/tik_duck/kitex_gen/user/userservice" 9 | "github.com/808-not-found/tik_duck/pkg/consts" 10 | "github.com/808-not-found/tik_duck/pkg/middleware" 11 | "github.com/cloudwego/kitex/pkg/rpcinfo" 12 | server "github.com/cloudwego/kitex/server" 13 | etcd "github.com/kitex-contrib/registry-etcd" 14 | ) 15 | 16 | func main() { 17 | r, err := etcd.NewEtcdRegistry([]string{consts.EtcdAddress}) 18 | if err != nil { 19 | panic(err) 20 | } 21 | addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:10001") 22 | svr := user.NewServer(new(UserServiceImpl), 23 | server.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: consts.UserServiceName}), // server name 24 | server.WithMiddleware(middleware.CommonMiddleware), // middleWare 25 | server.WithMiddleware(middleware.ServerMiddleware), 26 | server.WithServiceAddr(addr), server.WithRegistry(r)) 27 | db.Init() 28 | err = svr.Run() 29 | 30 | if err != nil { 31 | log.Println(err.Error()) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /cmd/userplat/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net" 6 | 7 | db "github.com/808-not-found/tik_duck/cmd/userplat/dal/db" 8 | userplat "github.com/808-not-found/tik_duck/kitex_gen/userplat/userplatservice" 9 | "github.com/808-not-found/tik_duck/pkg/consts" 10 | "github.com/808-not-found/tik_duck/pkg/middleware" 11 | "github.com/cloudwego/kitex/pkg/rpcinfo" 12 | server "github.com/cloudwego/kitex/server" 13 | etcd "github.com/kitex-contrib/registry-etcd" 14 | ) 15 | 16 | func main() { 17 | r, err := etcd.NewEtcdRegistry([]string{consts.EtcdAddress}) 18 | if err != nil { 19 | panic(err) 20 | } 21 | addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:10002") 22 | svr := userplat.NewServer(new(UserPlatServiceImpl), 23 | server.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: consts.UserPlatServiceName}), // server name 24 | server.WithMiddleware(middleware.CommonMiddleware), // middleWare 25 | server.WithMiddleware(middleware.ServerMiddleware), 26 | server.WithServiceAddr(addr), server.WithRegistry(r)) 27 | db.Init() 28 | err = svr.Run() 29 | if err != nil { 30 | log.Println(err.Error()) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /pkg/jwt/jwt.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "time" 5 | 6 | allerrors "github.com/808-not-found/tik_duck/pkg/allerrors" 7 | jwt "github.com/dgrijalva/jwt-go" 8 | ) 9 | 10 | const TokenExpireDuration = JWTOverTime 11 | 12 | var MySecret = []byte(JWTSecret) //nolint:gochecknoglobals 13 | 14 | // 生成jwt //目前是只进行记录用户名. 15 | func GenToken(username string, id int64) (string, error) { 16 | c := MyClaims{ 17 | id, 18 | username, 19 | jwt.StandardClaims{ 20 | ExpiresAt: time.Now().Add(TokenExpireDuration).Unix(), 21 | Issuer: "tik-duck", 22 | }, 23 | } 24 | // 使用指定的签名方法创建签名对象 25 | token := jwt.NewWithClaims(jwt.SigningMethodHS256, c) 26 | 27 | // 使用指定的secret签名并获得完成的编码后的字符串token 28 | return token.SignedString(MySecret) 29 | } 30 | 31 | // 解析JWT. 32 | func ParseToken(tokenString string) (*MyClaims, error) { 33 | // 解析token 34 | token, err := jwt.ParseWithClaims(tokenString, &MyClaims{}, func(token *jwt.Token) (i any, err error) { 35 | return MySecret, nil 36 | }) 37 | if err != nil { 38 | return nil, err 39 | } 40 | if claims, ok := token.Claims.(*MyClaims); ok && token.Valid { 41 | return claims, nil 42 | } 43 | return nil, allerrors.ErrJWTParseTokenRun() 44 | } 45 | -------------------------------------------------------------------------------- /cmd/useruser/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net" 6 | 7 | db "github.com/808-not-found/tik_duck/cmd/useruser/dal/db" 8 | useruser "github.com/808-not-found/tik_duck/kitex_gen/useruser/useruserservice" 9 | "github.com/808-not-found/tik_duck/pkg/consts" 10 | "github.com/808-not-found/tik_duck/pkg/middleware" 11 | "github.com/cloudwego/kitex/pkg/rpcinfo" 12 | server "github.com/cloudwego/kitex/server" 13 | etcd "github.com/kitex-contrib/registry-etcd" 14 | ) 15 | 16 | func main() { 17 | r, err := etcd.NewEtcdRegistry([]string{consts.EtcdAddress}) 18 | if err != nil { 19 | panic(err) 20 | } 21 | addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:10003") 22 | svr := useruser.NewServer(new(UserUserServiceImpl), 23 | server.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: consts.UserUserServiceName}), // server name 24 | server.WithMiddleware(middleware.CommonMiddleware), // middleWare 25 | server.WithMiddleware(middleware.ServerMiddleware), 26 | server.WithServiceAddr(addr), server.WithRegistry(r)) 27 | db.Init() 28 | err = svr.Run() 29 | 30 | if err != nil { 31 | log.Println(err.Error()) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /cmd/useruser/uuservice/follow_list.go: -------------------------------------------------------------------------------- 1 | package uuservice 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/808-not-found/tik_duck/cmd/useruser/dal/db" 7 | "github.com/808-not-found/tik_duck/cmd/useruser/pack" 8 | "github.com/808-not-found/tik_duck/kitex_gen/useruser" 9 | "github.com/808-not-found/tik_duck/pkg/jwt" 10 | ) 11 | 12 | func UserRelationFollowListService( 13 | ctx context.Context, 14 | req *useruser.RelationFollowListRequest, 15 | ) (*useruser.RelationFollowListResponse, error) { 16 | var resp useruser.RelationFollowListResponse 17 | // 用户鉴权 18 | claims, err := jwt.ParseToken(req.Token) 19 | if err != nil { 20 | resp.StatusCode = 3005 21 | return &resp, err 22 | } 23 | // 验证登录状态 24 | myID := claims.ID 25 | if myID == 0 { 26 | resp.StatusCode = 3006 27 | return &resp, err 28 | } 29 | // 查询数据库 30 | var dbUsers []*db.User 31 | dbUsers, err = db.GetFollowList(ctx, req.UserId) 32 | if err != nil { 33 | resp.StatusCode = 3007 34 | return &resp, err 35 | } 36 | // 数据封装 37 | rpcUsers, err := pack.Users(dbUsers, myID) 38 | if err != nil { 39 | resp.StatusCode = 3008 40 | return &resp, err 41 | } 42 | resp.UserList = rpcUsers 43 | return &resp, nil 44 | } 45 | -------------------------------------------------------------------------------- /cmd/useruser/uuservice/follower_list.go: -------------------------------------------------------------------------------- 1 | package uuservice 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/808-not-found/tik_duck/cmd/useruser/dal/db" 7 | "github.com/808-not-found/tik_duck/cmd/useruser/pack" 8 | "github.com/808-not-found/tik_duck/kitex_gen/useruser" 9 | "github.com/808-not-found/tik_duck/pkg/jwt" 10 | ) 11 | 12 | func UserRelationFollowerList( 13 | ctx context.Context, 14 | req *useruser.RelationFollowerListRequest, 15 | ) (*useruser.RelationFollowerListResponse, error) { 16 | var resp useruser.RelationFollowerListResponse 17 | // 用户鉴权 18 | claims, err := jwt.ParseToken(req.Token) 19 | if err != nil { 20 | resp.StatusCode = 3009 21 | return &resp, err 22 | } 23 | // 登录状态检查 24 | myID := claims.ID 25 | if myID == 0 { 26 | resp.StatusCode = 3010 27 | return &resp, err 28 | } 29 | // 请求数据库 30 | var dbUsers []*db.User 31 | dbUsers, err = db.GetFollowerList(ctx, req.UserId) 32 | if err != nil { 33 | resp.StatusCode = 3011 34 | return &resp, err 35 | } 36 | // 封装数据 37 | rpcUsers, err := pack.Users(dbUsers, myID) 38 | if err != nil { 39 | resp.StatusCode = 3012 40 | return &resp, err 41 | } 42 | resp.UserList = rpcUsers 43 | return &resp, nil 44 | } 45 | -------------------------------------------------------------------------------- /cmd/web/controller/favorite.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "net/http" 7 | "strconv" 8 | 9 | "github.com/808-not-found/tik_duck/cmd/web/rpc" 10 | "github.com/808-not-found/tik_duck/kitex_gen/userplat" 11 | "github.com/cloudwego/hertz/pkg/app" 12 | ) 13 | 14 | func FavoriteAction(ctx context.Context, c *app.RequestContext) { 15 | var feedReq userplat.FavoriteActionRequest 16 | feedReq.VideoId, _ = strconv.ParseInt(c.Query("video_id"), 10, 64) 17 | actionType, _ := strconv.ParseInt(c.Query("action_type"), 10, 64) 18 | feedReq.ActionType = int32(actionType) 19 | feedReq.Token = c.Query("token") 20 | resp, err := rpc.UserFavoriteAction(context.Background(), &feedReq) 21 | if err != nil { 22 | log.Println(err) 23 | return 24 | } 25 | c.JSON(http.StatusOK, resp) 26 | } 27 | 28 | func FavoriteList(ctx context.Context, c *app.RequestContext) { 29 | var feedReq userplat.FavoriteListRequest 30 | feedReq.Token = c.Query("token") 31 | feedReq.UserId, _ = strconv.ParseInt(c.Query("user_id"), 10, 64) 32 | resp, err := rpc.UserFavoriteList(context.Background(), &feedReq) 33 | if err != nil { 34 | log.Println(err) 35 | return 36 | } 37 | c.JSON(http.StatusOK, resp) 38 | } 39 | -------------------------------------------------------------------------------- /cmd/useruser/uuservice/friend_list.go: -------------------------------------------------------------------------------- 1 | package uuservice 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/808-not-found/tik_duck/cmd/useruser/dal/db" 7 | "github.com/808-not-found/tik_duck/cmd/useruser/pack" 8 | "github.com/808-not-found/tik_duck/kitex_gen/useruser" 9 | "github.com/808-not-found/tik_duck/pkg/jwt" 10 | ) 11 | 12 | func UserRelationFriendListService( 13 | ctx context.Context, 14 | req *useruser.RelationFriendListRequest, 15 | ) (*useruser.RelationFriendListResponse, error) { 16 | var resp useruser.RelationFriendListResponse 17 | // 用户鉴权 18 | claims, err := jwt.ParseToken(req.Token) 19 | if err != nil { 20 | resp.StatusCode = 3013 21 | return &resp, err 22 | } 23 | // 检查登录状态 24 | myID := claims.ID 25 | if myID == 0 { 26 | resp.StatusCode = 3014 27 | return &resp, err 28 | } 29 | // 查询数据库 30 | var dbUsers []*db.User 31 | dbUsers, err = db.GetFriendList(ctx, myID) 32 | if err != nil { 33 | resp.StatusCode = 3015 34 | return &resp, err 35 | } 36 | // 封装数据 37 | var rpcUsers []*useruser.User 38 | rpcUsers, err = pack.Users(dbUsers, myID) 39 | if err != nil { 40 | resp.StatusCode = 3016 41 | return &resp, err 42 | } 43 | resp.UserList = rpcUsers 44 | 45 | return &resp, nil 46 | } 47 | -------------------------------------------------------------------------------- /cmd/chat/chatservice/get_msg.go: -------------------------------------------------------------------------------- 1 | package chatservice 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/808-not-found/tik_duck/cmd/chat/dal/db" 7 | "github.com/808-not-found/tik_duck/cmd/chat/pack" 8 | chat "github.com/808-not-found/tik_duck/kitex_gen/chat" 9 | "github.com/808-not-found/tik_duck/pkg/jwt" 10 | ) 11 | 12 | func GetMsgService(ctx context.Context, req *chat.MessageChatRequest) (resp *chat.MessageChatResponse, err error) { 13 | resp = &chat.MessageChatResponse{ 14 | StatusCode: 0, 15 | } 16 | 17 | var myID int64 18 | if req.Token == "" { 19 | resp.StatusCode = 4001 20 | return resp, err 21 | } 22 | claims, err := jwt.ParseToken(req.Token) 23 | if err != nil { 24 | resp.StatusCode = 4002 25 | return resp, err 26 | } 27 | myID = claims.ID 28 | 29 | var chatlist []*db.Message 30 | chatlist, err = db.GetMsg(ctx, myID, req.ToUserId, &req.PreMsgTime) 31 | if err != nil { 32 | resp.StatusCode = 4003 33 | return resp, err 34 | } 35 | 36 | var rpcList []*chat.Message 37 | rpcList, err = pack.Msgs(ctx, chatlist) 38 | if err != nil { 39 | resp.StatusCode = 4004 40 | return resp, err 41 | } 42 | 43 | resp = &chat.MessageChatResponse{ 44 | StatusCode: 0, 45 | MessageList: rpcList, 46 | } 47 | return resp, nil 48 | } 49 | -------------------------------------------------------------------------------- /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches-ignore: 6 | - renovate/** 7 | paths: 8 | - ".github/workflows/test.yaml" 9 | - "go.mod" 10 | - "go.sum" 11 | - "Taskfile.yaml" 12 | - "**.go" 13 | - "**.go.json" 14 | pull_request: 15 | branches: 16 | - master 17 | paths: 18 | - ".github/workflows/test.yaml" 19 | - "go.mod" 20 | - "go.sum" 21 | - "Taskfile.yaml" 22 | - "**.go" 23 | - "**.go.json" 24 | 25 | jobs: 26 | test: 27 | runs-on: ubuntu-22.04 28 | steps: 29 | - uses: actions/checkout@v3 30 | with: 31 | submodules: recursive 32 | 33 | - name: Install Go 34 | uses: actions/setup-go@v3 35 | with: 36 | go-version-file: "go.mod" 37 | 38 | - name: Install Task 39 | uses: arduino/setup-task@v1 40 | with: 41 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 42 | 43 | - run: go mod tidy 44 | 45 | - name: Start server and run tests 46 | run: | 47 | go run ./cmd/web/ & 48 | sleep 10 && 49 | task coverage 50 | 51 | - uses: codecov/codecov-action@v3 52 | with: 53 | files: coverage.out 54 | -------------------------------------------------------------------------------- /cmd/chat/dal/db/chat.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "context" 5 | "time" 6 | 7 | "gorm.io/gorm" 8 | ) 9 | 10 | type Message struct { 11 | gorm.Model 12 | ID int64 `gorm:"column:id;primary_key;AUTO_INCREMENT"` 13 | MessageTime time.Time `gorm:"column:message_time;default:CURRENT_TIMESTAMP;NOT NULL"` 14 | FromUserID int64 `gorm:"column:from_user_id;NOT NULL"` 15 | ToUserID int64 `gorm:"column:to_user_id;NOT NULL"` 16 | Content string `gorm:"column:content;NOT NULL"` 17 | CreatedAt time.Time `gorm:"column:created_at;default:CURRENT_TIMESTAMP;NOT NULL"` 18 | } 19 | 20 | func GetMsg(ctx context.Context, myID int64, toID int64, t *int64) (res []*Message, err error) { 21 | curTime := time.Unix(*t, 0) 22 | conn := DB.WithContext(ctx).Where("created_at <= ?", curTime).Find(&res) 23 | if err = conn.Error; err != nil { 24 | return res, err 25 | } 26 | return res, nil 27 | } 28 | 29 | func PostMsg(ctx context.Context, myID int64, toID int64, content *string) (err error) { 30 | message := Message{ 31 | FromUserID: myID, 32 | ToUserID: toID, 33 | Content: *content, 34 | } 35 | conn := DB.WithContext(ctx).Create(&message) 36 | if err = conn.Error; err != nil { 37 | return err 38 | } 39 | 40 | return nil 41 | } 42 | -------------------------------------------------------------------------------- /cmd/useruser/uuservice/action.go: -------------------------------------------------------------------------------- 1 | package uuservice 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/808-not-found/tik_duck/cmd/useruser/dal/db" 7 | "github.com/808-not-found/tik_duck/kitex_gen/useruser" 8 | "github.com/808-not-found/tik_duck/pkg/jwt" 9 | ) 10 | 11 | func UserRelationActionService( 12 | ctx context.Context, 13 | req *useruser.RelationActionRequest, 14 | ) (*useruser.RelationActionResponse, error) { 15 | var resp useruser.RelationActionResponse 16 | 17 | // 用户鉴权 18 | claims, err := jwt.ParseToken(req.Token) 19 | if err != nil { 20 | resp.StatusCode = 3001 21 | return &resp, err 22 | } 23 | 24 | // 获取必要信息 25 | // 1.获取登录用户ID 26 | // 2.获取对方用户ID 27 | // 检查是关注还是取关 28 | myID := claims.ID 29 | toID := req.ToUserId 30 | actionType := req.ActionType 31 | 32 | // 检查登录状态 33 | if myID == 0 { 34 | resp.StatusCode = 3002 35 | return &resp, err 36 | } 37 | 38 | if actionType == 1 { 39 | // 关注 操作数据库 40 | err := db.FollowAction(ctx, myID, toID) 41 | if err != nil { 42 | resp.StatusCode = 3003 43 | return &resp, err 44 | } 45 | } else { 46 | // 取关 操作数据库 47 | err := db.UnFollowAction(ctx, myID, toID) 48 | if err != nil { 49 | resp.StatusCode = 3004 50 | return &resp, err 51 | } 52 | } 53 | 54 | return &resp, nil 55 | } 56 | -------------------------------------------------------------------------------- /cmd/userplat/userplatService/userplat_favorite_list.go: -------------------------------------------------------------------------------- 1 | package userplatservice 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/808-not-found/tik_duck/cmd/userplat/dal/db" 7 | "github.com/808-not-found/tik_duck/cmd/userplat/pack" 8 | "github.com/808-not-found/tik_duck/kitex_gen/userplat" 9 | "github.com/808-not-found/tik_duck/pkg/jwt" 10 | ) 11 | 12 | func UserFavoriteListService( 13 | ctx context.Context, 14 | req *userplat.FavoriteListRequest, 15 | ) (*userplat.FavoriteListResponse, error) { 16 | var resp userplat.FavoriteListResponse 17 | 18 | // 用户鉴权 19 | var myID int64 20 | if req.Token == "" { 21 | myID = 0 22 | } else { 23 | claims, err := jwt.ParseToken(req.Token) 24 | if err != nil { 25 | resp.StatusCode = 2037 26 | return &resp, nil 27 | } 28 | myID = claims.ID 29 | } 30 | // 检查登录状态 31 | // myID := claims.ID 32 | // if myID == 0 { 33 | // resp.StatusCode = 1008 34 | // return &resp, err 35 | // } 36 | // 查询数据库 37 | dbVideos, err := db.GetFavoriteList(ctx, req.UserId) 38 | if err != nil { 39 | resp.StatusCode = 2038 40 | return &resp, err 41 | } 42 | // 数据封装 43 | rpcVideos, err := pack.Videos(ctx, dbVideos, myID) 44 | if err != nil { 45 | resp.StatusCode = 2039 46 | return &resp, err 47 | } 48 | resp.VideoList = rpcVideos 49 | 50 | return &resp, nil 51 | } 52 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tik_duck env", 3 | 4 | // Configure tool-specific properties. 5 | "customizations": { 6 | // Configure properties specific to VS Code. 7 | "vscode": { 8 | "settings": {}, 9 | "extensions": ["golang.Go", "usernamehw.errorlens"] 10 | } 11 | }, 12 | 13 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 14 | // "forwardPorts": [3000], 15 | 16 | // Use 'portsAttributes' to set default properties for specific forwarded ports. 17 | // More info: https://containers.dev/implementors/json_reference/#port-attributes 18 | // "portsAttributes": { 19 | // "9000": { 20 | // "label": "Hello Remote World", 21 | // "onAutoForward": "notify" 22 | // } 23 | // }, 24 | 25 | // Use 'postCreateCommand' to run commands after the container is created. 26 | "postCreateCommand": "go install github.com/go-task/task/v3/cmd/task@latest && go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.50.1 && go install github.com/vektra/mockery/v2@latest && go install github.com/cloudwego/kitex/tool/cmd/kitex@latest && go install github.com/cloudwego/thriftgo@latest && npm install prettier -g" 27 | 28 | // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. 29 | // "remoteUser": "root" 30 | } 31 | -------------------------------------------------------------------------------- /cmd/userplat/userplatService/userplat_comment_list.go: -------------------------------------------------------------------------------- 1 | package userplatservice 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/808-not-found/tik_duck/cmd/userplat/dal/db" 7 | "github.com/808-not-found/tik_duck/cmd/userplat/pack" 8 | "github.com/808-not-found/tik_duck/kitex_gen/userplat" 9 | "github.com/808-not-found/tik_duck/pkg/jwt" 10 | ) 11 | 12 | func UserCommentListService( 13 | ctx context.Context, 14 | req *userplat.CommentListRequest, 15 | ) (*userplat.CommentListResponse, error) { 16 | var resp userplat.CommentListResponse 17 | 18 | // 用户鉴权 19 | var myID int64 20 | if req.Token == "" { 21 | myID = 0 22 | } else { 23 | claims, err := jwt.ParseToken(req.Token) 24 | if err != nil { 25 | resp.StatusCode = 2031 26 | return &resp, nil 27 | } 28 | myID = claims.ID 29 | } 30 | 31 | // 检查登录状态 32 | // myID := claims.ID 33 | // if myID == 0 { 34 | // resp.StatusCode = 1008 35 | // return &resp, err 36 | // } 37 | 38 | vdID := req.VideoId 39 | // 查询数据库 40 | dbComments, err := db.GetCommentList(ctx, myID, vdID) 41 | if err != nil { 42 | resp.StatusCode = 2032 43 | return &resp, err 44 | } 45 | // 数据封装 46 | rpcComments, err := pack.Comments(ctx, dbComments, myID, vdID) 47 | if err != nil { 48 | resp.StatusCode = 2033 49 | return &resp, err 50 | } 51 | resp.CommentList = rpcComments 52 | 53 | return &resp, nil 54 | } 55 | -------------------------------------------------------------------------------- /cmd/user/benchmark/user_publish_list_test.go: -------------------------------------------------------------------------------- 1 | package userservice_test 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | userservice "github.com/808-not-found/tik_duck/cmd/user/userService" 8 | "github.com/808-not-found/tik_duck/kitex_gen/user" 9 | ) 10 | 11 | // struct PublishListRequest { 12 | // 1: i64 UserId (go.tag = 'json:"user_id"') //用户id 13 | // 2: string Token (go.tag = 'json:"token"') //用户鉴权token 14 | // } 15 | // 16 | // struct PublishListResponse { 17 | // 1: i32 StatusCode (go.tag = 'json:"status_code"') //状态码,0-成功,其他值-失败 18 | // 2: optional string StatusMsg (go.tag = 'json:"status_msg"') //返回状态描述 19 | // 3: list