├── .github
├── auto_assign.yml
└── workflows
│ ├── codecov.yml
│ └── lint.yaml
├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── cmd
├── comment
│ └── Dockerfile
├── favorite
│ └── Dockerfile
├── follow
│ └── Dockerfile
├── gateway
│ └── Dockerfile
├── message
│ └── Dockerfile
├── minio-client
│ └── Dockerfile
├── mq
│ └── Dockerfile
├── mysql-gen
│ └── gen.go
├── user
│ └── Dockerfile
└── video
│ └── Dockerfile
├── common
├── checkpwd
│ ├── checkPwd.go
│ └── checkPwd_test.go
├── globalkey
│ ├── constantKey.go
│ └── redisCacheKey.go
├── help
│ ├── sensitiveWords
│ │ ├── sensitiveWords.go
│ │ └── sensitiveWoredsFilter.go
│ └── token
│ │ ├── common.go
│ │ ├── genToken.go
│ │ └── parseToken.go
├── messageTypes
│ └── message.go
├── model
│ ├── GenModel
│ │ └── createModel.sh
│ ├── commentModel
│ │ ├── commentmodel.go
│ │ ├── commentmodel_gen.go
│ │ └── vars.go
│ ├── favoriteModel
│ │ ├── favoritemodel.go
│ │ ├── favoritemodel_gen.go
│ │ └── vars.go
│ ├── followModel
│ │ ├── followmodel.go
│ │ ├── followmodel_gen.go
│ │ ├── followmodel_method.go
│ │ └── vars.go
│ ├── genmodel
│ │ └── readme.md
│ ├── messageModel
│ │ ├── messagemodel.go
│ │ ├── messagemodel_gen.go
│ │ └── vars.go
│ ├── userModel
│ │ ├── usermodel.go
│ │ ├── usermodel_gen.go
│ │ └── vars.go
│ └── videoModel
│ │ ├── vars.go
│ │ ├── videomodel.go
│ │ ├── videomodel_gen.go
│ │ └── videomodel_method.go
└── xerr
│ ├── errCode.go
│ ├── errMsg.go
│ └── errors.go
├── deployment
├── cluster
│ └── douyin-cluster.yaml
├── comment
│ └── comment.yaml
├── dashboard
│ ├── README.md
│ ├── cluster_role_binding.yaml
│ └── service_account.yaml
├── favorite
│ └── favorite.yaml
├── follow
│ └── follow.yaml
├── gateway
│ └── gateway.yaml
├── message
│ └── message.yaml
├── minio-client
│ └── minio-client.yaml
├── minio
│ └── minio.yaml
├── mq
│ └── mq.yaml
├── mysql
│ ├── mysql-deploy.yaml
│ └── mysql-scheme.yaml
├── nfs
│ ├── README.md
│ ├── nfs-deploy.yaml
│ └── nfs-pvx.yaml
├── user
│ └── user.yaml
└── video
│ └── video.yaml
├── docs
├── Setup.md
└── design
│ ├── CodingRules.md
│ ├── Structure.drawio
│ └── design.md
├── go.mod
├── go.sum
├── pkg
├── comment
│ ├── etc
│ │ └── usercomment.yaml
│ ├── internal
│ │ ├── config
│ │ │ └── config.go
│ │ ├── logic
│ │ │ ├── getvideocommentlogic.go
│ │ │ └── updatecommentstatuslogic.go
│ │ ├── server
│ │ │ └── usercommentserver.go
│ │ └── svc
│ │ │ └── servicecontext.go
│ ├── readme.md
│ ├── userCommentPb
│ │ ├── GenPb
│ │ │ ├── UserComment.proto
│ │ │ └── build.sh
│ │ ├── UserComment.pb.go
│ │ └── UserComment_grpc.pb.go
│ ├── usercomment.go
│ └── usercomment
│ │ └── usercomment.go
├── constant
│ └── mysql.go
├── favorite
│ ├── etc
│ │ └── userOptService.yaml
│ ├── internal
│ │ ├── config
│ │ │ └── config.go
│ │ ├── logic
│ │ │ ├── checkIsFavoriteLogic.go
│ │ │ ├── getUserFavoriteLogic.go
│ │ │ └── updateFavoriteStatusLogic.go
│ │ ├── server
│ │ │ └── userOptServiceServer.go
│ │ └── svc
│ │ │ └── serviceContext.go
│ ├── userOptPb
│ │ ├── GenPb
│ │ │ ├── UserOptService.proto
│ │ │ └── build.sh
│ │ ├── UserOptService.pb.go
│ │ └── UserOptService_grpc.pb.go
│ ├── userOptService.go
│ └── useroptservice
│ │ └── userOptService.go
├── follow
│ ├── etc
│ │ └── follow.yaml
│ ├── follow.go
│ ├── followservice
│ │ └── followservice.go
│ ├── internal
│ │ ├── config
│ │ │ └── config.go
│ │ ├── logic
│ │ │ ├── checkisfollowlogic.go
│ │ │ ├── followlogic.go
│ │ │ ├── getfollowerlistlogic.go
│ │ │ ├── getfollowlistlogic.go
│ │ │ └── getfriendlistlogic.go
│ │ ├── server
│ │ │ └── followserviceserver.go
│ │ └── svc
│ │ │ └── servicecontext.go
│ ├── proto
│ │ └── follow.proto
│ └── types
│ │ └── follow
│ │ ├── follow.pb.go
│ │ └── follow_grpc.pb.go
├── gateway
│ ├── api.go
│ ├── api
│ │ ├── build.sh
│ │ ├── message.api
│ │ ├── user.api
│ │ ├── userOpt.api
│ │ └── video.api
│ ├── etc
│ │ └── user-api.yaml
│ └── internal
│ │ ├── config
│ │ └── config.go
│ │ ├── handler
│ │ ├── feed
│ │ │ └── feedVideoListHandler.go
│ │ ├── message
│ │ │ ├── messageHandler.go
│ │ │ └── messagelistHandler.go
│ │ ├── publish
│ │ │ ├── getPublishVideoListHandler.go
│ │ │ └── publishVideoHandler.go
│ │ ├── routes.go
│ │ ├── user
│ │ │ ├── userInfoHandler.go
│ │ │ ├── userLoginHandler.go
│ │ │ └── userRegisterHandler.go
│ │ └── userOpt
│ │ │ ├── commentOptHandler.go
│ │ │ ├── favoriteOptHandler.go
│ │ │ ├── followOptHandler.go
│ │ │ ├── getCommentListHandler.go
│ │ │ ├── getFavoriteListHandler.go
│ │ │ ├── getFollowListHandler.go
│ │ │ ├── getFollowerListHandler.go
│ │ │ └── getFriendListHandler.go
│ │ ├── logic
│ │ ├── feed
│ │ │ └── feedVideoListLogic.go
│ │ ├── message
│ │ │ ├── messageLogic.go
│ │ │ └── messagelistLogic.go
│ │ ├── publish
│ │ │ ├── getPublishVideoListLogic.go
│ │ │ └── publishVideoLogic.go
│ │ ├── user
│ │ │ ├── userInfoLogic.go
│ │ │ ├── userLoginLogic.go
│ │ │ └── userRegisterLogic.go
│ │ └── userOpt
│ │ │ ├── commentoptlogic.go
│ │ │ ├── favoriteOptLogic.go
│ │ │ ├── followOptLogic.go
│ │ │ ├── getFavoriteListLogic.go
│ │ │ ├── getFollowListLogic.go
│ │ │ ├── getFollowerListLogic.go
│ │ │ ├── getFriendListLogic.go
│ │ │ └── getcommentlistlogic.go
│ │ ├── middleware
│ │ ├── authjwtMiddleware.go
│ │ └── isloginMiddleware.go
│ │ ├── svc
│ │ └── serviceContext.go
│ │ └── types
│ │ └── types.go
├── kafka
│ ├── docs.go
│ ├── manager.go
│ └── operator.go
├── logger
│ └── log.go
├── message
│ ├── etc
│ │ └── userMessage.yaml
│ ├── internal
│ │ ├── config
│ │ │ └── config.go
│ │ ├── logic
│ │ │ ├── getMessageListLogic.go
│ │ │ └── sendMessageLogic.go
│ │ ├── server
│ │ │ └── userMessageServer.go
│ │ └── svc
│ │ │ └── serviceContext.go
│ ├── userMessage.go
│ ├── userMessagePb
│ │ ├── GenPb
│ │ │ ├── UserMessage.proto
│ │ │ └── build.sh
│ │ ├── UserMessage.pb.go
│ │ └── UserMessage_grpc.pb.go
│ └── usermessage
│ │ └── userMessage.go
├── minio-client
│ ├── etc
│ │ └── minioclient.yaml
│ ├── internal
│ │ ├── config
│ │ │ └── config.go
│ │ ├── logic
│ │ │ ├── uploadfilelogic.go
│ │ │ └── utils.go
│ │ ├── server
│ │ │ └── minioclientserver.go
│ │ └── svc
│ │ │ └── servicecontext.go
│ ├── minioclient.go
│ ├── minioclient
│ │ └── minioclient.go
│ ├── proto
│ │ └── minio-client.proto
│ └── types
│ │ └── minio-client
│ │ ├── minio-client.pb.go
│ │ └── minio-client_grpc.pb.go
├── mq
│ ├── etc
│ │ └── mq.yaml
│ ├── internal
│ │ ├── config
│ │ │ └── config.go
│ │ ├── listen
│ │ │ ├── kqMqs.go
│ │ │ └── listen.go
│ │ ├── mqs
│ │ │ └── kq
│ │ │ │ ├── userCommentUpdate.go
│ │ │ │ ├── userFavoriteUpdate.go
│ │ │ │ └── userFollowUpdate.go
│ │ └── svc
│ │ │ └── serviceContext.go
│ └── mq.go
├── sql
│ ├── 01_test.go
│ ├── README.md
│ ├── dal
│ │ ├── dal.go
│ │ ├── method.go
│ │ ├── model
│ │ │ ├── chat.gen.go
│ │ │ ├── comment.gen.go
│ │ │ ├── favorite.gen.go
│ │ │ ├── follow.gen.go
│ │ │ ├── user.gen.go
│ │ │ └── video.gen.go
│ │ ├── query
│ │ │ ├── chat.gen.go
│ │ │ ├── comment.gen.go
│ │ │ ├── favorite.gen.go
│ │ │ ├── follow.gen.go
│ │ │ ├── gen.go
│ │ │ ├── user.gen.go
│ │ │ └── video.gen.go
│ │ └── user_test.go
│ ├── pack
│ │ ├── conn.go
│ │ └── query.go
│ └── schema.sql
├── user
│ ├── etc
│ │ └── userService.yaml
│ ├── internal
│ │ ├── config
│ │ │ └── config.go
│ │ ├── logic
│ │ │ ├── infoLogic.go
│ │ │ ├── loginLogic.go
│ │ │ └── registerLogic.go
│ │ ├── server
│ │ │ └── userServiceServer.go
│ │ └── svc
│ │ │ └── serviceContext.go
│ ├── user.go
│ ├── userInfoPb
│ │ ├── GenPb
│ │ │ ├── UserService.proto
│ │ │ └── build.sh
│ │ ├── UserService.pb.go
│ │ └── UserService_grpc.pb.go
│ └── userservice
│ │ └── userService.go
└── video
│ ├── etc
│ └── video.yaml
│ ├── internal
│ ├── config
│ │ └── config.go
│ ├── logic
│ │ ├── changevideocommentlogic.go
│ │ ├── getallvideobyuseridlogic.go
│ │ ├── getvideologic.go
│ │ └── publishvideologic.go
│ ├── server
│ │ └── videoserviceserver.go
│ └── svc
│ │ └── servicecontext.go
│ ├── proto
│ └── video.proto
│ ├── types
│ └── video
│ │ ├── video.pb.go
│ │ └── video_grpc.pb.go
│ ├── video.go
│ └── videoservice
│ └── videoservice.go
└── proto
├── READEME.md
├── comment_action.proto
├── comment_list.proto
├── favorite_action.proto
├── favorite_list.proto
├── feed.proto
├── message_action.proto
├── message_chat.proto
├── publish_action.proto
├── publish_list.proto
├── relation_action.proto
├── relation_follow_list.proto
├── relation_follower_list.proto
├── relation_friend_list.proto
├── user.proto
├── user_login.proto
└── user_register.proto
/.github/auto_assign.yml:
--------------------------------------------------------------------------------
1 | # Set to true to add reviewers to pull requests
2 | addReviewers: true
3 |
4 | # Set to true to add assignees to pull requests
5 | addAssignees: true
6 |
7 | # A list of reviewers to be added to pull requests (GitHub user name)
8 | reviewers:
9 | - Vacant2333
10 |
11 | # A list of keywords to be skipped the process that add reviewers if pull requests include it
12 | skipKeywords:
13 | - wip
14 |
15 | # A number of reviewers added to the pull request
16 | # Set 0 to add all the reviewers (default: 0)
17 | numberOfReviewers: 0
18 |
--------------------------------------------------------------------------------
/.github/workflows/codecov.yml:
--------------------------------------------------------------------------------
1 | name: golangci-codecov
2 |
3 | on:
4 | push:
5 | branches: [ "main" ]
6 | pull_request:
7 | branches: [ "main" ]
8 |
9 | jobs:
10 | build:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/checkout@v2
14 | with:
15 | fetch-depth: 2
16 | - uses: actions/setup-go@v2
17 | with:
18 | go-version: '1.18'
19 | - name: Run coverage
20 | run: go test -race -coverprofile=coverage.txt -covermode=atomic ./...
21 | - name: Upload coverage to Codecov
22 | uses: codecov/codecov-action@v3
--------------------------------------------------------------------------------
/.github/workflows/lint.yaml:
--------------------------------------------------------------------------------
1 | name: golangci-lint
2 | on:
3 | push:
4 | tags:
5 | - v*
6 | branches:
7 | - master
8 | - main
9 | pull_request:
10 | permissions:
11 | contents: read
12 | # Optional: allow read access to pull request. Use with `only-new-issues` option.
13 | # pull-requests: read
14 | jobs:
15 | golangci:
16 | name: lint
17 | runs-on: ubuntu-latest
18 | steps:
19 | - uses: actions/setup-go@v3
20 | with:
21 | go-version: 1.19
22 | - uses: actions/checkout@v3
23 | - name: golangci-lint
24 | uses: golangci/golangci-lint-action@v3
25 | with:
26 | # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
27 | version: latest
28 | args: --timeout=10m
29 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .vscode
3 | /deployment/dashboard/token.txt
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Vacant
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ByteDance douyin project
2 |
3 | [Docs](https://github.com/Vacant2333/douyin/blob/main/docs/)
4 |
5 | [Structure](https://github.com/Vacant2333/douyin/blob/main/docs/design/Structure.drawio)
--------------------------------------------------------------------------------
/cmd/comment/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:latest AS builder
2 | ENV CGO_ENABLED 0
3 | ENV GOPROXY https://goproxy.cn,direct
4 | WORKDIR /build
5 | ADD go.mod .
6 | ADD go.sum .
7 | RUN go mod download
8 | COPY pkg /usr/local/go/src/douyin/pkg
9 | COPY common /usr/local/go/src/douyin/common
10 | COPY pkg/comment/etc /app/etc
11 | RUN go build -ldflags="-s -w" -o /app/usercomment /usr/local/go/src/douyin/pkg/comment/usercomment.go
12 |
13 | FROM gcr.io/distroless/static-debian11:latest
14 | WORKDIR /app
15 | COPY --from=builder /app/usercomment /app/usercomment
16 | COPY --from=builder /app/etc /app/etc
17 | CMD ["./usercomment", "-f", "etc/usercomment.yaml"]
18 |
--------------------------------------------------------------------------------
/cmd/favorite/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:latest AS builder
2 | ENV CGO_ENABLED 0
3 | ENV GOPROXY https://goproxy.cn,direct
4 | WORKDIR /build
5 | ADD go.mod .
6 | ADD go.sum .
7 | RUN go mod download
8 | COPY pkg /usr/local/go/src/douyin/pkg
9 | COPY common /usr/local/go/src/douyin/common
10 | COPY pkg/favorite/etc /app/etc
11 | RUN go build -ldflags="-s -w" -o /app/favorite /usr/local/go/src/douyin/pkg/favorite/userOptService.go
12 |
13 | FROM gcr.io/distroless/static-debian11:latest
14 | WORKDIR /app
15 | COPY --from=builder /app/favorite /app/favorite
16 | COPY --from=builder /app/etc /app/etc
17 | CMD ["./favorite", "-f", "etc/userOptService.yaml"]
18 |
--------------------------------------------------------------------------------
/cmd/follow/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:latest AS builder
2 | ENV CGO_ENABLED 0
3 | ENV GOPROXY https://goproxy.cn,direct
4 | WORKDIR /build
5 | ADD go.mod .
6 | ADD go.sum .
7 | RUN go mod download
8 | COPY pkg /usr/local/go/src/douyin/pkg
9 | COPY common /usr/local/go/src/douyin/common
10 | COPY pkg/follow/etc /app/etc
11 | RUN go build -ldflags="-s -w" -o /app/follow /usr/local/go/src/douyin/pkg/follow/follow.go
12 |
13 | FROM gcr.io/distroless/static-debian11:latest
14 | WORKDIR /app
15 | COPY --from=builder /app/follow /app/follow
16 | COPY --from=builder /app/etc /app/etc
17 | CMD ["./follow", "-f", "etc/follow.yaml"]
18 |
--------------------------------------------------------------------------------
/cmd/gateway/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:latest AS builder
2 | ENV CGO_ENABLED 0
3 | ENV GOPROXY https://goproxy.cn,direct
4 | WORKDIR /build
5 | ADD go.mod .
6 | ADD go.sum .
7 | RUN go mod download
8 | COPY pkg /usr/local/go/src/douyin/pkg
9 | COPY common /usr/local/go/src/douyin/common
10 | COPY pkg/gateway/etc /app/etc
11 | RUN go build -ldflags="-s -w" -o /app/gateway /usr/local/go/src/douyin/pkg/gateway/api.go
12 |
13 | FROM gcr.io/distroless/static-debian11:latest
14 | WORKDIR /app
15 | COPY --from=builder /app/gateway /app/gateway
16 | COPY --from=builder /app/etc /app/etc
17 | CMD ["./gateway", "-f", "etc/user-api.yaml"]
18 |
--------------------------------------------------------------------------------
/cmd/message/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:latest AS builder
2 | ENV CGO_ENABLED 0
3 | ENV GOPROXY https://goproxy.cn,direct
4 | WORKDIR /build
5 | ADD go.mod .
6 | ADD go.sum .
7 | RUN go mod download
8 | COPY pkg /usr/local/go/src/douyin/pkg
9 | COPY common /usr/local/go/src/douyin/common
10 | COPY pkg/message/etc /app/etc
11 | RUN go build -ldflags="-s -w" -o /app/message /usr/local/go/src/douyin/pkg/message/userMessage.go
12 |
13 | FROM gcr.io/distroless/static-debian11:latest
14 | WORKDIR /app
15 | COPY --from=builder /app/message /app/message
16 | COPY --from=builder /app/etc /app/etc
17 | CMD ["./message", "-f", "etc/userMessage.yaml"]
18 |
--------------------------------------------------------------------------------
/cmd/minio-client/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:latest AS builder
2 | ENV CGO_ENABLED 0
3 | ENV GOPROXY https://goproxy.cn,direct
4 | WORKDIR /build
5 | ADD go.mod .
6 | ADD go.sum .
7 | RUN go mod download
8 | COPY pkg /usr/local/go/src/douyin/pkg
9 | COPY common /usr/local/go/src/douyin/common
10 | COPY pkg/minio-client/etc /app/etc
11 | RUN go build -ldflags="-s -w" -o /app/minioclient /usr/local/go/src/douyin/pkg/minio-client/minioclient.go
12 |
13 | FROM minidocks/ffmpeg
14 | WORKDIR /app
15 | COPY --from=builder /app/minioclient /app/minioclient
16 | COPY --from=builder /app/etc /app/etc
17 | CMD ["./minioclient", "-f", "etc/minioclient.yaml"]
18 |
--------------------------------------------------------------------------------
/cmd/mq/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:latest AS builder
2 | ENV CGO_ENABLED 0
3 | ENV GOPROXY https://goproxy.cn,direct
4 | WORKDIR /build
5 | ADD go.mod .
6 | ADD go.sum .
7 | RUN go mod download
8 | COPY pkg /usr/local/go/src/douyin/pkg
9 | COPY common /usr/local/go/src/douyin/common
10 | COPY pkg/mq/etc /app/etc
11 | RUN go build -ldflags="-s -w" -o /app/mq /usr/local/go/src/douyin/pkg/mq/mq.go
12 |
13 | FROM gcr.io/distroless/static-debian11:latest
14 | WORKDIR /app
15 | COPY --from=builder /app/mq /app/mq
16 | COPY --from=builder /app/etc /app/etc
17 | CMD ["./mq", "-f", "etc/mq.yaml"]
18 |
--------------------------------------------------------------------------------
/cmd/user/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:latest AS builder
2 | ENV CGO_ENABLED 0
3 | ENV GOPROXY https://goproxy.cn,direct
4 | WORKDIR /build
5 | ADD go.mod .
6 | ADD go.sum .
7 | RUN go mod download
8 | COPY pkg /usr/local/go/src/douyin/pkg
9 | COPY common /usr/local/go/src/douyin/common
10 | COPY pkg/user/etc /app/etc
11 | RUN go build -ldflags="-s -w" -o /app/user /usr/local/go/src/douyin/pkg/user/user.go
12 |
13 | FROM gcr.io/distroless/static-debian11:latest
14 | WORKDIR /app
15 | COPY --from=builder /app/user /app/user
16 | COPY --from=builder /app/etc /app/etc
17 | CMD ["./user", "-f", "etc/userService.yaml"]
18 |
--------------------------------------------------------------------------------
/cmd/video/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:latest AS builder
2 | ENV CGO_ENABLED 0
3 | ENV GOPROXY https://goproxy.cn,direct
4 | WORKDIR /build
5 | ADD go.mod .
6 | ADD go.sum .
7 | RUN go mod download
8 | COPY pkg /usr/local/go/src/douyin/pkg
9 | COPY common /usr/local/go/src/douyin/common
10 | COPY pkg/video/etc /app/etc
11 | RUN go build -ldflags="-s -w" -o /app/video /usr/local/go/src/douyin/pkg/video/video.go
12 |
13 | FROM gcr.io/distroless/static-debian11:latest
14 | WORKDIR /app
15 | COPY --from=builder /app/video /app/video
16 | COPY --from=builder /app/etc /app/etc
17 | CMD ["./video", "-f", "etc/video.yaml"]
18 |
--------------------------------------------------------------------------------
/common/checkpwd/checkPwd.go:
--------------------------------------------------------------------------------
1 | package checkpwd
2 |
3 | import (
4 | "fmt"
5 | "regexp"
6 | )
7 |
8 | // 密码强度必须为字⺟⼤⼩写+数字+符号,9位以上
9 | func CheckPassword(ps string) error {
10 | if len(ps) < 9 {
11 | return fmt.Errorf("password len is < 9")
12 | }
13 | num := `[0-9]{1}`
14 | a_z := `[a-z]{1}`
15 | A_Z := `[A-Z]{1}`
16 | symbol := `[!@#~$%^&*()+|_]{1}`
17 | if b, err := regexp.MatchString(num, ps); !b || err != nil {
18 | return fmt.Errorf("password need num :%v", err)
19 | }
20 | if b, err := regexp.MatchString(a_z, ps); !b || err != nil {
21 | return fmt.Errorf("password need a_z :%v", err)
22 | }
23 | if b, err := regexp.MatchString(A_Z, ps); !b || err != nil {
24 | return fmt.Errorf("password need A_Z :%v", err)
25 | }
26 | if b, err := regexp.MatchString(symbol, ps); !b || err != nil {
27 | return fmt.Errorf("password need symbol :%v", err)
28 | }
29 | return nil
30 | }
31 |
--------------------------------------------------------------------------------
/common/checkpwd/checkPwd_test.go:
--------------------------------------------------------------------------------
1 | package checkpwd
2 |
3 | import (
4 | "fmt"
5 | "testing"
6 | )
7 |
8 | func TestCheckPassword(t *testing.T) { // 测试函数名必须以Test开头,必须接收一个*testing.T类型参数
9 | got := CheckPassword("@2019") // 程序输出的结果
10 | fmt.Printf("result:%v\n", got)
11 | }
12 |
--------------------------------------------------------------------------------
/common/globalkey/constantKey.go:
--------------------------------------------------------------------------------
1 | package globalkey
2 |
3 | // 软删除只是在数据库表中添加量该字段
4 |
5 | var DelStateNo int64 = 0 //未删除
6 | var DelStateYes int64 = 1 //已删除
7 |
--------------------------------------------------------------------------------
/common/globalkey/redisCacheKey.go:
--------------------------------------------------------------------------------
1 | package globalkey
2 |
3 | // 存放的是api记录点赞和关注放在redis的key与valTpl
4 |
5 | const FavoriteSetKey = "FavoriteKey"
6 | const FavoriteSetValTpl = "Favorite&Video&Id:%d"
7 |
8 | const FollowSetKey = "FollowKey"
9 | const FollowSetValTpl = "Follow&Follow&Id:%d"
10 |
11 | const ExistDataValTpl = "%d:%d"
12 |
--------------------------------------------------------------------------------
/common/help/sensitiveWords/sensitiveWords.go:
--------------------------------------------------------------------------------
1 | package sensitiveWords
2 |
3 | var SensitiveWords = []string{
4 | "共产专制",
5 | "共产王朝",
6 | "裆中央",
7 | "土共",
8 | "土g",
9 | "共狗",
10 | "g匪",
11 | "共匪",
12 | "仇共",
13 | "共产党腐败",
14 | "共产党专制",
15 | "共产党的报应",
16 | "共产党的末日",
17 | "共产党专制",
18 | "communistparty",
19 | "症腐",
20 | "政腐",
21 | "政付",
22 | "正府",
23 | "政俯",
24 | "政f",
25 | "zhengfu",
26 | "政zhi",
27 | "挡中央",
28 | "档中央",
29 | "中国zf",
30 | "中央zf",
31 | "国wu院",
32 | "中华帝国",
33 | "gong和",
34 | "大陆官方",
35 | "北京政权",
36 | "艹你",
37 | "死全家",
38 | "全家不得好死",
39 | "cao你",
40 | "草你妈",
41 | "日你妈",
42 | "JB",
43 | "本屌",
44 | "齐B短裙",
45 | "法克鱿",
46 | "傻逼",
47 | "绿茶婊",
48 | "你妈的",
49 | "表砸",
50 | "屌爆了",
51 | "买了个婊",
52 | "已撸",
53 | "吉跋猫",
54 | "妈蛋",
55 | "碧池",
56 | "淫家",
57 | "法轮功",
58 | "伪火",
59 | "退党",
60 | "超越红墙",
61 | "逢8必灾",
62 | "逢八必灾",
63 | "逢9必乱",
64 | "逢九必乱",
65 | "甲睾酮",
66 | "adrenaline",
67 | "erythropoietin",
68 | "地奈德",
69 | "莫达非尼",
70 | "氯噻嗪",
71 | "苯巴比妥",
72 | "促性腺激素",
73 | "泼尼松",
74 | "麻黄草",
75 | "雄烯二醇",
76 | "地塞米松",
77 | "tamoxifen",
78 | "strychnine",
79 | "androst",
80 | "新型毒品",
81 | "杜冷丁",
82 | "兴奋剂",
83 | "mdma",
84 | "海洛因",
85 | "海luo因",
86 | "heroin",
87 | "diamorphine",
88 | "diacetylmorphine",
89 | "鸦片",
90 | "阿芙蓉",
91 | "咖啡因",
92 | "cocain",
93 | "三唑仑",
94 | "美沙酮",
95 | "麻古",
96 | "k粉",
97 | "凯他敏",
98 | "ketamine",
99 | "冰毒",
100 | "苯丙胺",
101 | "cannabis",
102 | "大麻",
103 | "爱他死",
104 | "氯胺酮",
105 | "benzodiazepines",
106 | "甲基安非他明",
107 | "安非他命",
108 | "吗啡",
109 | "社会主义灭亡",
110 | "打倒中国",
111 | "打倒共产党",
112 | "打倒共产主义",
113 | "64惨案",
114 | "64时期",
115 | "64运动",
116 | "4事件",
117 | "四事件",
118 | "北京风波",
119 | "操逼",
120 | "操黑",
121 | "操烂",
122 | "肏你",
123 | "肏死",
124 | "插逼",
125 | "插进",
126 | "插你",
127 | "插我",
128 | "插阴",
129 | "潮吹",
130 | "潮喷",
131 | "成人dv",
132 | "成人电影",
133 | "成人论坛",
134 | "成人小说",
135 | "成人电",
136 | "成人电影",
137 | "成人卡通",
138 | "成人聊",
139 | "成人片",
140 | "成人视",
141 | "成人图",
142 | "成人文",
143 | "成人小",
144 | "成人电影",
145 | "成人论坛",
146 | "成人色情",
147 | "成人网站",
148 | "成人文学",
149 | "成人小说",
150 | "艳情小说",
151 | "成人游戏",
152 | "黄片",
153 | "几吧",
154 | "鸡吧",
155 | "鸡巴",
156 | "鸡奸",
157 | "寂寞男",
158 | "寂寞女",
159 | "妓女",
160 | "激情",
161 | "集体淫",
162 | "奸情",
163 | "叫床",
164 | "脚交",
165 | }
166 |
--------------------------------------------------------------------------------
/common/help/sensitiveWords/sensitiveWoredsFilter.go:
--------------------------------------------------------------------------------
1 | package sensitiveWords
2 |
3 | import (
4 | "github.com/zeromicro/go-zero/core/stringx"
5 | )
6 |
7 | func SensitiveWordsFliter(sensitiveWords []string, context string, replaceMask rune) string {
8 | //敏感词过滤
9 | filter := stringx.NewTrie(sensitiveWords, stringx.WithMask(replaceMask)) // 默认替换为*
10 | safe, _, _ := filter.Filter(context)
11 | return safe
12 | }
13 |
--------------------------------------------------------------------------------
/common/help/token/common.go:
--------------------------------------------------------------------------------
1 | package token
2 |
3 | import "github.com/golang-jwt/jwt/v4"
4 |
5 | type Claims struct {
6 | UserId int64 `json:"user_id"`
7 | ExpireAt int64 `json:"expire_at"`
8 | Else jwt.MapClaims
9 | jwt.RegisteredClaims
10 | }
11 |
12 | type CurrentUserId string
13 |
14 | const (
15 | AccessSecret = "pedagoguing"
16 | AccessExpire = 86400
17 | )
18 |
--------------------------------------------------------------------------------
/common/help/token/genToken.go:
--------------------------------------------------------------------------------
1 | package token
2 |
3 | import (
4 | "github.com/golang-jwt/jwt/v4"
5 | "time"
6 | )
7 |
8 | type GenToken struct{}
9 |
10 | func (g *GenToken) GenToken(iat time.Time, userId int64, payloads map[string]interface{}) (string, error) {
11 | claims := Claims{
12 | UserId: userId,
13 | ExpireAt: iat.Add(time.Second * AccessExpire).Unix(),
14 | RegisteredClaims: jwt.RegisteredClaims{
15 | Issuer: "pedagoguing",
16 | },
17 | }
18 | for k, v := range payloads {
19 | claims.Else[k] = v
20 | }
21 | token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
22 | return token.SignedString([]byte(AccessSecret))
23 | }
24 |
--------------------------------------------------------------------------------
/common/help/token/parseToken.go:
--------------------------------------------------------------------------------
1 | package token
2 |
3 | import "github.com/golang-jwt/jwt/v4"
4 |
5 | type ParseToken struct{}
6 |
7 | func (*ParseToken) ParseToken(tokenString string) (*Claims, error) {
8 | // 解码token
9 | tokenClaims, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
10 | return []byte(AccessSecret), nil
11 | })
12 | // 如果不为空,解码成功
13 | if tokenClaims != nil {
14 | // 断言转换
15 | if claims, ok := tokenClaims.Claims.(*Claims); ok && tokenClaims.Valid {
16 | return claims, nil
17 | }
18 | }
19 | return nil, err
20 | }
21 |
--------------------------------------------------------------------------------
/common/messageTypes/message.go:
--------------------------------------------------------------------------------
1 | package messageTypes
2 |
3 | const (
4 | ActionADD int64 = 1
5 | ActionCancel int64 = 2
6 | ActionErr int64 = -99
7 | )
8 |
9 | // UserCommentOptMessage 评论 / 删除评论
10 | type UserCommentOptMessage struct {
11 | VideoId int64 `json:"video_id"`
12 | CommentId int64 `json:"comment_id"`
13 | UserId int64 `json:"user_id"`
14 | ActionType int64 `json:"action_type"`
15 | CommentText string `json:"comment_text,omitempty"`
16 | CreateDate string `json:"create_date,omitempty"`
17 | }
18 |
19 | // UserFavoriteOptMessage 点赞 / 取消点赞
20 | type UserFavoriteOptMessage struct {
21 | ActionType int64 `json:"action_type"`
22 | VideoId int64 `json:"video_id"`
23 | UserId int64 `json:"user_id"`
24 | }
25 |
26 | // UserFollowOptMessage 关注 / 取消关注
27 | type UserFollowOptMessage struct {
28 | ActionType int64 `json:"action_type"`
29 | ToUserId int64 `json:"to_user_id"`
30 | UserId int64 `json:"user_id"`
31 | }
32 |
--------------------------------------------------------------------------------
/common/model/GenModel/createModel.sh:
--------------------------------------------------------------------------------
1 | # 生成comment表模型
2 | goctl model mysql datasource -url="root:2019xzcdg@tcp(120.25.202.230:3306)/tiktok" -table="comment" -c -dir="../../model" --home=../../../../../tpl/1.3.5
--------------------------------------------------------------------------------
/common/model/commentModel/commentmodel.go:
--------------------------------------------------------------------------------
1 | package commentModel
2 |
3 | import (
4 | "github.com/zeromicro/go-zero/core/stores/cache"
5 | "github.com/zeromicro/go-zero/core/stores/sqlx"
6 | )
7 |
8 | var _ CommentModel = (*customCommentModel)(nil)
9 |
10 | type (
11 | // CommentModel is an interface to be customized, add more methods here,
12 | // and implement the added methods in customCommentModel.
13 | CommentModel interface {
14 | commentModel
15 | }
16 |
17 | customCommentModel struct {
18 | *defaultCommentModel
19 | }
20 | )
21 |
22 | // NewCommentModel returns a model for the database table.
23 | func NewCommentModel(conn sqlx.SqlConn, c cache.CacheConf) CommentModel {
24 | return &customCommentModel{
25 | defaultCommentModel: newCommentModel(conn, c),
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/common/model/commentModel/vars.go:
--------------------------------------------------------------------------------
1 | package commentModel
2 |
3 | import "github.com/zeromicro/go-zero/core/stores/sqlx"
4 |
5 | var ErrNotFound = sqlx.ErrNotFound
6 |
--------------------------------------------------------------------------------
/common/model/favoriteModel/favoritemodel.go:
--------------------------------------------------------------------------------
1 | package favoriteModel
2 |
3 | import "github.com/zeromicro/go-zero/core/stores/sqlx"
4 |
5 | var _ FavoriteModel = (*customFavoriteModel)(nil)
6 |
7 | type (
8 | // FavoriteModel is an interface to be customized, add more methods here,
9 | // and implement the added methods in customFavoriteModel.
10 | FavoriteModel interface {
11 | favoriteModel
12 | }
13 |
14 | customFavoriteModel struct {
15 | *defaultFavoriteModel
16 | }
17 | )
18 |
19 | // NewFavoriteModel returns a model for the database table.
20 | func NewFavoriteModel(conn sqlx.SqlConn) FavoriteModel {
21 | return &customFavoriteModel{
22 | defaultFavoriteModel: newFavoriteModel(conn),
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/common/model/favoriteModel/vars.go:
--------------------------------------------------------------------------------
1 | package favoriteModel
2 |
3 | import "github.com/zeromicro/go-zero/core/stores/sqlx"
4 |
5 | var ErrNotFound = sqlx.ErrNotFound
6 |
--------------------------------------------------------------------------------
/common/model/followModel/followmodel.go:
--------------------------------------------------------------------------------
1 | package followModel
2 |
3 | import (
4 | "github.com/zeromicro/go-zero/core/stores/cache"
5 | "github.com/zeromicro/go-zero/core/stores/sqlx"
6 | )
7 |
8 | var _ FollowModel = (*customFollowModel)(nil)
9 |
10 | type (
11 | // FollowModel is an interface to be customized, add more methods here,
12 | // and implement the added methods in customFollowModel.
13 | FollowModel interface {
14 | followModel
15 | }
16 |
17 | customFollowModel struct {
18 | *defaultFollowModel
19 | }
20 | )
21 |
22 | // NewFollowModel returns a model for the database table.
23 | func NewFollowModel(conn sqlx.SqlConn, c cache.CacheConf) FollowModel {
24 | return &customFollowModel{
25 | defaultFollowModel: newFollowModel(conn, c),
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/common/model/followModel/vars.go:
--------------------------------------------------------------------------------
1 | package followModel
2 |
3 | import "github.com/zeromicro/go-zero/core/stores/sqlx"
4 |
5 | var ErrNotFound = sqlx.ErrNotFound
6 |
--------------------------------------------------------------------------------
/common/model/genmodel/readme.md:
--------------------------------------------------------------------------------
1 | ```bash
2 | cd ../
3 | goctl model mysql datasource -url="root:123456@tcp(127.0.0.1:3306)/tiktok" -table="video" -dir="./videoModel" -c
4 | goctl model mysql datasource -url="root:123456@tcp(127.0.0.1:3306)/tiktok" -table="follow" -dir="./followModel" -c
5 | ```
--------------------------------------------------------------------------------
/common/model/messageModel/messagemodel.go:
--------------------------------------------------------------------------------
1 | package messageModel
2 |
3 | import (
4 | "github.com/zeromicro/go-zero/core/stores/cache"
5 | "github.com/zeromicro/go-zero/core/stores/sqlx"
6 | )
7 |
8 | var _ MessageModel = (*customMessageModel)(nil)
9 |
10 | type (
11 | // MessageModel is an interface to be customized, add more methods here,
12 | // and implement the added methods in customMessageModel.
13 | MessageModel interface {
14 | messageModel
15 | }
16 |
17 | customMessageModel struct {
18 | *defaultMessageModel
19 | }
20 | )
21 |
22 | // NewMessageModel returns a model for the database table.
23 | func NewMessageModel(conn sqlx.SqlConn, c cache.CacheConf) MessageModel {
24 | return &customMessageModel{
25 | defaultMessageModel: newMessageModel(conn, c),
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/common/model/messageModel/vars.go:
--------------------------------------------------------------------------------
1 | package messageModel
2 |
3 | import "github.com/zeromicro/go-zero/core/stores/sqlx"
4 |
5 | var ErrNotFound = sqlx.ErrNotFound
6 |
--------------------------------------------------------------------------------
/common/model/userModel/usermodel.go:
--------------------------------------------------------------------------------
1 | package userModel
2 |
3 | import (
4 | "github.com/zeromicro/go-zero/core/stores/cache"
5 | "github.com/zeromicro/go-zero/core/stores/sqlx"
6 | )
7 |
8 | var _ UserModel = (*customUserModel)(nil)
9 |
10 | type (
11 | // UserModel is an interface to be customized, add more methods here,
12 | // and implement the added methods in customUserModel.
13 | UserModel interface {
14 | userModel
15 | }
16 |
17 | customUserModel struct {
18 | *defaultUserModel
19 | }
20 | )
21 |
22 | // NewUserModel returns a model for the database table.
23 | func NewUserModel(conn sqlx.SqlConn, c cache.CacheConf) UserModel {
24 | return &customUserModel{
25 | defaultUserModel: newUserModel(conn, c),
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/common/model/userModel/vars.go:
--------------------------------------------------------------------------------
1 | package userModel
2 |
3 | import "github.com/zeromicro/go-zero/core/stores/sqlx"
4 |
5 | var ErrNotFound = sqlx.ErrNotFound
6 |
--------------------------------------------------------------------------------
/common/model/videoModel/vars.go:
--------------------------------------------------------------------------------
1 | package videoModel
2 |
3 | import "github.com/zeromicro/go-zero/core/stores/sqlx"
4 |
5 | var ErrNotFound = sqlx.ErrNotFound
6 |
--------------------------------------------------------------------------------
/common/model/videoModel/videomodel.go:
--------------------------------------------------------------------------------
1 | package videoModel
2 |
3 | import (
4 | "github.com/zeromicro/go-zero/core/stores/cache"
5 | "github.com/zeromicro/go-zero/core/stores/sqlx"
6 | )
7 |
8 | var _ VideoModel = (*customVideoModel)(nil)
9 |
10 | type (
11 | // VideoModel is an interface to be customized, add more methods here,
12 | // and implement the added methods in customVideoModel.
13 | VideoModel interface {
14 | videoModel
15 | }
16 |
17 | customVideoModel struct {
18 | *defaultVideoModel
19 | }
20 | )
21 |
22 | // NewVideoModel returns a model for the database table.
23 | func NewVideoModel(conn sqlx.SqlConn, c cache.CacheConf) VideoModel {
24 | return &customVideoModel{
25 | defaultVideoModel: newVideoModel(conn, c),
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/common/model/videoModel/videomodel_method.go:
--------------------------------------------------------------------------------
1 | package videoModel
2 |
3 | import (
4 | "context"
5 | "database/sql"
6 | "fmt"
7 | "github.com/zeromicro/go-zero/core/stores/sqlc"
8 | "github.com/zeromicro/go-zero/core/stores/sqlx"
9 | )
10 |
11 | func (m *defaultVideoModel) FindManyByTime(ctx context.Context, time int64, num int64) ([]*Video, error) {
12 | var resp []*Video
13 | query := fmt.Sprintf("select %s from %s where `removed` = 0 and `time` > ? limit ?", videoRows, m.table)
14 | err := m.QueryRowsNoCacheCtx(ctx, &resp, query, time, num)
15 |
16 | switch err {
17 | case nil:
18 | return resp, nil
19 | case sqlc.ErrNotFound:
20 | return nil, ErrNotFound
21 | default:
22 | return nil, err
23 | }
24 | }
25 |
26 | func (m *defaultVideoModel) FindAllByUserId(ctx context.Context, userId int64) ([]*Video, error) {
27 | var resp []*Video
28 | query := fmt.Sprintf("select %s from %s where `removed` = 0 and `author_id` = ?", videoRows, m.table)
29 | err := m.QueryRowsNoCacheCtx(ctx, &resp, query, userId)
30 |
31 | switch err {
32 | case nil:
33 | return resp, nil
34 | case sqlc.ErrNotFound:
35 | return nil, ErrNotFound
36 | default:
37 | return nil, err
38 | }
39 | }
40 |
41 | func (m *defaultVideoModel) UpdateCount(ctx context.Context, videoId int64, filed string, actionType int64) error {
42 | var query string
43 | if actionType == 1 {
44 | query = fmt.Sprintf("update %s set %s = %s + 1 where `id` = ?", m.table, filed, filed)
45 | } else {
46 | query = fmt.Sprintf("update %s set %s = %s - 1 where `id` = ?", m.table, filed, filed)
47 | }
48 | tiktokVideoIdKey := fmt.Sprintf("%s%v", cacheTiktokVideoIdPrefix, videoId)
49 | _, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
50 | return conn.ExecCtx(ctx, query, videoId)
51 | }, tiktokVideoIdKey)
52 | if err != nil {
53 | return err
54 | }
55 | return nil
56 | }
57 |
--------------------------------------------------------------------------------
/common/xerr/errCode.go:
--------------------------------------------------------------------------------
1 | package xerr
2 |
3 | // 通用错误码成功返回
4 | const (
5 | OK int64 = 0
6 | ERR int64 = 1
7 | )
8 |
9 | // 全局错误码
10 | const (
11 | SERVER_COMMON_ERROR int64 = 100001
12 | REUQEST_PARAM_ERROR int64 = 100002
13 | TOKEN_EXPIRE_ERROR int64 = 100003
14 | TOKEN_GENERATE_ERROR int64 = 100004
15 | DB_ERROR int64 = 100005
16 | DB_UPDATE_AFFECTED_ZERO_ERROR int64 = 100006
17 | SECRET_ERROR int64 = 100007
18 | )
19 |
--------------------------------------------------------------------------------
/common/xerr/errMsg.go:
--------------------------------------------------------------------------------
1 | package xerr
2 |
3 | var message map[int64]string
4 |
5 | func init() {
6 | message = make(map[int64]string)
7 | message[OK] = "SUCCESS"
8 | message[REUQEST_PARAM_ERROR] = "参数错误"
9 | message[TOKEN_EXPIRE_ERROR] = "token失效,请重新登陆"
10 | message[TOKEN_GENERATE_ERROR] = "生成token失败"
11 | message[DB_ERROR] = "数据库繁忙,请稍后再试"
12 | message[SECRET_ERROR] = "密码错误"
13 | }
14 |
15 | func MapErrMsg(errcode int64) string {
16 | if msg, ok := message[errcode]; ok {
17 | return msg
18 | } else {
19 | return "服务器开小差啦,稍后再来试一试"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/common/xerr/errors.go:
--------------------------------------------------------------------------------
1 | package xerr
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | /**
8 | 常用通用固定错误
9 | */
10 |
11 | type CodeError struct {
12 | errCode int64
13 | errMsg string
14 | }
15 |
16 | // GetErrCode 返回给前端的错误码
17 | func (e *CodeError) GetErrCode() int64 {
18 | return e.errCode
19 | }
20 |
21 | // GetErrMsg 返回给前端显示端错误信息
22 | func (e *CodeError) GetErrMsg() string {
23 | return e.errMsg
24 | }
25 |
26 | func (e *CodeError) Error() string {
27 | return fmt.Sprintf("ErrCode:%d,ErrMsg:%s", e.errCode, e.errMsg)
28 | }
29 |
30 | func NewErrCode(errCode int64) *CodeError {
31 | return &CodeError{errCode: errCode, errMsg: MapErrMsg(errCode)}
32 | }
33 |
34 | func NewErrMsg(errMsg string) *CodeError {
35 | return &CodeError{errCode: SERVER_COMMON_ERROR, errMsg: errMsg}
36 | }
37 |
--------------------------------------------------------------------------------
/deployment/cluster/douyin-cluster.yaml:
--------------------------------------------------------------------------------
1 | kind: Cluster
2 | apiVersion: kind.x-k8s.io/v1alpha4
3 | name: douyin
4 | nodes:
5 | - role: control-plane
6 | - role: worker
7 | - role: worker
8 | - role: worker
9 |
--------------------------------------------------------------------------------
/deployment/comment/comment.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | labels:
5 | app: comment
6 | name: comment
7 | namespace: comment
8 | spec:
9 | replicas: 2
10 | selector:
11 | matchLabels:
12 | app: comment
13 | template:
14 | metadata:
15 | labels:
16 | app: comment
17 | spec:
18 | containers:
19 | - name: comment
20 | image: douyin/comment:nightly
21 | imagePullPolicy: Never
22 |
--------------------------------------------------------------------------------
/deployment/dashboard/README.md:
--------------------------------------------------------------------------------
1 | # kubernets dashboard
2 |
3 | ## Install Kubernetes-Dashboard
4 |
5 | ```bash
6 | # Add dashboard repo to your helm
7 | helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/
8 | # Create dashboard namespace
9 | kubectl create ns dashboard
10 | # Install dashboard to the last namespace
11 | helm install kubernetes-dashboard kubernetes-dashboard/kubernetes-dashboard -n dashboard
12 | # Apply role and account config file
13 | kubectl apply -f cluster_role_binding.yaml
14 | kubectl apply -f service_account.yaml
15 | # Get the login token
16 | kubectl -n dashboard create token admin-user > token.txt
17 | ```
18 |
19 | ## Visit Kubernetes-Dashboard
20 |
21 | ```bash
22 | export POD_NAME=$(kubectl get pods \
23 | -n dashboard \
24 | -l "app.kubernetes.io/name=kubernetes-dashboard,app.kubernetes.io/instance=kubernetes-dashboard" \
25 | -o jsonpath="{.items[0].metadata.name}")
26 | echo Visit the dashboard https://127.0.0.1:8443/ by your token:
27 | cat token.txt
28 | kubectl -n dashboard port-forward $POD_NAME 8443:8443
29 | ```
30 |
--------------------------------------------------------------------------------
/deployment/dashboard/cluster_role_binding.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: rbac.authorization.k8s.io/v1
2 | kind: ClusterRoleBinding
3 | metadata:
4 | name: admin-user
5 | roleRef:
6 | apiGroup: rbac.authorization.k8s.io
7 | kind: ClusterRole
8 | name: cluster-admin
9 | subjects:
10 | - kind: ServiceAccount
11 | name: admin-user
12 | namespace: dashboard
--------------------------------------------------------------------------------
/deployment/dashboard/service_account.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: ServiceAccount
3 | metadata:
4 | name: admin-user
5 | namespace: dashboard
--------------------------------------------------------------------------------
/deployment/favorite/favorite.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | labels:
5 | app: favorite
6 | name: favorite
7 | namespace: favorite
8 | spec:
9 | replicas: 2
10 | selector:
11 | matchLabels:
12 | app: favorite
13 | template:
14 | metadata:
15 | labels:
16 | app: favorite
17 | spec:
18 | containers:
19 | - name: favorite
20 | image: douyin/favorite:nightly
21 | imagePullPolicy: Never
22 |
--------------------------------------------------------------------------------
/deployment/follow/follow.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | labels:
5 | app: follow
6 | name: follow
7 | namespace: follow
8 | spec:
9 | replicas: 2
10 | selector:
11 | matchLabels:
12 | app: follow
13 | template:
14 | metadata:
15 | labels:
16 | app: follow
17 | spec:
18 | containers:
19 | - name: follow
20 | image: douyin/follow:nightly
21 | imagePullPolicy: Never
22 |
--------------------------------------------------------------------------------
/deployment/gateway/gateway.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | labels:
5 | app: gateway
6 | name: gateway
7 | namespace: gateway
8 | spec:
9 | ports:
10 | - port: 8888
11 | protocol: TCP
12 | targetPort: 8888
13 | selector:
14 | app: gateway
15 | type: LoadBalancer
16 | ---
17 | apiVersion: apps/v1
18 | kind: Deployment
19 | metadata:
20 | labels:
21 | app: gateway
22 | name: gateway
23 | namespace: gateway
24 | spec:
25 | replicas: 1
26 | selector:
27 | matchLabels:
28 | app: gateway
29 | template:
30 | metadata:
31 | labels:
32 | app: gateway
33 | spec:
34 | containers:
35 | - name: gateway
36 | image: douyin/gateway:nightly
37 | imagePullPolicy: Never
38 | ports:
39 | - containerPort: 8888
40 |
--------------------------------------------------------------------------------
/deployment/message/message.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | labels:
5 | app: message
6 | name: message
7 | namespace: message
8 | spec:
9 | replicas: 2
10 | selector:
11 | matchLabels:
12 | app: message
13 | template:
14 | metadata:
15 | labels:
16 | app: message
17 | spec:
18 | containers:
19 | - name: message
20 | image: douyin/message:nightly
21 | imagePullPolicy: Never
22 |
--------------------------------------------------------------------------------
/deployment/minio-client/minio-client.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | labels:
5 | app: minio-client
6 | name: minio-client
7 | namespace: minio-client
8 | spec:
9 | replicas: 2
10 | selector:
11 | matchLabels:
12 | app: minio-client
13 | template:
14 | metadata:
15 | labels:
16 | app: minio-client
17 | spec:
18 | containers:
19 | - name: minio-client
20 | image: douyin/minio-client:nightly
21 | imagePullPolicy: Never
22 |
--------------------------------------------------------------------------------
/deployment/minio/minio.yaml:
--------------------------------------------------------------------------------
1 | rootUser: "douyin"
2 | rootPassword: "douyin_pass"
3 | replicas: 2
4 | persistence:
5 | size: 10Gi
6 | resources:
7 | requests:
8 | memory: 1Gi
9 | buckets:
10 | - name: douyin
11 | policy: public
12 |
--------------------------------------------------------------------------------
/deployment/mq/mq.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | labels:
5 | app: mq
6 | name: mq
7 | namespace: mq
8 | spec:
9 | replicas: 2
10 | selector:
11 | matchLabels:
12 | app: mq
13 | template:
14 | metadata:
15 | labels:
16 | app: mq
17 | spec:
18 | containers:
19 | - name: mq
20 | image: douyin/mq:nightly
21 | imagePullPolicy: Never
22 |
--------------------------------------------------------------------------------
/deployment/mysql/mysql-deploy.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: service-mysql
5 | labels:
6 | app: mysql
7 | spec:
8 | ports:
9 | - name: mysql
10 | port: 3306
11 | targetPort: 3306
12 | selector:
13 | app: mysql
14 | type: ClusterIP
15 | ---
16 | apiVersion: apps/v1
17 | kind: Deployment
18 | metadata:
19 | name: mysql
20 | spec:
21 | selector:
22 | matchLabels:
23 | app: mysql
24 | strategy:
25 | type: Recreate
26 | template:
27 | metadata:
28 | labels:
29 | app: mysql
30 | spec:
31 | containers:
32 | - name: mysql
33 | image: mysql
34 | env:
35 | - name: MYSQL_ROOT_PASSWORD
36 | value: root
37 | - name: MYSQL_USER
38 | value: titok
39 | - name: MYSQL_PASSWORD
40 | value: titok
41 | ports:
42 | - name: mysql
43 | containerPort: 3306
44 | volumeMounts:
45 | - name: mysql-pv
46 | mountPath: /var/lib/mysql
47 | - name: mysql-initdb
48 | mountPath: /var/lib/mysql
49 | command:
50 | - bash
51 | - "-c"
52 | - |
53 | /entrypoint.sh mysqld &
54 | sleep 30
55 | mysql -u root -p${MYSQL_ROOT_PASSWORD} -e "CREATE USER 'titok'@'%' IDENTIFIED BY 'titok';"
56 | mysql -u root -p${MYSQL_ROOT_PASSWORD} -e "GRANT ALL PRIVILEGES ON *.* TO 'titok'@'%';"
57 | mysql -u root -p${MYSQL_ROOT_PASSWORD} -e "FLUSH PRIVILEGES;"
58 | mysql -u root -p${MYSQL_ROOT_PASSWORD} < /var/lib/mysql/schema.sql
59 | volumes:
60 | - name: mysql-pv
61 | persistentVolumeClaim:
62 | claimName: nfs-pvc
63 | - name: mysql-initdb
64 | configMap:
65 | name: mysql-scheme
66 |
--------------------------------------------------------------------------------
/deployment/nfs/README.md:
--------------------------------------------------------------------------------
1 | # NFS
2 |
3 | ## Why nfs?
4 |
5 | When your pods down... All datas will disappear from there.
6 | Just because you store you all data in this instace rather than presistence volume.
7 |
8 | So we need a `NFS`, a file system for distributed systems... with no more explaination.
9 |
10 | - It can provide the `volume` for backend
11 | - Presistent storage
12 | - Accesss from different `namespcae` or `pods
13 |
14 |
15 | ## nfs-client-provisioner
16 |
17 | >nfs-client-provisioner 是一个Kubernetes的简易NFS的外部provisioner,本身不提供NFS,需要现有的NFS服务器提供存储
18 | >- PV以 ${namespace}-${pvcName}-${pvName}的命名格式提供(在NFS服务器上)
19 | >- PV回收的时候以 archieved-${namespace}-${pvcName}-${pvName} 的命名格式(在NFS服务器上)
20 |
--------------------------------------------------------------------------------
/deployment/nfs/nfs-deploy.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: nfs-server
5 | spec:
6 | ports:
7 | - name: nfs
8 | port: 2049
9 | protocol: TCP
10 | - name: mountd
11 | port: 20048
12 | protocol: TCP
13 | - name: rpcbind
14 | port: 111
15 | protocol: TCP
16 | selector:
17 | app: nfs-server
18 | type: ClusterIP
19 | ---
20 | apiVersion: apps/v1
21 | kind: StatefulSet
22 | metadata:
23 | name: nfs-server
24 | spec:
25 | serviceName: "nfs-server"
26 | replicas: 1
27 | selector:
28 | matchLabels:
29 | app: nfs-server
30 | template:
31 | metadata:
32 | labels:
33 | app: nfs-server
34 | spec:
35 | containers:
36 | - name: nfs-server
37 | image: quay.io/kubernetes_incubator/nfs-server:1.0
38 | ports:
39 | - name: nfs
40 | containerPort: 2049
41 | protocol: TCP
42 | - name: mountd
43 | containerPort: 20048
44 | protocol: TCP
45 | - name: rpcbind
46 | containerPort: 111
47 | protocol: TCP
48 | securityContext:
49 | privileged: true
50 | volumeMounts:
51 | - name: nfs-pv
52 | mountPath: /nfsdata
53 | volumes:
54 | - name: nfs-pv
55 | persistentVolumeClaim:
56 | claimName: nfs-pvc
57 |
--------------------------------------------------------------------------------
/deployment/nfs/nfs-pvx.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: PersistentVolume
3 | metadata:
4 | name: nfs-pv
5 | spec:
6 | capacity:
7 | storage: 2Gi
8 | accessModes:
9 | - ReadWriteMany
10 | nfs:
11 | server: nfs-server
12 | path: "/"
13 | ---
14 | apiVersion: v1
15 | kind: PersistentVolumeClaim
16 | metadata:
17 | name: nfs-pvc
18 | spec:
19 | accessModes:
20 | - ReadWriteMany
21 | resources:
22 | requests:
23 | storage: 2Gi
24 | storageClassName: standard
25 |
--------------------------------------------------------------------------------
/deployment/user/user.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | labels:
5 | app: user
6 | name: user
7 | namespace: user
8 | spec:
9 | replicas: 2
10 | selector:
11 | matchLabels:
12 | app: user
13 | template:
14 | metadata:
15 | labels:
16 | app: user
17 | spec:
18 | containers:
19 | - name: user
20 | image: douyin/user:nightly
21 | imagePullPolicy: Never
22 |
--------------------------------------------------------------------------------
/deployment/video/video.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | labels:
5 | app: video
6 | name: video
7 | namespace: video
8 | spec:
9 | replicas: 2
10 | selector:
11 | matchLabels:
12 | app: video
13 | template:
14 | metadata:
15 | labels:
16 | app: video
17 | spec:
18 | containers:
19 | - name: video
20 | image: douyin/video:nightly
21 | imagePullPolicy: Never
22 |
--------------------------------------------------------------------------------
/docs/Setup.md:
--------------------------------------------------------------------------------
1 | # Deploy this project
2 |
3 | ## 1. Install dependencies
4 | If you use Windows, we recommend that you install dependent software in the virtual machine.
5 | - [Docker](https://www.docker.com/)
6 | - [Kind](https://kind.sigs.k8s.io/)
7 | - [Kubectl](https://kubernetes.io/docs/tasks/tools/)
8 | - [Helm](https://helm.sh/docs/intro/install/)
9 | - [Make](https://www.gnu.org/software/make/#download)
10 |
11 | ## 2. Install the cluster and components
12 | Run this commands in root direction.
13 | #### Install Cluster
14 | ```bash
15 | make install-cluster
16 | ```
17 |
18 | #### Install components which you need
19 | ```bash
20 | make install-minio install-etcd install-kafka install-redis
21 | ```
22 |
23 | ## Install the microservices
24 | ```bash
25 | make install-minio-client install-user install-comment install-mq install-favorite install-video install-message install-follow install-gateway
26 | ```
27 |
28 | ## Optional components
29 | - [Kubernetes-Dashboard](https://github.com/Vacant2333/douyin/blob/main/deployment/dashboard/README.md)
30 |
--------------------------------------------------------------------------------
/docs/design/CodingRules.md:
--------------------------------------------------------------------------------
1 | ## Coding rules
2 |
3 | #### Coding
4 |
5 | Annotations like this one:
6 |
7 | ```go
8 | // The number of videos
9 | var num int64
10 | ```
11 |
12 | #### Designing
13 |
14 | RPC Port:`30001`
15 | API Port:`30002`
16 | Dockerfile builder image: `golang:latest`
17 | Dockerfile running image: `gcr.io/distroless/static-debian11:latest`
18 |
--------------------------------------------------------------------------------
/pkg/comment/etc/usercomment.yaml:
--------------------------------------------------------------------------------
1 | Name: usercomment.rpc
2 | ListenOn: 0.0.0.0:8083
3 | Mode: dev
4 | Etcd:
5 | Hosts:
6 | - etcd.etcd.svc.cluster.local:2379
7 | Key: usercomment.rpc
8 | DB:
9 | DataSource: douyin:Z4eEXbWWCApby8dE@tcp(bt.vacant.zone:3306)/douyin?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai
10 | CacheConf:
11 | - Host: redis-master.redis.svc.cluster.local:6379
12 | Pass: redispwd123
13 | VideoRPC:
14 | Etcd:
15 | Hosts:
16 | - etcd.etcd.svc.cluster.local:2379
17 | Key: video.rpc
18 |
--------------------------------------------------------------------------------
/pkg/comment/internal/config/config.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import (
4 | "github.com/zeromicro/go-zero/core/stores/cache"
5 | "github.com/zeromicro/go-zero/zrpc"
6 | )
7 |
8 | type Config struct {
9 | zrpc.RpcServerConf
10 | DB struct {
11 | DataSource string
12 | }
13 | CacheConf cache.CacheConf
14 | VideoRPC zrpc.RpcClientConf
15 | }
16 |
--------------------------------------------------------------------------------
/pkg/comment/internal/logic/getvideocommentlogic.go:
--------------------------------------------------------------------------------
1 | package logic
2 |
3 | import (
4 | "context"
5 | "douyin/pkg/comment/internal/svc"
6 | "douyin/pkg/comment/userCommentPb"
7 | "fmt"
8 | "github.com/zeromicro/go-zero/core/logx"
9 | )
10 |
11 | type GetVideoCommentLogic struct {
12 | ctx context.Context
13 | svcCtx *svc.ServiceContext
14 | logx.Logger
15 | }
16 |
17 | func NewGetVideoCommentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetVideoCommentLogic {
18 | return &GetVideoCommentLogic{
19 | ctx: ctx,
20 | svcCtx: svcCtx,
21 | Logger: logx.WithContext(ctx),
22 | }
23 | }
24 |
25 | // GetVideoComment -----------------------userCommentList-----------------------
26 | func (l *GetVideoCommentLogic) GetVideoComment(in *userCommentPb.GetVideoCommentReq) (*userCommentPb.GetVideoCommentReqResp, error) {
27 | fmt.Printf(":::::::::::::::::::::::::::::::::::::::::::::::")
28 | allCommentInfoData, err := l.svcCtx.UserCommentModel.FindAll(l.ctx, in.VideoId)
29 |
30 | if err != nil {
31 | logx.Errorf("GetCommentList------->SELECT err : %s", err.Error())
32 | return &userCommentPb.GetVideoCommentReqResp{}, err
33 | }
34 |
35 | var commentList []*userCommentPb.Comment
36 | for _, v := range allCommentInfoData {
37 | var comment userCommentPb.Comment
38 | comment.CommentId = v.Id
39 | comment.Content = v.Content
40 | comment.CreateDate = v.CreateTime.String()
41 | comment.UserId = v.UserId
42 |
43 | commentList = append(commentList, &comment)
44 | }
45 |
46 | return &userCommentPb.GetVideoCommentReqResp{
47 | CommentList: commentList,
48 | }, nil
49 | }
50 |
--------------------------------------------------------------------------------
/pkg/comment/internal/server/usercommentserver.go:
--------------------------------------------------------------------------------
1 | // Code generated by goctl. DO NOT EDIT.
2 | // Source: UserComment.proto
3 |
4 | package server
5 |
6 | import (
7 | "context"
8 | logic2 "douyin/pkg/comment/internal/logic"
9 | "douyin/pkg/comment/internal/svc"
10 | userCommentPb2 "douyin/pkg/comment/userCommentPb"
11 | )
12 |
13 | type UserCommentServer struct {
14 | svcCtx *svc.ServiceContext
15 | userCommentPb2.UnimplementedUserCommentServer
16 | }
17 |
18 | func NewUserCommentServer(svcCtx *svc.ServiceContext) *UserCommentServer {
19 | return &UserCommentServer{
20 | svcCtx: svcCtx,
21 | }
22 | }
23 |
24 | // -----------------------userCommentStatus-----------------------
25 | func (s *UserCommentServer) UpdateCommentStatus(ctx context.Context, in *userCommentPb2.UpdateCommentStatusReq) (*userCommentPb2.UpdateCommentStatusResp, error) {
26 | l := logic2.NewUpdateCommentStatusLogic(ctx, s.svcCtx)
27 | return l.UpdateCommentStatus(in)
28 | }
29 |
30 | // -----------------------userCommentList-----------------------
31 | func (s *UserCommentServer) GetVideoComment(ctx context.Context, in *userCommentPb2.GetVideoCommentReq) (*userCommentPb2.GetVideoCommentReqResp, error) {
32 | l := logic2.NewGetVideoCommentLogic(ctx, s.svcCtx)
33 | return l.GetVideoComment(in)
34 | }
35 |
--------------------------------------------------------------------------------
/pkg/comment/internal/svc/servicecontext.go:
--------------------------------------------------------------------------------
1 | package svc
2 |
3 | import (
4 | "douyin/common/model/commentModel"
5 | "douyin/pkg/comment/internal/config"
6 | "douyin/pkg/video/videoservice"
7 | "github.com/zeromicro/go-zero/core/stores/sqlx"
8 | "github.com/zeromicro/go-zero/zrpc"
9 | )
10 |
11 | type ServiceContext struct {
12 | Config config.Config
13 | UserCommentModel commentModel.CommentModel
14 | VideoRPC videoservice.VideoService
15 | }
16 |
17 | func NewServiceContext(c config.Config) *ServiceContext {
18 | return &ServiceContext{
19 | Config: c,
20 | UserCommentModel: commentModel.NewCommentModel(sqlx.NewMysql(c.DB.DataSource), c.CacheConf),
21 | VideoRPC: videoservice.NewVideoService(zrpc.MustNewClient(c.VideoRPC)),
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/pkg/comment/readme.md:
--------------------------------------------------------------------------------
1 | goctl model mysql datasource -url="user:password@tcp(127.0.0.1:3306)/database" -table="*" -dir="./model" goctl model mysql datasource -url="user:password@tcp(127.0.0.1:3306)/database" -table="*" -dir="./model"
2 |
3 | kubectl apply -f auth.yaml
4 |
5 | kubectl get sa -n douyin-comment
6 |
7 | goctl docker -go .\usercomment.go .
8 |
9 | docker build -t douyin-comment-api:v1 .
10 |
11 | kind create cluster --image kindest/node:v1.25.3 --config deployment/cluster/douyin-cluster.yaml
12 |
13 |
14 | # 创建命名空间
15 | kubectl create namespace douyin-comment
16 |
17 | kind create cluster --config deployment/cluster/douyin-cluster.yaml
18 |
19 | goctl kube deploy -replicas 2 -requestCpu 200 -requestMem 50 -limitCpu 300 -limitMem 100 -name comment-rpc-svc -namespace douyin-comment -i
20 | mage douyin-comment-rpc:v1 -o douyin-comment-rpc.yaml -port 8081 --serviceAccount find-endpoints
21 |
22 | goctl kube deploy -nodePort 32010 -replicas 2 -requestCpu 200 -requestMem 50 -limitCpu 300 -limitMem 100 -name douyin-api-svc -namespace do
23 | uyin-comment -image douyin-comment-api:v1 -o douyin-comment-api.yaml -port 8888 --serviceAccount find-endpoints
24 |
25 |
26 | kubectl apply -f .\douyin-comment-rpc.yaml
27 | kubectl apply -f .\douyin-comment-api.yaml
28 |
29 | kind load docker-image douyin-comment-rpc:v1 --name douyin
30 | kind load docker-image douyin-comment-api:v1 --name douyin
31 |
32 |
33 |
--------------------------------------------------------------------------------
/pkg/comment/userCommentPb/GenPb/UserComment.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | option go_package ="./userCommentPb";
4 |
5 | package pb;
6 |
7 | // ------------------------------------
8 | // Messages
9 | // ------------------------------------
10 |
11 | // 用户对视频评论
12 | message UpdateCommentStatusReq {
13 | int64 videoId = 1; //videoId
14 | int64 userId = 2; //userId
15 | int64 commentId = 3; //commentId
16 | string Content = 4;
17 | int64 actionType = 5; //评论 取消评论
18 | }
19 |
20 | message UpdateCommentStatusResp {
21 | int64 commentId = 3; //commentId
22 | }
23 |
24 | // 获得视频的评论列表
25 | message GetVideoCommentReq {
26 | int64 videoId = 1; //video_id
27 | }
28 | message Comment {
29 | int64 commentId = 1;
30 | int64 userId = 2;
31 | string content = 3;
32 | string createDate = 4;
33 | }
34 |
35 | message GetVideoCommentReqResp {
36 | repeated Comment commentList = 1;//comment_list
37 | }
38 |
39 | // ------------------------------------
40 | // Rpc Func
41 | // ------------------------------------
42 |
43 | service UserComment{
44 | //-----------------------userCommentStatus-----------------------
45 | rpc UpdateCommentStatus(UpdateCommentStatusReq) returns (UpdateCommentStatusResp);
46 | //-----------------------userCommentList-----------------------
47 | rpc GetVideoComment(GetVideoCommentReq) returns (GetVideoCommentReqResp);
48 | }
49 |
--------------------------------------------------------------------------------
/pkg/comment/userCommentPb/GenPb/build.sh:
--------------------------------------------------------------------------------
1 | goctl rpc protoc UserCommentService.proto --go_out=../../ --go-grpc_out=../../ --zrpc_out=../../ --style=goZero --home=../../../../tpl
2 | # 当有多个proto文件时 需要先生成其他的文件 再生成主要的pb文件
3 |
4 |
5 | goctl rpc protoc UserComment.proto --go_out=../../ --go-grpc_out=../../ --zrpc_out=../../
6 |
--------------------------------------------------------------------------------
/pkg/comment/usercomment.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "douyin/pkg/comment/internal/config"
5 | "douyin/pkg/comment/internal/server"
6 | "douyin/pkg/comment/internal/svc"
7 | "douyin/pkg/comment/userCommentPb"
8 | "flag"
9 | "fmt"
10 |
11 | "github.com/zeromicro/go-zero/core/conf"
12 | "github.com/zeromicro/go-zero/core/service"
13 | "github.com/zeromicro/go-zero/zrpc"
14 | "google.golang.org/grpc"
15 | "google.golang.org/grpc/reflection"
16 | )
17 |
18 | var configFile = flag.String("f", "etc/usercomment.yaml", "the config file")
19 |
20 | func main() {
21 | flag.Parse()
22 |
23 | var c config.Config
24 | conf.MustLoad(*configFile, &c)
25 | ctx := svc.NewServiceContext(c)
26 |
27 | s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
28 | userCommentPb.RegisterUserCommentServer(grpcServer, server.NewUserCommentServer(ctx))
29 |
30 | if c.Mode == service.DevMode || c.Mode == service.TestMode {
31 | reflection.Register(grpcServer)
32 | }
33 | })
34 | defer s.Stop()
35 |
36 | fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
37 | s.Start()
38 | }
39 |
--------------------------------------------------------------------------------
/pkg/comment/usercomment/usercomment.go:
--------------------------------------------------------------------------------
1 | // Code generated by goctl. DO NOT EDIT.
2 | // Source: UserComment.proto
3 |
4 | package usercomment
5 |
6 | import (
7 | "context"
8 | userCommentPb2 "douyin/pkg/comment/userCommentPb"
9 |
10 | "github.com/zeromicro/go-zero/zrpc"
11 | "google.golang.org/grpc"
12 | )
13 |
14 | type (
15 | Comment = userCommentPb2.Comment
16 | GetVideoCommentReq = userCommentPb2.GetVideoCommentReq
17 | GetVideoCommentReqResp = userCommentPb2.GetVideoCommentReqResp
18 | UpdateCommentStatusReq = userCommentPb2.UpdateCommentStatusReq
19 | UpdateCommentStatusResp = userCommentPb2.UpdateCommentStatusResp
20 |
21 | UserComment interface {
22 | // -----------------------userCommentStatus-----------------------
23 | UpdateCommentStatus(ctx context.Context, in *UpdateCommentStatusReq, opts ...grpc.CallOption) (*UpdateCommentStatusResp, error)
24 | // -----------------------userCommentList-----------------------
25 | GetVideoComment(ctx context.Context, in *GetVideoCommentReq, opts ...grpc.CallOption) (*GetVideoCommentReqResp, error)
26 | }
27 |
28 | defaultUserComment struct {
29 | cli zrpc.Client
30 | }
31 | )
32 |
33 | func NewUserComment(cli zrpc.Client) UserComment {
34 | return &defaultUserComment{
35 | cli: cli,
36 | }
37 | }
38 |
39 | // -----------------------userCommentStatus-----------------------
40 | func (m *defaultUserComment) UpdateCommentStatus(ctx context.Context, in *UpdateCommentStatusReq, opts ...grpc.CallOption) (*UpdateCommentStatusResp, error) {
41 | client := userCommentPb2.NewUserCommentClient(m.cli.Conn())
42 | return client.UpdateCommentStatus(ctx, in, opts...)
43 | }
44 |
45 | // -----------------------userCommentList-----------------------
46 | func (m *defaultUserComment) GetVideoComment(ctx context.Context, in *GetVideoCommentReq, opts ...grpc.CallOption) (*GetVideoCommentReqResp, error) {
47 | client := userCommentPb2.NewUserCommentClient(m.cli.Conn())
48 | return client.GetVideoComment(ctx, in, opts...)
49 | }
50 |
--------------------------------------------------------------------------------
/pkg/constant/mysql.go:
--------------------------------------------------------------------------------
1 | package constantx
2 |
3 | const (
4 | MYSQL_Dsn string = "titok:titok@tcp(127.0.0.1:3306)/titok?charset=utf8mb4&parseTime=True&loc=Local"
5 | )
6 |
7 | // config
8 | const (
9 | MYSQL_SkipDefaultTransaction bool = true // close default tx
10 | MYSQL_PrepareStmt bool = true // cache precompile sentence
11 | )
12 |
--------------------------------------------------------------------------------
/pkg/favorite/etc/userOptService.yaml:
--------------------------------------------------------------------------------
1 | Name: useropt.rpc
2 | ListenOn: 0.0.0.0:8081
3 | Mode: dev
4 | Etcd:
5 | Hosts:
6 | - etcd.etcd.svc.cluster.local:2379
7 | Key: useropt.rpc
8 | DB:
9 | DataSource: douyin:Z4eEXbWWCApby8dE@tcp(bt.vacant.zone:3306)/douyin?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai
10 | CacheRedis:
11 | - Host: redis-master.redis.svc.cluster.local:6379
12 | Pass: redispwd123
13 | VideoRPC:
14 | Etcd:
15 | Hosts:
16 | - etcd.etcd.svc.cluster.local:2379
17 | Key: video.rpc
18 |
--------------------------------------------------------------------------------
/pkg/favorite/internal/config/config.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import (
4 | "github.com/zeromicro/go-zero/core/stores/cache"
5 | "github.com/zeromicro/go-zero/zrpc"
6 | )
7 |
8 | type Config struct {
9 | zrpc.RpcServerConf
10 |
11 | DB struct {
12 | DataSource string
13 | }
14 | CacheRedis cache.CacheConf
15 | VideoRPC zrpc.RpcClientConf
16 | }
17 |
--------------------------------------------------------------------------------
/pkg/favorite/internal/logic/checkIsFavoriteLogic.go:
--------------------------------------------------------------------------------
1 | package logic
2 |
3 | import (
4 | "context"
5 | "douyin/pkg/logger"
6 |
7 | "douyin/pkg/favorite/internal/svc"
8 | "douyin/pkg/favorite/userOptPb"
9 |
10 | "github.com/zeromicro/go-zero/core/logx"
11 | )
12 |
13 | type CheckIsFavoriteLogic struct {
14 | ctx context.Context
15 | svcCtx *svc.ServiceContext
16 | logx.Logger
17 | }
18 |
19 | func NewCheckIsFavoriteLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CheckIsFavoriteLogic {
20 | return &CheckIsFavoriteLogic{
21 | ctx: ctx,
22 | svcCtx: svcCtx,
23 | Logger: logx.WithContext(ctx),
24 | }
25 | }
26 |
27 | func (l *CheckIsFavoriteLogic) CheckIsFavorite(in *userOptPb.CheckIsFavoriteReq) (*userOptPb.CheckIsFavoriteResp, error) {
28 | result, err := l.svcCtx.UserFavoriteModel.CheckIsFavorite(l.ctx, in.UserId, in.VideoId)
29 | if err != nil {
30 | logger.Error("CheckIsFavorite查询错误", err)
31 | return nil, err
32 | }
33 | return &userOptPb.CheckIsFavoriteResp{IsFavorite: result}, nil
34 | }
35 |
--------------------------------------------------------------------------------
/pkg/favorite/internal/logic/getUserFavoriteLogic.go:
--------------------------------------------------------------------------------
1 | package logic
2 |
3 | import (
4 | "context"
5 | "douyin/pkg/favorite/internal/svc"
6 | "douyin/pkg/favorite/userOptPb"
7 | "fmt"
8 |
9 | "github.com/zeromicro/go-zero/core/logx"
10 | )
11 |
12 | type GetUserFavoriteLogic struct {
13 | ctx context.Context
14 | svcCtx *svc.ServiceContext
15 | logx.Logger
16 | }
17 |
18 | func NewGetUserFavoriteLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserFavoriteLogic {
19 | return &GetUserFavoriteLogic{
20 | ctx: ctx,
21 | svcCtx: svcCtx,
22 | Logger: logx.WithContext(ctx),
23 | }
24 | }
25 |
26 | // -----------------------userFavoriteList-----------------------
27 | func (l *GetUserFavoriteLogic) GetUserFavorite(in *userOptPb.GetUserFavoriteReq) (*userOptPb.GetUserFavoriteResp, error) {
28 | fmt.Printf("GetVideoFavorite-------------->")
29 |
30 | allFavoriteInfoData, err := l.svcCtx.UserFavoriteModel.FindAll(l.ctx, in.UserId)
31 | if err != nil {
32 | logx.Errorf("GetFavoriteList------->SELECT err : %s", err.Error())
33 | return &userOptPb.GetUserFavoriteResp{}, err
34 | }
35 | var favoriteList []*userOptPb.Favorite
36 | for _, v := range allFavoriteInfoData {
37 | var favorite userOptPb.Favorite
38 | videoInfoData, err := l.svcCtx.UserVideoModel.FindOne(l.ctx, v.VideoId)
39 | if err != nil {
40 | logx.Errorf("GetFavoriteList------->SELECT err : %s", err.Error())
41 | return &userOptPb.GetUserFavoriteResp{}, err
42 | }
43 | favorite.UserId = v.UserId
44 | favorite.PlayUrl = videoInfoData.PlayUrl
45 | favorite.Title = videoInfoData.Title
46 | favorite.VideoId = videoInfoData.Id
47 | favorite.CoverUrl = videoInfoData.CoverUrl
48 | favorite.AuthorId = videoInfoData.AuthorId
49 |
50 | favoriteList = append(favoriteList, &favorite)
51 | }
52 | return &userOptPb.GetUserFavoriteResp{
53 | FavoriteList: favoriteList,
54 | }, nil
55 | }
56 |
--------------------------------------------------------------------------------
/pkg/favorite/internal/server/userOptServiceServer.go:
--------------------------------------------------------------------------------
1 | // Code generated by goctl. DO NOT EDIT.
2 | // Source: UserOptService.proto
3 |
4 | package server
5 |
6 | import (
7 | "context"
8 | logic2 "douyin/pkg/favorite/internal/logic"
9 | "douyin/pkg/favorite/internal/svc"
10 | userOptPb2 "douyin/pkg/favorite/userOptPb"
11 | )
12 |
13 | type UserOptServiceServer struct {
14 | svcCtx *svc.ServiceContext
15 | userOptPb2.UnimplementedUserOptServiceServer
16 | }
17 |
18 | func NewUserOptServiceServer(svcCtx *svc.ServiceContext) *UserOptServiceServer {
19 | return &UserOptServiceServer{
20 | svcCtx: svcCtx,
21 | }
22 | }
23 |
24 | // -----------------------userFavoriteList-----------------------
25 | func (s *UserOptServiceServer) GetUserFavorite(ctx context.Context, in *userOptPb2.GetUserFavoriteReq) (*userOptPb2.GetUserFavoriteResp, error) {
26 | l := logic2.NewGetUserFavoriteLogic(ctx, s.svcCtx)
27 | return l.GetUserFavorite(in)
28 | }
29 |
30 | func (s *UserOptServiceServer) UpdateFavoriteStatus(ctx context.Context, in *userOptPb2.UpdateFavoriteStatusReq) (*userOptPb2.UpdateFavoriteStatusResp, error) {
31 | l := logic2.NewUpdateFavoriteStatusLogic(ctx, s.svcCtx)
32 | return l.UpdateFavoriteStatus(in)
33 | }
34 |
35 | func (s *UserOptServiceServer) CheckIsFavorite(ctx context.Context, in *userOptPb2.CheckIsFavoriteReq) (*userOptPb2.CheckIsFavoriteResp, error) {
36 | l := logic2.NewCheckIsFavoriteLogic(ctx, s.svcCtx)
37 | return l.CheckIsFavorite(in)
38 | }
39 |
--------------------------------------------------------------------------------
/pkg/favorite/internal/svc/serviceContext.go:
--------------------------------------------------------------------------------
1 | package svc
2 |
3 | import (
4 | "douyin/common/model/favoriteModel"
5 | "douyin/common/model/videoModel"
6 | "douyin/pkg/favorite/internal/config"
7 | "github.com/zeromicro/go-zero/core/stores/sqlx"
8 | )
9 |
10 | type ServiceContext struct {
11 | Config config.Config
12 | UserFavoriteModel favoriteModel.FavoriteModel
13 | UserVideoModel videoModel.VideoModel
14 | VideoModel videoModel.VideoModel
15 | }
16 |
17 | func NewServiceContext(c config.Config) *ServiceContext {
18 | return &ServiceContext{
19 | Config: c,
20 | UserFavoriteModel: favoriteModel.NewFavoriteModel(sqlx.NewMysql(c.DB.DataSource)),
21 | UserVideoModel: videoModel.NewVideoModel(sqlx.NewMysql(c.DB.DataSource), c.CacheRedis),
22 | VideoModel: videoModel.NewVideoModel(sqlx.NewMysql(c.DB.DataSource), c.CacheRedis),
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/pkg/favorite/userOptPb/GenPb/UserOptService.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | option go_package ="./userOptPb";
4 |
5 | package pb;
6 |
7 | // ------------------------------------
8 | // Messages
9 | // ------------------------------------
10 |
11 | //--------------------------------userFavoriteList--------------------------------
12 |
13 | // 用户给视频点赞
14 | message UpdateFavoriteStatusReq {
15 | int64 videoId = 1; //videoId
16 | int64 userId = 2; //userId
17 | int64 actionType = 3; //点赞
18 | }
19 |
20 | message UpdateFavoriteStatusResp {
21 | }
22 |
23 | // 获得用户和视频的点赞关系
24 | message GetUserFavoriteReq {
25 | int64 userId = 1; //userId
26 | }
27 |
28 | message Favorite{
29 | int64 videoId = 1;//videoId
30 | string play_url = 2;
31 | string cover_url = 3;
32 | string title = 4;
33 | int64 author_id = 5;
34 | int64 user_id=6;
35 | }
36 |
37 | message GetUserFavoriteResp {
38 | repeated Favorite FavoriteList = 1; //userFavoriteList
39 |
40 | }
41 |
42 | message CheckIsFavoriteReq {
43 | int64 userId=1;
44 | int64 videoId=2;
45 | }
46 |
47 | message CheckIsFavoriteResp {
48 | bool isFavorite=1;
49 | }
50 |
51 | // ------------------------------------
52 | // Rpc Func
53 | // ------------------------------------
54 |
55 | service UserOptService{
56 | //-----------------------userFavoriteList-----------------------
57 | rpc GetUserFavorite(GetUserFavoriteReq) returns (GetUserFavoriteResp);
58 | rpc UpdateFavoriteStatus(UpdateFavoriteStatusReq) returns (UpdateFavoriteStatusResp);
59 | rpc CheckIsFavorite(CheckIsFavoriteReq) returns (CheckIsFavoriteResp);
60 | }
61 |
--------------------------------------------------------------------------------
/pkg/favorite/userOptPb/GenPb/build.sh:
--------------------------------------------------------------------------------
1 | goctl rpc protoc UserOptService.proto --go_out=../../ --go-grpc_out=../../ --zrpc_out=../../ --style=goZero --home=../../../../tpl
2 | # 当有多个proto文件时 需要先生成其他的文件 再生成主要的pb文件
--------------------------------------------------------------------------------
/pkg/favorite/userOptService.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "douyin/pkg/favorite/internal/config"
5 | "douyin/pkg/favorite/internal/server"
6 | "douyin/pkg/favorite/internal/svc"
7 | "douyin/pkg/favorite/userOptPb"
8 | "flag"
9 | "fmt"
10 |
11 | "github.com/zeromicro/go-zero/core/conf"
12 | "github.com/zeromicro/go-zero/core/service"
13 | "github.com/zeromicro/go-zero/zrpc"
14 | "google.golang.org/grpc"
15 | "google.golang.org/grpc/reflection"
16 | )
17 |
18 | var configFile = flag.String("f", "etc/userOptService.yaml", "the config file")
19 |
20 | func main() {
21 | flag.Parse()
22 |
23 | var c config.Config
24 | conf.MustLoad(*configFile, &c)
25 | ctx := svc.NewServiceContext(c)
26 |
27 | s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
28 | userOptPb.RegisterUserOptServiceServer(grpcServer, server.NewUserOptServiceServer(ctx))
29 |
30 | if c.Mode == service.DevMode || c.Mode == service.TestMode {
31 | reflection.Register(grpcServer)
32 | }
33 | })
34 | defer s.Stop()
35 |
36 | fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
37 | s.Start()
38 | }
39 |
--------------------------------------------------------------------------------
/pkg/favorite/useroptservice/userOptService.go:
--------------------------------------------------------------------------------
1 | // Code generated by goctl. DO NOT EDIT.
2 | // Source: UserOptService.proto
3 |
4 | package useroptservice
5 |
6 | import (
7 | "context"
8 |
9 | "douyin/pkg/favorite/userOptPb"
10 |
11 | "github.com/zeromicro/go-zero/zrpc"
12 | "google.golang.org/grpc"
13 | )
14 |
15 | type (
16 | CheckIsFavoriteReq = userOptPb.CheckIsFavoriteReq
17 | CheckIsFavoriteResp = userOptPb.CheckIsFavoriteResp
18 | Favorite = userOptPb.Favorite
19 | GetUserFavoriteReq = userOptPb.GetUserFavoriteReq
20 | GetUserFavoriteResp = userOptPb.GetUserFavoriteResp
21 | UpdateFavoriteStatusReq = userOptPb.UpdateFavoriteStatusReq
22 | UpdateFavoriteStatusResp = userOptPb.UpdateFavoriteStatusResp
23 |
24 | UserOptService interface {
25 | // -----------------------userFavoriteList-----------------------
26 | GetUserFavorite(ctx context.Context, in *GetUserFavoriteReq, opts ...grpc.CallOption) (*GetUserFavoriteResp, error)
27 | UpdateFavoriteStatus(ctx context.Context, in *UpdateFavoriteStatusReq, opts ...grpc.CallOption) (*UpdateFavoriteStatusResp, error)
28 | CheckIsFavorite(ctx context.Context, in *CheckIsFavoriteReq, opts ...grpc.CallOption) (*CheckIsFavoriteResp, error)
29 | }
30 |
31 | defaultUserOptService struct {
32 | cli zrpc.Client
33 | }
34 | )
35 |
36 | func NewUserOptService(cli zrpc.Client) UserOptService {
37 | return &defaultUserOptService{
38 | cli: cli,
39 | }
40 | }
41 |
42 | // -----------------------userFavoriteList-----------------------
43 | func (m *defaultUserOptService) GetUserFavorite(ctx context.Context, in *GetUserFavoriteReq, opts ...grpc.CallOption) (*GetUserFavoriteResp, error) {
44 | client := userOptPb.NewUserOptServiceClient(m.cli.Conn())
45 | return client.GetUserFavorite(ctx, in, opts...)
46 | }
47 |
48 | func (m *defaultUserOptService) UpdateFavoriteStatus(ctx context.Context, in *UpdateFavoriteStatusReq, opts ...grpc.CallOption) (*UpdateFavoriteStatusResp, error) {
49 | client := userOptPb.NewUserOptServiceClient(m.cli.Conn())
50 | return client.UpdateFavoriteStatus(ctx, in, opts...)
51 | }
52 |
53 | func (m *defaultUserOptService) CheckIsFavorite(ctx context.Context, in *CheckIsFavoriteReq, opts ...grpc.CallOption) (*CheckIsFavoriteResp, error) {
54 | client := userOptPb.NewUserOptServiceClient(m.cli.Conn())
55 | return client.CheckIsFavorite(ctx, in, opts...)
56 | }
57 |
--------------------------------------------------------------------------------
/pkg/follow/etc/follow.yaml:
--------------------------------------------------------------------------------
1 | Name: follow.rpc
2 | ListenOn: 0.0.0.0:8082
3 | Etcd:
4 | Hosts:
5 | - etcd.etcd.svc.cluster.local:2379
6 | Key: follow.rpc
7 | Mysql:
8 | DataSource: douyin:Z4eEXbWWCApby8dE@tcp(bt.vacant.zone:3306)/douyin?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai
9 | CacheRedis:
10 | - Host: redis-master.redis.svc.cluster.local:6379
11 | Pass: redispwd123
12 | UserRPC:
13 | Etcd:
14 | Hosts:
15 | - etcd.etcd.svc.cluster.local:2379
16 | Key: user.rpc
17 |
--------------------------------------------------------------------------------
/pkg/follow/follow.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "douyin/pkg/follow/internal/config"
5 | "douyin/pkg/follow/internal/server"
6 | "douyin/pkg/follow/internal/svc"
7 | "douyin/pkg/follow/types/follow"
8 | "flag"
9 | "fmt"
10 |
11 | "github.com/zeromicro/go-zero/core/conf"
12 | "github.com/zeromicro/go-zero/core/service"
13 | "github.com/zeromicro/go-zero/zrpc"
14 | "google.golang.org/grpc"
15 | "google.golang.org/grpc/reflection"
16 | )
17 |
18 | var configFile = flag.String("f", "etc/follow.yaml", "the config file")
19 |
20 | func main() {
21 | flag.Parse()
22 |
23 | var c config.Config
24 | conf.MustLoad(*configFile, &c)
25 | ctx := svc.NewServiceContext(c)
26 |
27 | s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
28 | follow.RegisterFollowServiceServer(grpcServer, server.NewFollowServiceServer(ctx))
29 |
30 | if c.Mode == service.DevMode || c.Mode == service.TestMode {
31 | reflection.Register(grpcServer)
32 | }
33 | })
34 | defer s.Stop()
35 |
36 | fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
37 | s.Start()
38 | }
39 |
--------------------------------------------------------------------------------
/pkg/follow/internal/config/config.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import (
4 | "github.com/zeromicro/go-zero/core/stores/cache"
5 | "github.com/zeromicro/go-zero/zrpc"
6 | )
7 |
8 | type Config struct {
9 | zrpc.RpcServerConf
10 | UserRPC zrpc.RpcClientConf
11 | Mysql struct {
12 | DataSource string
13 | }
14 | CacheRedis cache.CacheConf
15 | }
16 |
--------------------------------------------------------------------------------
/pkg/follow/internal/logic/checkisfollowlogic.go:
--------------------------------------------------------------------------------
1 | package logic
2 |
3 | import (
4 | "context"
5 |
6 | "douyin/pkg/follow/internal/svc"
7 | "douyin/pkg/follow/types/follow"
8 |
9 | "github.com/zeromicro/go-zero/core/logx"
10 | )
11 |
12 | type CheckIsFollowLogic struct {
13 | ctx context.Context
14 | svcCtx *svc.ServiceContext
15 | logx.Logger
16 | }
17 |
18 | func NewCheckIsFollowLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CheckIsFollowLogic {
19 | return &CheckIsFollowLogic{
20 | ctx: ctx,
21 | svcCtx: svcCtx,
22 | Logger: logx.WithContext(ctx),
23 | }
24 | }
25 |
26 | func (l *CheckIsFollowLogic) CheckIsFollow(in *follow.CheckIsFollowReq) (*follow.CheckIsFollowResp, error) {
27 | isFollow, err := l.svcCtx.FollowModel.CheckIsFollow(l.ctx, in.UserId, in.FunId)
28 | if err != nil {
29 | logx.Errorf("query is follow failed: %v", err.Error())
30 | return nil, err
31 | }
32 | return &follow.CheckIsFollowResp{
33 | StatusCode: 0,
34 | StatusMsg: "success",
35 | IsFollow: isFollow,
36 | }, nil
37 | }
38 |
--------------------------------------------------------------------------------
/pkg/follow/internal/logic/followlogic.go:
--------------------------------------------------------------------------------
1 | package logic
2 |
3 | import (
4 | "context"
5 | "database/sql"
6 | "douyin/common/model/followModel"
7 | "douyin/pkg/follow/internal/svc"
8 | "douyin/pkg/follow/types/follow"
9 | "douyin/pkg/logger"
10 | "github.com/zeromicro/go-zero/core/logx"
11 | )
12 |
13 | type FollowLogic struct {
14 | ctx context.Context
15 | svcCtx *svc.ServiceContext
16 | logx.Logger
17 | }
18 |
19 | func NewFollowLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FollowLogic {
20 | return &FollowLogic{
21 | ctx: ctx,
22 | svcCtx: svcCtx,
23 | Logger: logx.WithContext(ctx),
24 | }
25 | }
26 |
27 | func (l *FollowLogic) Follow(in *follow.FollowReq) (*follow.FollowResp, error) {
28 | followId, _ := l.svcCtx.FollowModel.FindIfExist(l.ctx, in.ToUserId, in.UserId)
29 |
30 | if followId != 0 {
31 | var removed int64
32 | if in.ActionType == 2 {
33 | removed = 1
34 | }
35 | // 查询到了followId,调用update更新
36 | newFollowModel := &followModel.Follow{
37 | Id: followId,
38 | Removed: removed,
39 | }
40 | err := l.svcCtx.FollowModel.Update(l.ctx, newFollowModel)
41 | if err != nil {
42 | logger.Errorf("follow option failed: %v", err.Error())
43 | return &follow.FollowResp{
44 | StatusCode: -1,
45 | StatusMsg: "follow option failed",
46 | }, err
47 | }
48 | } else {
49 | // 未查询到相关数据,直接insert
50 | if in.ActionType == 1 {
51 | newFollowModel := &followModel.Follow{
52 | UserId: sql.NullInt64{
53 | Int64: in.ToUserId,
54 | Valid: true,
55 | },
56 | FunId: in.UserId,
57 | }
58 | _, err := l.svcCtx.FollowModel.Insert(l.ctx, newFollowModel)
59 | if err != nil {
60 | return &follow.FollowResp{
61 | StatusCode: -1,
62 | StatusMsg: "follow option failed",
63 | }, err
64 | }
65 | }
66 | }
67 |
68 | return &follow.FollowResp{
69 | StatusCode: 0,
70 | StatusMsg: "success",
71 | }, nil
72 | }
73 |
--------------------------------------------------------------------------------
/pkg/follow/internal/logic/getfollowlistlogic.go:
--------------------------------------------------------------------------------
1 | package logic
2 |
3 | import (
4 | "context"
5 | "douyin/pkg/follow/internal/svc"
6 | "douyin/pkg/follow/types/follow"
7 | "douyin/pkg/user/userservice"
8 | "sync"
9 |
10 | "github.com/zeromicro/go-zero/core/logx"
11 | )
12 |
13 | type GetFollowListLogic struct {
14 | ctx context.Context
15 | svcCtx *svc.ServiceContext
16 | logx.Logger
17 | }
18 |
19 | func NewGetFollowListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetFollowListLogic {
20 | return &GetFollowListLogic{
21 | ctx: ctx,
22 | svcCtx: svcCtx,
23 | Logger: logx.WithContext(ctx),
24 | }
25 | }
26 |
27 | func (l *GetFollowListLogic) GetFollowList(in *follow.GetFollowListReq) (*follow.GetFollowListResp, error) {
28 | queryFollow, err := l.svcCtx.FollowModel.FindAllByFunId(l.ctx, in.UserId)
29 | if err != nil {
30 | logx.Errorf("get follow list failed: %v", err.Error())
31 | return &follow.GetFollowListResp{
32 | StatusCode: -1,
33 | StatusMsg: "get follow list failed",
34 | }, err
35 | }
36 | follows := make([]*follow.User, len(queryFollow))
37 | var wg sync.WaitGroup
38 | for index, v := range queryFollow {
39 | wg.Add(1)
40 | query := v
41 | i := index
42 | go func() {
43 | queryFollows, err := l.svcCtx.UserPRC.Info(l.ctx, &userservice.UserInfoReq{
44 | UserId: query.UserId.Int64,
45 | })
46 | if err != nil {
47 | logx.Errorf("in follow model get user info failed: %v", err.Error())
48 | return
49 | }
50 | follows[i] = &follow.User{}
51 | follows[i].Id = queryFollows.User.UserId
52 | follows[i].Name = queryFollows.User.UserName
53 | follows[i].FollowCount = queryFollows.User.FollowCount
54 | follows[i].FollowerCount = queryFollows.User.FollowerCount
55 | follows[i].IsFollow = true
56 | follows[i].Avatar = queryFollows.User.Avatar
57 | follows[i].BackgroundImage = queryFollows.User.BackgroundImage
58 | follows[i].Signature = queryFollows.User.Signature
59 | follows[i].TotalFavorited = queryFollows.User.TotalFavorited
60 | follows[i].WorkCount = queryFollows.User.WorkCount
61 | follows[i].FavoriteCount = queryFollows.User.FavoriteCount
62 | defer wg.Done()
63 | }()
64 | }
65 | wg.Wait()
66 | return &follow.GetFollowListResp{
67 | StatusCode: 0,
68 | UserList: follows,
69 | }, nil
70 | }
71 |
--------------------------------------------------------------------------------
/pkg/follow/internal/server/followserviceserver.go:
--------------------------------------------------------------------------------
1 | // Code generated by goctl. DO NOT EDIT.
2 | // Source: follow.proto
3 |
4 | package server
5 |
6 | import (
7 | "context"
8 |
9 | "douyin/pkg/follow/internal/logic"
10 | "douyin/pkg/follow/internal/svc"
11 | "douyin/pkg/follow/types/follow"
12 | )
13 |
14 | type FollowServiceServer struct {
15 | svcCtx *svc.ServiceContext
16 | follow.UnimplementedFollowServiceServer
17 | }
18 |
19 | func NewFollowServiceServer(svcCtx *svc.ServiceContext) *FollowServiceServer {
20 | return &FollowServiceServer{
21 | svcCtx: svcCtx,
22 | }
23 | }
24 |
25 | func (s *FollowServiceServer) Follow(ctx context.Context, in *follow.FollowReq) (*follow.FollowResp, error) {
26 | l := logic.NewFollowLogic(ctx, s.svcCtx)
27 | return l.Follow(in)
28 | }
29 |
30 | func (s *FollowServiceServer) GetFollowList(ctx context.Context, in *follow.GetFollowListReq) (*follow.GetFollowListResp, error) {
31 | l := logic.NewGetFollowListLogic(ctx, s.svcCtx)
32 | return l.GetFollowList(in)
33 | }
34 |
35 | func (s *FollowServiceServer) GetFollowerList(ctx context.Context, in *follow.GetFollowerListReq) (*follow.GetFollowerListResp, error) {
36 | l := logic.NewGetFollowerListLogic(ctx, s.svcCtx)
37 | return l.GetFollowerList(in)
38 | }
39 |
40 | func (s *FollowServiceServer) GetFriendList(ctx context.Context, in *follow.GetFriendListReq) (*follow.GetFriendListResp, error) {
41 | l := logic.NewGetFriendListLogic(ctx, s.svcCtx)
42 | return l.GetFriendList(in)
43 | }
44 |
45 | func (s *FollowServiceServer) CheckIsFollow(ctx context.Context, in *follow.CheckIsFollowReq) (*follow.CheckIsFollowResp, error) {
46 | l := logic.NewCheckIsFollowLogic(ctx, s.svcCtx)
47 | return l.CheckIsFollow(in)
48 | }
49 |
--------------------------------------------------------------------------------
/pkg/follow/internal/svc/servicecontext.go:
--------------------------------------------------------------------------------
1 | package svc
2 |
3 | import (
4 | "douyin/common/model/followModel"
5 | "douyin/pkg/follow/internal/config"
6 | "douyin/pkg/user/userservice"
7 | "github.com/zeromicro/go-zero/core/stores/sqlx"
8 | "github.com/zeromicro/go-zero/zrpc"
9 | )
10 |
11 | type ServiceContext struct {
12 | Config config.Config
13 | FollowModel followModel.FollowModel
14 | UserPRC userservice.UserService
15 | }
16 |
17 | func NewServiceContext(c config.Config) *ServiceContext {
18 | conn := sqlx.NewMysql(c.Mysql.DataSource)
19 | return &ServiceContext{
20 | Config: c,
21 | FollowModel: followModel.NewFollowModel(conn, c.CacheRedis),
22 | UserPRC: userservice.NewUserService(zrpc.MustNewClient(c.UserRPC)),
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/pkg/gateway/api.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "douyin/pkg/gateway/internal/config"
5 | "douyin/pkg/gateway/internal/handler"
6 | "douyin/pkg/gateway/internal/svc"
7 | "flag"
8 | "fmt"
9 |
10 | "github.com/zeromicro/go-zero/core/conf"
11 | "github.com/zeromicro/go-zero/rest"
12 | )
13 |
14 | var configFile = flag.String("f", "etc/user-api.yaml", "the config file")
15 |
16 | func main() {
17 | flag.Parse()
18 |
19 | var c config.Config
20 |
21 | conf.MustLoad(*configFile, &c)
22 |
23 | server := rest.MustNewServer(c.RestConf)
24 | defer server.Stop()
25 |
26 | ctx := svc.NewServiceContext(c)
27 | handler.RegisterHandlers(server, ctx)
28 |
29 | fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
30 | server.Start()
31 | }
32 |
--------------------------------------------------------------------------------
/pkg/gateway/api/build.sh:
--------------------------------------------------------------------------------
1 | # 通过goctl生成脚手架 --home 是你的模板(如果未对goctl的模板进行修改就不写,我这里修改了一些模板)
2 | # userOpt.api中 import了多个api文件 所以最后只需要这一个文件
3 | goctl api go -api userOpt.api -dir ../ --style=goZero --home=../../../tpl
--------------------------------------------------------------------------------
/pkg/gateway/api/message.api:
--------------------------------------------------------------------------------
1 | syntax = "v1"
2 |
3 | import "user.api"
4 |
5 | type MessageReq {
6 | Token string `form:"token"`
7 | ToUserId int64 `form:"to_user_id"`
8 | ActionType int64 `form:"action_type"`
9 | Content string `form:"content"`
10 | }
11 |
12 | type MessageRes {
13 | Code int64 `json:"status_code"`
14 | Msg string `json:"status_msg,omitempty"`
15 | }
16 | type MessageListReq {
17 | UserId int64 `form:"user_id"`
18 | Token string `form:"token"`
19 | }
20 |
21 | type MessageListRes {
22 | Status
23 | MessageList []*Message `json:"message_list,omitempty"`
24 | }
25 |
26 | type Message {
27 | Id int64 `json:"id"`
28 | ToUserId int64 `json:"to_user_id"`
29 | FromUserId int64 `json:"from_user_id"`
30 | Content string `json:"content"`
31 | CreateTime string `json:"create_time"`
32 | }
33 |
34 | @server(
35 | group : message
36 | prefix : /douyin
37 | middleware: AuthJWT
38 | )
39 |
40 | service user-api {
41 | @doc "发送消息"
42 | @handler Message
43 | post /message/action (MessageReq) returns (MessageRes)
44 |
45 | @doc "聊天记录"
46 | @handler MessageList
47 | get /message/chat (MessageListReq) returns (MessageListRes)
48 | }
--------------------------------------------------------------------------------
/pkg/gateway/api/user.api:
--------------------------------------------------------------------------------
1 | // api语法版本
2 | syntax = "v1"
3 |
4 | info(
5 | author: "babysite"
6 | date: "2023-02-18"
7 | )
8 | // common 返回
9 | type Status {
10 | Code int64 `json:"status_code"`
11 | Msg string `json:"status_msg,omitempty"`
12 | }
13 |
14 | // common 请求
15 | type UserReq {
16 | UserName string `form:"username"`
17 | Password string `form:"password"`
18 | }
19 |
20 | type IdWithTokenReq {
21 | UserId int64 `form:"user_id"`
22 | Token string `form:"token"`
23 | }
24 |
25 | type IdWithTokenRes {
26 | UserId int64 `json:"user_id,omitempty"`
27 | Token string `json:"token,omitempty"`
28 | }
29 |
30 | // 每个成员的tag只能绑定一种 json,form,path header
31 | // 注册
32 | type (
33 | UserRegisterReq {
34 | UserReq
35 | }
36 | UserRegisterRes {
37 | Status
38 | IdWithTokenRes
39 | }
40 | )
41 |
42 | // 登录
43 | type (
44 | UserLoginReq {
45 | UserReq
46 | }
47 | UserLoginRes {
48 | Status
49 | IdWithTokenRes
50 | }
51 | )
52 |
53 | // 用户信息
54 | type User {
55 | UserId int64 `json:"id"`
56 | UserName string `json:"name"`
57 | FollowCount int64 `json:"follow_count"`
58 | FollowerCount int64 `json:"follower_count"`
59 | IsFollow bool `json:"is_follow"`
60 | Avatar string `json:"avatar"`
61 | BackgroundImage string `json:"background_image"`
62 | Signature string `json:"signature"`
63 | TotalFavorited int64 `json:"total_favorited"`
64 | WorkCount int64 `json:"work_count"`
65 | FavoriteCount int64 `json:"favorite_count"`
66 | }
67 |
68 | type (
69 | UserInfoReq {
70 | IdWithTokenReq
71 | }
72 | UserInfoRes {
73 | Status
74 | User *User `json:"user,omitempty"`
75 | }
76 | )
77 | @server (
78 | group : user
79 | prefix : /douyin/user
80 | )
81 | service user-api {
82 | @doc "用户注册"
83 | @handler UserRegister
84 | post /register (UserRegisterReq) returns (UserRegisterRes)
85 | @doc "用户登录"
86 | @handler UserLogin
87 | post /login (UserLoginReq) returns (UserLoginRes)
88 | }
89 |
90 | @server (
91 | group : user
92 | prefix : /douyin/user
93 | middleware: AuthJWT
94 | )
95 | service user-api {
96 | @doc "用户信息"
97 | @handler UserInfo
98 | get / (UserInfoReq) returns (UserInfoRes)
99 | }
--------------------------------------------------------------------------------
/pkg/gateway/api/video.api:
--------------------------------------------------------------------------------
1 | syntax = "v1"
2 |
3 | info(
4 | title: "video"
5 | author: "babysite"
6 | )
7 |
8 | import "user.api"
9 |
10 | type PubVideoReq {
11 | Token string `form:"token"`
12 | Data []byte `form:"data"`
13 | Title string `form:"title"`
14 | }
15 |
16 | type PubVideoRes {
17 | Status
18 | }
19 |
20 | type GetPubVideoListReq {
21 | Token string `form:"token"`
22 | UserId int64 `form:"user_id"`
23 | }
24 |
25 | type PubVideo {
26 | Id int64 `json:"id"`
27 | User User `json:"author"`
28 | PlayURL string `json:"play_url"`
29 | CoverURL string `json:"cover_url"`
30 | FavoriteCount int `json:"favorite_count"`
31 | CommentCount int `json:"comment_count"`
32 | IsFavorite bool `json:"is_favorite"`
33 | Title string `json:"title"`
34 | }
35 |
36 | type GetPubVideoListRes {
37 | Status
38 | VideoPubList []*PubVideo `json:"video_list,omitempty"`
39 | }
40 |
41 | @server(
42 | group: publish
43 | prefix: /douyin/publish
44 | middleware: AuthJWT
45 | )
46 | service user-api {
47 | @doc "发布视频"
48 | @handler PublishVideo
49 | post /action (PubVideoReq) returns (PubVideoRes)
50 |
51 | @doc "获取发布视频列表"
52 | @handler GetPublishVideoList
53 | get /list (GetPubVideoListReq) returns (GetPubVideoListRes)
54 | }
55 |
56 | type FeedVideoListReq {
57 | Token string `form:"token,optional"`
58 | LastTime int64 `form:"last_time,optional"`
59 | }
60 |
61 | type FeedVideoListRes {
62 | Status
63 | NextTime int64 `json:"next_time,omitempty"`
64 | VideoList []*PubVideo `json:"video_list,omitempty"`
65 | }
66 |
67 | @server(
68 | group: feed
69 | prefix: /douyin/feed
70 | )
71 | service user-api {
72 | @doc "获取视频流"
73 | @handler FeedVideoList
74 | get / (FeedVideoListReq) returns (FeedVideoListRes)
75 | }
--------------------------------------------------------------------------------
/pkg/gateway/etc/user-api.yaml:
--------------------------------------------------------------------------------
1 | Name: user-api
2 | Host: 0.0.0.0
3 | Port: 8888
4 | MaxBytes: 8388608
5 | Timeout: 30000
6 | UserCommentRpc:
7 | Etcd:
8 | Hosts:
9 | - etcd.etcd.svc.cluster.local:2379
10 | Key: usercomment.rpc
11 | UserRpc:
12 | Etcd:
13 | Hosts:
14 | - etcd.etcd.svc.cluster.local:2379
15 | Key: user.rpc
16 | UserFavoriteRpc:
17 | Etcd:
18 | Hosts:
19 | - etcd.etcd.svc.cluster.local:2379
20 | Key: useropt.rpc
21 | VideoRPC:
22 | Etcd:
23 | Hosts:
24 | - etcd.etcd.svc.cluster.local:2379
25 | Key: video.rpc
26 | MessageRpc:
27 | Etcd:
28 | Hosts:
29 | - etcd.etcd.svc.cluster.local:2379
30 | Key: usermessage.rpc
31 | UserCommentOptServiceConf:
32 | Name: UserCommentOptService
33 | Brokers:
34 | - kafka.kafka.svc.cluster.local:9092
35 | Group: UserCommentOptService-group
36 | Topic: UserCommentOptService-topic
37 | Offset: first
38 | Consumers: 1
39 | Processors: 1
40 | UserFollowOptServiceConf:
41 | Name: UserCommentOptService
42 | Brokers:
43 | - kafka.kafka.svc.cluster.local:9092
44 | Group: UserFollowOptService-group
45 | Topic: UserFollowOptService-topic
46 | Offset: first
47 | Consumers: 1
48 | Processors: 1
49 | UserFavoriteOptServiceConf:
50 | Name: UserFavoriteOptService
51 | Brokers:
52 | - kafka.kafka.svc.cluster.local:9092
53 | Group: UserFavoriteOptService-group
54 | Topic: UserFavoriteOptService-topic
55 | Offset: first
56 | Consumers: 1
57 | Processors: 1
58 | FollowRpc:
59 | Etcd:
60 | Hosts:
61 | - etcd.etcd.svc.cluster.local:2379
62 | Key: follow.rpc
63 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/config/config.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import (
4 | "github.com/zeromicro/go-queue/kq"
5 | "github.com/zeromicro/go-zero/rest"
6 | "github.com/zeromicro/go-zero/zrpc"
7 | )
8 |
9 | type Config struct {
10 | rest.RestConf
11 | // rpc
12 | UserFavoriteRpc zrpc.RpcClientConf
13 | UserRpc zrpc.RpcClientConf
14 | UserCommentRpc zrpc.RpcClientConf
15 | VideoRPC zrpc.RpcClientConf
16 | FollowRPC zrpc.RpcClientConf
17 | MessageRpc zrpc.RpcClientConf
18 | // kq
19 | UserCommentOptServiceConf kq.KqConf
20 | UserFavoriteOptServiceConf kq.KqConf
21 | UserFollowOptServiceConf kq.KqConf
22 | }
23 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/handler/feed/feedVideoListHandler.go:
--------------------------------------------------------------------------------
1 | package feed
2 |
3 | import (
4 | "douyin/pkg/gateway/internal/logic/feed"
5 | "douyin/pkg/gateway/internal/svc"
6 | "douyin/pkg/gateway/internal/types"
7 | "net/http"
8 |
9 | "github.com/zeromicro/go-zero/rest/httpx"
10 | )
11 |
12 | func FeedVideoListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
13 | return func(w http.ResponseWriter, r *http.Request) {
14 | var req types.FeedVideoListReq
15 | if err := httpx.Parse(r, &req); err != nil {
16 | httpx.ErrorCtx(r.Context(), w, err)
17 | return
18 | }
19 |
20 | l := feed.NewFeedVideoListLogic(r.Context(), svcCtx)
21 | resp, err := l.FeedVideoList(&req)
22 | if err != nil {
23 | httpx.ErrorCtx(r.Context(), w, err)
24 | } else {
25 | httpx.OkJsonCtx(r.Context(), w, resp)
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/handler/message/messageHandler.go:
--------------------------------------------------------------------------------
1 | package message
2 |
3 | import (
4 | "net/http"
5 |
6 | "douyin/pkg/gateway/internal/logic/message"
7 | "douyin/pkg/gateway/internal/svc"
8 | "douyin/pkg/gateway/internal/types"
9 | "github.com/zeromicro/go-zero/rest/httpx"
10 | )
11 |
12 | func MessageHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
13 | return func(w http.ResponseWriter, r *http.Request) {
14 | var req types.MessageReq
15 | if err := httpx.Parse(r, &req); err != nil {
16 | httpx.ErrorCtx(r.Context(), w, err)
17 | return
18 | }
19 |
20 | l := message.NewMessageLogic(r.Context(), svcCtx)
21 | resp, err := l.Message(&req)
22 | if err != nil {
23 | httpx.ErrorCtx(r.Context(), w, err)
24 | } else {
25 | httpx.OkJsonCtx(r.Context(), w, resp)
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/handler/message/messagelistHandler.go:
--------------------------------------------------------------------------------
1 | package message
2 |
3 | import (
4 | "net/http"
5 |
6 | "douyin/pkg/gateway/internal/logic/message"
7 | "douyin/pkg/gateway/internal/svc"
8 | "douyin/pkg/gateway/internal/types"
9 | "github.com/zeromicro/go-zero/rest/httpx"
10 | )
11 |
12 | func MessageListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
13 | return func(w http.ResponseWriter, r *http.Request) {
14 | var req types.MessageListReq
15 | if err := httpx.Parse(r, &req); err != nil {
16 | httpx.ErrorCtx(r.Context(), w, err)
17 | return
18 | }
19 |
20 | l := message.NewMessageListLogin(r.Context(), svcCtx)
21 | resp, err := l.MessageList(&req)
22 | if err != nil {
23 | httpx.ErrorCtx(r.Context(), w, err)
24 | } else {
25 | httpx.OkJsonCtx(r.Context(), w, resp)
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/handler/publish/getPublishVideoListHandler.go:
--------------------------------------------------------------------------------
1 | package publish
2 |
3 | import (
4 | "douyin/pkg/gateway/internal/logic/publish"
5 | "douyin/pkg/gateway/internal/svc"
6 | "douyin/pkg/gateway/internal/types"
7 | "net/http"
8 |
9 | "github.com/zeromicro/go-zero/rest/httpx"
10 | )
11 |
12 | func GetPublishVideoListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
13 | return func(w http.ResponseWriter, r *http.Request) {
14 | var req types.GetPubVideoListReq
15 | if err := httpx.Parse(r, &req); err != nil {
16 | httpx.ErrorCtx(r.Context(), w, err)
17 | return
18 | }
19 |
20 | l := publish.NewGetPublishVideoListLogic(r.Context(), svcCtx)
21 | resp, err := l.GetPublishVideoList(&req)
22 | if err != nil {
23 | httpx.ErrorCtx(r.Context(), w, err)
24 | } else {
25 | httpx.OkJsonCtx(r.Context(), w, resp)
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/handler/publish/publishVideoHandler.go:
--------------------------------------------------------------------------------
1 | package publish
2 |
3 | import (
4 | "douyin/pkg/gateway/internal/logic/publish"
5 | "douyin/pkg/gateway/internal/svc"
6 | "douyin/pkg/gateway/internal/types"
7 | "errors"
8 | "io"
9 | "net/http"
10 |
11 | "github.com/zeromicro/go-zero/rest/httpx"
12 | )
13 |
14 | func PublishVideoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
15 | return func(w http.ResponseWriter, r *http.Request) {
16 | var req types.PubVideoReq
17 |
18 | if !r.Form.Has("title") || !r.Form.Has("token") || r.MultipartForm.File == nil || r.MultipartForm.File["data"] == nil {
19 | httpx.ErrorCtx(r.Context(), w, errors.New("missing parameter title,token or file"))
20 | return
21 | }
22 | req.Token = r.Form.Get("token")
23 | req.Title = r.Form.Get("title")
24 |
25 | file, err := r.MultipartForm.File["data"][0].Open()
26 | if err != nil {
27 | httpx.ErrorCtx(r.Context(), w, err)
28 | return
29 | }
30 | req.Data, err = io.ReadAll(file)
31 | if err != nil {
32 | httpx.ErrorCtx(r.Context(), w, err)
33 | return
34 | }
35 |
36 | l := publish.NewPublishVideoLogic(r.Context(), svcCtx)
37 | resp, err := l.PublishVideo(&req)
38 | if err != nil {
39 | httpx.ErrorCtx(r.Context(), w, err)
40 | } else {
41 | httpx.OkJsonCtx(r.Context(), w, resp)
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/handler/user/userInfoHandler.go:
--------------------------------------------------------------------------------
1 | package user
2 |
3 | import (
4 | "douyin/pkg/gateway/internal/logic/user"
5 | "douyin/pkg/gateway/internal/svc"
6 | "douyin/pkg/gateway/internal/types"
7 | "net/http"
8 |
9 | "github.com/zeromicro/go-zero/rest/httpx"
10 | )
11 |
12 | func UserInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
13 | return func(w http.ResponseWriter, r *http.Request) {
14 | var req types.UserInfoReq
15 | if err := httpx.Parse(r, &req); err != nil {
16 | httpx.ErrorCtx(r.Context(), w, err)
17 | return
18 | }
19 |
20 | l := user.NewUserInfoLogic(r.Context(), svcCtx)
21 | resp, err := l.UserInfo(&req)
22 | if err != nil {
23 | httpx.ErrorCtx(r.Context(), w, err)
24 | } else {
25 | httpx.OkJsonCtx(r.Context(), w, resp)
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/handler/user/userLoginHandler.go:
--------------------------------------------------------------------------------
1 | package user
2 |
3 | import (
4 | "douyin/pkg/gateway/internal/logic/user"
5 | "douyin/pkg/gateway/internal/svc"
6 | "douyin/pkg/gateway/internal/types"
7 | "net/http"
8 |
9 | "github.com/zeromicro/go-zero/rest/httpx"
10 | )
11 |
12 | func UserLoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
13 | return func(w http.ResponseWriter, r *http.Request) {
14 | var req types.UserLoginReq
15 | if err := httpx.Parse(r, &req); err != nil {
16 | httpx.ErrorCtx(r.Context(), w, err)
17 | return
18 | }
19 |
20 | l := user.NewUserLoginLogic(r.Context(), svcCtx)
21 | resp, err := l.UserLogin(&req)
22 | if err != nil {
23 | httpx.ErrorCtx(r.Context(), w, err)
24 | } else {
25 | httpx.OkJsonCtx(r.Context(), w, resp)
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/handler/user/userRegisterHandler.go:
--------------------------------------------------------------------------------
1 | package user
2 |
3 | import (
4 | "douyin/pkg/gateway/internal/logic/user"
5 | "douyin/pkg/gateway/internal/svc"
6 | "douyin/pkg/gateway/internal/types"
7 | "net/http"
8 |
9 | "github.com/zeromicro/go-zero/rest/httpx"
10 | )
11 |
12 | func UserRegisterHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
13 | return func(w http.ResponseWriter, r *http.Request) {
14 | var req types.UserRegisterReq
15 | if err := httpx.Parse(r, &req); err != nil {
16 | httpx.ErrorCtx(r.Context(), w, err)
17 | return
18 | }
19 |
20 | l := user.NewUserRegisterLogic(r.Context(), svcCtx)
21 | resp, err := l.UserRegister(&req)
22 | if err != nil {
23 | httpx.ErrorCtx(r.Context(), w, err)
24 | } else {
25 | httpx.OkJsonCtx(r.Context(), w, resp)
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/handler/userOpt/commentOptHandler.go:
--------------------------------------------------------------------------------
1 | package userOpt
2 |
3 | import (
4 | "douyin/pkg/gateway/internal/logic/userOpt"
5 | "douyin/pkg/gateway/internal/svc"
6 | "douyin/pkg/gateway/internal/types"
7 | "net/http"
8 |
9 | "github.com/zeromicro/go-zero/rest/httpx"
10 | )
11 |
12 | func CommentOptHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
13 | return func(w http.ResponseWriter, r *http.Request) {
14 | var req types.CommentOptReq
15 | if err := httpx.Parse(r, &req); err != nil {
16 | httpx.ErrorCtx(r.Context(), w, err)
17 | return
18 | }
19 |
20 | l := userOpt.NewCommentOptLogic(r.Context(), svcCtx)
21 | resp, err := l.CommentOpt(&req)
22 | if err != nil {
23 | httpx.ErrorCtx(r.Context(), w, err)
24 | } else {
25 | httpx.OkJsonCtx(r.Context(), w, resp)
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/handler/userOpt/favoriteOptHandler.go:
--------------------------------------------------------------------------------
1 | package userOpt
2 |
3 | import (
4 | "douyin/pkg/gateway/internal/logic/userOpt"
5 | "douyin/pkg/gateway/internal/svc"
6 | "douyin/pkg/gateway/internal/types"
7 | "net/http"
8 |
9 | "github.com/zeromicro/go-zero/rest/httpx"
10 | )
11 |
12 | func FavoriteOptHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
13 | return func(w http.ResponseWriter, r *http.Request) {
14 | var req types.FavoriteOptReq
15 | if err := httpx.Parse(r, &req); err != nil {
16 | httpx.ErrorCtx(r.Context(), w, err)
17 | return
18 | }
19 |
20 | l := userOpt.NewFavoriteOptLogic(r.Context(), svcCtx)
21 | resp, err := l.FavoriteOpt(&req)
22 | if err != nil {
23 | httpx.ErrorCtx(r.Context(), w, err)
24 | } else {
25 | httpx.OkJsonCtx(r.Context(), w, resp)
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/handler/userOpt/followOptHandler.go:
--------------------------------------------------------------------------------
1 | package userOpt
2 |
3 | import (
4 | "douyin/pkg/gateway/internal/logic/userOpt"
5 | "douyin/pkg/gateway/internal/svc"
6 | "douyin/pkg/gateway/internal/types"
7 | "net/http"
8 |
9 | "github.com/zeromicro/go-zero/rest/httpx"
10 | )
11 |
12 | func FollowOptHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
13 | return func(w http.ResponseWriter, r *http.Request) {
14 | var req types.FollowOptReq
15 | if err := httpx.Parse(r, &req); err != nil {
16 | httpx.ErrorCtx(r.Context(), w, err)
17 | return
18 | }
19 |
20 | l := userOpt.NewFollowOptLogic(r.Context(), svcCtx)
21 | resp, err := l.FollowOpt(&req)
22 | if err != nil {
23 | httpx.ErrorCtx(r.Context(), w, err)
24 | } else {
25 | httpx.OkJsonCtx(r.Context(), w, resp)
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/handler/userOpt/getCommentListHandler.go:
--------------------------------------------------------------------------------
1 | package userOpt
2 |
3 | import (
4 | "douyin/pkg/gateway/internal/logic/userOpt"
5 | "douyin/pkg/gateway/internal/svc"
6 | "douyin/pkg/gateway/internal/types"
7 | "fmt"
8 | "net/http"
9 |
10 | "github.com/zeromicro/go-zero/rest/httpx"
11 | )
12 |
13 | func GetCommentListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
14 | return func(w http.ResponseWriter, r *http.Request) {
15 | var req types.CommentListReq
16 | if err := httpx.Parse(r, &req); err != nil {
17 | httpx.ErrorCtx(r.Context(), w, err)
18 | return
19 | }
20 |
21 | l := userOpt.NewGetCommentListLogic(r.Context(), svcCtx)
22 | resp, err := l.GetCommentList(&req)
23 | fmt.Println("list", resp.CommentList, resp)
24 | if err != nil {
25 | httpx.ErrorCtx(r.Context(), w, err)
26 | } else {
27 | httpx.OkJsonCtx(r.Context(), w, resp)
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/handler/userOpt/getFavoriteListHandler.go:
--------------------------------------------------------------------------------
1 | package userOpt
2 |
3 | import (
4 | "douyin/pkg/gateway/internal/logic/userOpt"
5 | "douyin/pkg/gateway/internal/svc"
6 | "douyin/pkg/gateway/internal/types"
7 | "net/http"
8 |
9 | "github.com/zeromicro/go-zero/rest/httpx"
10 | )
11 |
12 | func GetFavoriteListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
13 | return func(w http.ResponseWriter, r *http.Request) {
14 | var req types.FavoriteListReq
15 | if err := httpx.Parse(r, &req); err != nil {
16 | httpx.ErrorCtx(r.Context(), w, err)
17 | return
18 | }
19 |
20 | l := userOpt.NewGetFavoriteListLogic(r.Context(), svcCtx)
21 | resp, err := l.GetFavoriteList(&req)
22 | if err != nil {
23 | httpx.ErrorCtx(r.Context(), w, err)
24 | } else {
25 | httpx.OkJsonCtx(r.Context(), w, resp)
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/handler/userOpt/getFollowListHandler.go:
--------------------------------------------------------------------------------
1 | package userOpt
2 |
3 | import (
4 | "douyin/pkg/gateway/internal/logic/userOpt"
5 | "douyin/pkg/gateway/internal/svc"
6 | "douyin/pkg/gateway/internal/types"
7 | "net/http"
8 |
9 | "github.com/zeromicro/go-zero/rest/httpx"
10 | )
11 |
12 | func GetFollowListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
13 | return func(w http.ResponseWriter, r *http.Request) {
14 | var req types.FollowListReq
15 | if err := httpx.Parse(r, &req); err != nil {
16 | httpx.ErrorCtx(r.Context(), w, err)
17 | return
18 | }
19 |
20 | l := userOpt.NewGetFollowListLogic(r.Context(), svcCtx)
21 | resp, err := l.GetFollowList(&req)
22 | if err != nil {
23 | httpx.ErrorCtx(r.Context(), w, err)
24 | } else {
25 | httpx.OkJsonCtx(r.Context(), w, resp)
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/handler/userOpt/getFollowerListHandler.go:
--------------------------------------------------------------------------------
1 | package userOpt
2 |
3 | import (
4 | "douyin/pkg/gateway/internal/logic/userOpt"
5 | "douyin/pkg/gateway/internal/svc"
6 | "douyin/pkg/gateway/internal/types"
7 | "net/http"
8 |
9 | "github.com/zeromicro/go-zero/rest/httpx"
10 | )
11 |
12 | func GetFollowerListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
13 | return func(w http.ResponseWriter, r *http.Request) {
14 | var req types.FollowerListReq
15 | if err := httpx.Parse(r, &req); err != nil {
16 | httpx.ErrorCtx(r.Context(), w, err)
17 | return
18 | }
19 |
20 | l := userOpt.NewGetFollowerListLogic(r.Context(), svcCtx)
21 | resp, err := l.GetFollowerList(&req)
22 | if err != nil {
23 | httpx.ErrorCtx(r.Context(), w, err)
24 | } else {
25 | httpx.OkJsonCtx(r.Context(), w, resp)
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/handler/userOpt/getFriendListHandler.go:
--------------------------------------------------------------------------------
1 | package userOpt
2 |
3 | import (
4 | "net/http"
5 |
6 | "douyin/pkg/gateway/internal/logic/userOpt"
7 | "douyin/pkg/gateway/internal/svc"
8 | "douyin/pkg/gateway/internal/types"
9 | "github.com/zeromicro/go-zero/rest/httpx"
10 | )
11 |
12 | func GetFriendListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
13 | return func(w http.ResponseWriter, r *http.Request) {
14 | var req types.FriendListReq
15 | if err := httpx.Parse(r, &req); err != nil {
16 | httpx.ErrorCtx(r.Context(), w, err)
17 | return
18 | }
19 |
20 | l := userOpt.NewGetFriendListLogic(r.Context(), svcCtx)
21 | resp, err := l.GetFriendList(&req)
22 | if err != nil {
23 | httpx.ErrorCtx(r.Context(), w, err)
24 | } else {
25 | httpx.OkJsonCtx(r.Context(), w, resp)
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/logic/feed/feedVideoListLogic.go:
--------------------------------------------------------------------------------
1 | package feed
2 |
3 | import (
4 | "context"
5 | "douyin/common/xerr"
6 | "douyin/pkg/gateway/internal/svc"
7 | "douyin/pkg/gateway/internal/types"
8 | "douyin/pkg/video/types/video"
9 | "github.com/zeromicro/go-zero/core/logx"
10 | )
11 |
12 | type FeedVideoListLogic struct {
13 | logx.Logger
14 | ctx context.Context
15 | svcCtx *svc.ServiceContext
16 | }
17 |
18 | func NewFeedVideoListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FeedVideoListLogic {
19 | return &FeedVideoListLogic{
20 | Logger: logx.WithContext(ctx),
21 | ctx: ctx,
22 | svcCtx: svcCtx,
23 | }
24 | }
25 |
26 | func (l *FeedVideoListLogic) FeedVideoList(req *types.FeedVideoListReq) (resp *types.FeedVideoListRes, err error) {
27 | videosResp, err := l.svcCtx.VideoRPC.GetVideo(l.ctx, &video.GetVideoReq{
28 | LatestTime: req.LastTime,
29 | Token: req.Token,
30 | })
31 | if err != nil {
32 | logx.Errorf("get videos failed: %v", err.Error())
33 | return &types.FeedVideoListRes{
34 | Status: types.Status{
35 | Code: xerr.ERR,
36 | Msg: "get videos failed",
37 | },
38 | }, err
39 | }
40 | videos := make([]*types.PubVideo, len(videosResp.VideoList))
41 | for i, v := range videosResp.VideoList {
42 | videos[i] = &types.PubVideo{}
43 | videos[i].Id = v.Id
44 | videos[i].User = types.User{
45 | UserId: v.Author.Id,
46 | UserName: v.Author.Name,
47 | FollowCount: v.Author.FollowCount,
48 | FollowerCount: v.Author.FollowerCount,
49 | IsFollow: v.Author.IsFollow,
50 | Avatar: v.Author.Avatar,
51 | BackgroundImage: v.Author.BackgroundImage,
52 | Signature: v.Author.Signature,
53 | TotalFavorited: v.Author.TotalFavorited,
54 | WorkCount: v.Author.WorkCount,
55 | FavoriteCount: v.Author.FavoriteCount,
56 | }
57 | videos[i].PlayURL = v.PlayUrl
58 | videos[i].CoverURL = v.CoverUrl
59 | videos[i].FavoriteCount = int(v.FavoriteCount)
60 | videos[i].CommentCount = int(v.CommentCount)
61 | videos[i].IsFavorite = v.IsFavorite
62 | videos[i].Title = v.Title
63 | }
64 | return &types.FeedVideoListRes{
65 | Status: types.Status{
66 | Code: xerr.OK,
67 | },
68 | NextTime: videosResp.NextTime,
69 | VideoList: videos,
70 | }, nil
71 | }
72 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/logic/message/messageLogic.go:
--------------------------------------------------------------------------------
1 | package message
2 |
3 | import (
4 | "context"
5 | "douyin/common/help/sensitiveWords"
6 | "douyin/pkg/message/userMessagePb"
7 |
8 | "douyin/pkg/gateway/internal/svc"
9 | "douyin/pkg/gateway/internal/types"
10 |
11 | "github.com/zeromicro/go-zero/core/logx"
12 | )
13 |
14 | type MessageLogic struct {
15 | logx.Logger
16 | ctx context.Context
17 | svcCtx *svc.ServiceContext
18 | }
19 |
20 | func NewMessageLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MessageLogic {
21 | return &MessageLogic{
22 | Logger: logx.WithContext(ctx),
23 | ctx: ctx,
24 | svcCtx: svcCtx,
25 | }
26 | }
27 |
28 | func (l *MessageLogic) Message(req *types.MessageReq) (resp *types.MessageRes, err error) {
29 | req.Content = sensitiveWords.SensitiveWordsFliter(sensitiveWords.SensitiveWords, req.Content, '?')
30 | SendMessageRPC, err := l.svcCtx.MessageRpc.SendMessage(l.ctx, &userMessagePb.MessageReq{
31 | ToUserId: req.ToUserId,
32 | Content: req.Content,
33 | Token: req.Token,
34 | ActionType: req.ActionType,
35 | })
36 |
37 | if err != nil {
38 | logx.Errorf("SendMessage->SendMessageRpc err : %v , val : %s , message:%+v", err)
39 | return &types.MessageRes{
40 | Code: 1,
41 | Msg: "send message to SendMessageRPC err",
42 | }, err
43 | }
44 | return &types.MessageRes{
45 | Code: 0,
46 | Msg: SendMessageRPC.Msg,
47 | }, nil
48 | }
49 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/logic/message/messagelistLogic.go:
--------------------------------------------------------------------------------
1 | package message
2 |
3 | import (
4 | "context"
5 | "douyin/pkg/gateway/internal/svc"
6 | "douyin/pkg/gateway/internal/types"
7 | "douyin/pkg/message/userMessagePb"
8 | "github.com/zeromicro/go-zero/core/logx"
9 | )
10 |
11 | type MessagelistLogic struct {
12 | logx.Logger
13 | ctx context.Context
14 | svcCtx *svc.ServiceContext
15 | }
16 |
17 | func NewMessageListLogin(ctx context.Context, svcCtx *svc.ServiceContext) *MessagelistLogic {
18 | return &MessagelistLogic{
19 | Logger: logx.WithContext(ctx),
20 | ctx: ctx,
21 | svcCtx: svcCtx,
22 | }
23 | }
24 |
25 | func (l *MessagelistLogic) MessageList(req *types.MessageListReq) (resp *types.MessageListRes, err error) {
26 | GetMessagelistRPC, err := l.svcCtx.MessageRpc.GetMessageList(l.ctx, &userMessagePb.MessageListReq{
27 | UserId: req.ToUserId,
28 | Token: req.Token,
29 | PreTime: req.PreMsgTime,
30 | })
31 | if err != nil {
32 | logx.Errorf("GetMessagelist->GetMessagelistRpc err : %v , val : %s , message:%+v", err)
33 | return &types.MessageListRes{
34 | Status: types.Status{Code: 1, Msg: err.Error()},
35 | MessageList: nil,
36 | }, err
37 | }
38 | MessageList := make([]*types.Message, len(GetMessagelistRPC.MessageList))
39 |
40 | for i, v := range GetMessagelistRPC.MessageList {
41 | message := &types.Message{}
42 | message.Id = v.Id
43 | message.Content = v.Content
44 | message.CreateTime = v.CreateTime
45 | message.FromUserId = v.FromUserId
46 | message.ToUserId = v.ToUserId
47 | MessageList[i] = message
48 | }
49 | return &types.MessageListRes{
50 | Status: types.Status{Code: 0},
51 | MessageList: MessageList,
52 | }, nil
53 | }
54 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/logic/publish/getPublishVideoListLogic.go:
--------------------------------------------------------------------------------
1 | package publish
2 |
3 | import (
4 | "context"
5 | "douyin/common/xerr"
6 | "douyin/pkg/gateway/internal/svc"
7 | "douyin/pkg/gateway/internal/types"
8 | "douyin/pkg/video/types/video"
9 |
10 | "github.com/zeromicro/go-zero/core/logx"
11 | )
12 |
13 | type GetPublishVideoListLogic struct {
14 | logx.Logger
15 | ctx context.Context
16 | svcCtx *svc.ServiceContext
17 | }
18 |
19 | func NewGetPublishVideoListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetPublishVideoListLogic {
20 | return &GetPublishVideoListLogic{
21 | Logger: logx.WithContext(ctx),
22 | ctx: ctx,
23 | svcCtx: svcCtx,
24 | }
25 | }
26 |
27 | func (l *GetPublishVideoListLogic) GetPublishVideoList(req *types.GetPubVideoListReq) (resp *types.GetPubVideoListRes, err error) {
28 | videosResp, err := l.svcCtx.VideoRPC.GetAllVideoByUserId(l.ctx, &video.GetAllVideoByUserIdReq{
29 | Token: req.Token,
30 | UserId: req.UserId,
31 | })
32 | if err != nil {
33 | logx.Errorf("get videos by userID failed: %v", err.Error())
34 | return &types.GetPubVideoListRes{
35 | Status: types.Status{
36 | Code: xerr.ERR,
37 | Msg: "get videos failed",
38 | },
39 | }, err
40 | }
41 | videos := make([]*types.PubVideo, len(videosResp.VideoList))
42 | for i, v := range videosResp.VideoList {
43 | videos[i] = &types.PubVideo{}
44 | videos[i].Id = v.Id
45 | videos[i].User = types.User{
46 | UserId: v.Author.Id,
47 | UserName: v.Author.Name,
48 | FollowCount: v.Author.FollowCount,
49 | FollowerCount: v.Author.FollowerCount,
50 | IsFollow: v.Author.IsFollow,
51 | Avatar: v.Author.Avatar,
52 | BackgroundImage: v.Author.BackgroundImage,
53 | Signature: v.Author.Signature,
54 | TotalFavorited: v.Author.TotalFavorited,
55 | WorkCount: v.Author.WorkCount,
56 | FavoriteCount: v.Author.FavoriteCount,
57 | }
58 | videos[i].PlayURL = v.PlayUrl
59 | videos[i].CoverURL = v.CoverUrl
60 | videos[i].FavoriteCount = int(v.FavoriteCount)
61 | videos[i].CommentCount = int(v.CommentCount)
62 | videos[i].IsFavorite = v.IsFavorite
63 | videos[i].Title = v.Title
64 | }
65 | return &types.GetPubVideoListRes{
66 | Status: types.Status{
67 | Code: xerr.OK,
68 | },
69 | VideoPubList: videos,
70 | }, nil
71 | }
72 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/logic/publish/publishVideoLogic.go:
--------------------------------------------------------------------------------
1 | package publish
2 |
3 | import (
4 | "context"
5 | "douyin/common/xerr"
6 | "douyin/pkg/gateway/internal/svc"
7 | "douyin/pkg/gateway/internal/types"
8 | "douyin/pkg/video/types/video"
9 | "github.com/zeromicro/go-zero/core/logx"
10 | )
11 |
12 | type PublishVideoLogic struct {
13 | logx.Logger
14 | ctx context.Context
15 | svcCtx *svc.ServiceContext
16 | }
17 |
18 | func NewPublishVideoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PublishVideoLogic {
19 | return &PublishVideoLogic{
20 | Logger: logx.WithContext(ctx),
21 | ctx: ctx,
22 | svcCtx: svcCtx,
23 | }
24 | }
25 |
26 | func (l *PublishVideoLogic) PublishVideo(req *types.PubVideoReq) (resp *types.PubVideoRes, err error) {
27 | pubResp, err := l.svcCtx.VideoRPC.PublishVideo(l.ctx, &video.PublishVideoReq{
28 | Token: req.Token,
29 | Data: req.Data,
30 | Title: req.Title,
31 | })
32 | if err != nil {
33 | logx.Errorf("publish video failed: %v", err.Error())
34 | return &types.PubVideoRes{
35 | Status: types.Status{
36 | Code: xerr.ERR,
37 | Msg: "get videos failed",
38 | },
39 | }, err
40 | }
41 | return &types.PubVideoRes{
42 | Status: types.Status{
43 | Code: int64(pubResp.StatusCode),
44 | Msg: pubResp.StatusMsg,
45 | },
46 | }, nil
47 | }
48 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/logic/user/userInfoLogic.go:
--------------------------------------------------------------------------------
1 | package user
2 |
3 | import (
4 | "context"
5 | "douyin/common/xerr"
6 | "douyin/pkg/gateway/internal/svc"
7 | "douyin/pkg/gateway/internal/types"
8 | "douyin/pkg/user/userservice"
9 | "github.com/zeromicro/go-zero/core/logx"
10 | )
11 |
12 | type UserInfoLogic struct {
13 | logx.Logger
14 | ctx context.Context
15 | svcCtx *svc.ServiceContext
16 | }
17 |
18 | func NewUserInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserInfoLogic {
19 | return &UserInfoLogic{
20 | Logger: logx.WithContext(ctx),
21 | ctx: ctx,
22 | svcCtx: svcCtx,
23 | }
24 | }
25 |
26 | func (l *UserInfoLogic) UserInfo(req *types.UserInfoReq) (resp *types.UserInfoRes, err error) {
27 | info, err := l.svcCtx.UserRpc.Info(l.ctx, &userservice.UserInfoReq{
28 | UserId: req.UserId,
29 | })
30 | if err != nil {
31 | logx.Errorf("get user info failed: %v", err.Error())
32 | return &types.UserInfoRes{
33 | Status: types.Status{
34 | Code: xerr.ERR,
35 | Msg: "get user info failed",
36 | },
37 | }, nil
38 | }
39 |
40 | return &types.UserInfoRes{
41 | Status: types.Status{
42 | Code: xerr.OK,
43 | },
44 | User: &types.User{
45 | UserId: info.User.UserId,
46 | UserName: info.User.UserName,
47 | FollowCount: info.User.FollowCount,
48 | FollowerCount: info.User.FollowerCount,
49 | IsFollow: false,
50 | Avatar: info.User.Avatar,
51 | BackgroundImage: info.User.BackgroundImage,
52 | Signature: info.User.Signature,
53 | TotalFavorited: info.User.TotalFavorited,
54 | WorkCount: info.User.WorkCount,
55 | FavoriteCount: info.User.FavoriteCount,
56 | },
57 | }, nil
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/logic/user/userLoginLogic.go:
--------------------------------------------------------------------------------
1 | package user
2 |
3 | import (
4 | "context"
5 | "douyin/common/xerr"
6 | "douyin/pkg/gateway/internal/svc"
7 | "douyin/pkg/gateway/internal/types"
8 | "douyin/pkg/user/userservice"
9 |
10 | "github.com/zeromicro/go-zero/core/logx"
11 | )
12 |
13 | type UserLoginLogic struct {
14 | logx.Logger
15 | ctx context.Context
16 | svcCtx *svc.ServiceContext
17 | }
18 |
19 | func NewUserLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserLoginLogic {
20 | return &UserLoginLogic{
21 | Logger: logx.WithContext(ctx),
22 | ctx: ctx,
23 | svcCtx: svcCtx,
24 | }
25 | }
26 |
27 | func (l *UserLoginLogic) UserLogin(req *types.UserLoginReq) (resp *types.UserLoginRes, err error) {
28 | res, err := l.svcCtx.UserRpc.Login(l.ctx, &userservice.LoginReq{
29 | UserName: req.UserName,
30 | Password: req.Password,
31 | })
32 | if err != nil {
33 | logx.Errorf("login failed: %v", err.Error())
34 | return &types.UserLoginRes{
35 | Status: types.Status{
36 | Code: xerr.ERR,
37 | Msg: "login failed",
38 | },
39 | }, nil
40 | }
41 |
42 | return &types.UserLoginRes{
43 | Status: types.Status{
44 | Code: xerr.OK,
45 | },
46 | IdWithTokenRes: types.IdWithTokenRes{
47 | UserId: res.UserId,
48 | Token: res.Token,
49 | },
50 | }, nil
51 | }
52 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/logic/user/userRegisterLogic.go:
--------------------------------------------------------------------------------
1 | package user
2 |
3 | import (
4 | "context"
5 | "douyin/common/checkpwd"
6 | "douyin/common/xerr"
7 | "douyin/pkg/gateway/internal/svc"
8 | "douyin/pkg/gateway/internal/types"
9 | "douyin/pkg/user/userservice"
10 | "github.com/zeromicro/go-zero/core/logx"
11 | )
12 |
13 | type UserRegisterLogic struct {
14 | logx.Logger
15 | ctx context.Context
16 | svcCtx *svc.ServiceContext
17 | }
18 |
19 | func NewUserRegisterLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserRegisterLogic {
20 | return &UserRegisterLogic{
21 | Logger: logx.WithContext(ctx),
22 | ctx: ctx,
23 | svcCtx: svcCtx,
24 | }
25 | }
26 |
27 | func (l *UserRegisterLogic) UserRegister(req *types.UserRegisterReq) (resp *types.UserRegisterRes, err error) {
28 | err = checkpwd.CheckPassword(req.Password)
29 | if err != nil {
30 | return &types.UserRegisterRes{
31 | Status: types.Status{
32 | Code: xerr.REUQEST_PARAM_ERROR,
33 | Msg: "Password strength must be the word write + number + symbol, more than 9 digits",
34 | },
35 | }, nil
36 | }
37 |
38 | res, err := l.svcCtx.UserRpc.Register(l.ctx, &userservice.RegisterReq{
39 | UserName: req.UserName,
40 | Password: req.Password,
41 | })
42 | if err != nil {
43 | logx.Errorf("register failed: %s", err.Error())
44 | return &types.UserRegisterRes{
45 | Status: types.Status{
46 | Code: xerr.SECRET_ERROR,
47 | Msg: "register failed" + err.Error(),
48 | },
49 | }, nil
50 | }
51 |
52 | return &types.UserRegisterRes{
53 | Status: types.Status{
54 | Code: xerr.OK,
55 | },
56 | IdWithTokenRes: types.IdWithTokenRes{
57 | UserId: res.UserId,
58 | Token: res.Token,
59 | },
60 | }, nil
61 | }
62 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/logic/userOpt/favoriteOptLogic.go:
--------------------------------------------------------------------------------
1 | package userOpt
2 |
3 | import (
4 | "context"
5 | myToken "douyin/common/help/token"
6 | "douyin/common/messageTypes"
7 | "douyin/common/xerr"
8 | "douyin/pkg/gateway/internal/svc"
9 | "douyin/pkg/gateway/internal/types"
10 | "encoding/json"
11 | "github.com/jinzhu/copier"
12 | "github.com/pkg/errors"
13 |
14 | "github.com/zeromicro/go-zero/core/logx"
15 | )
16 |
17 | type FavoriteOptLogic struct {
18 | logx.Logger
19 | ctx context.Context
20 | svcCtx *svc.ServiceContext
21 | }
22 |
23 | func NewFavoriteOptLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FavoriteOptLogic {
24 | return &FavoriteOptLogic{
25 | Logger: logx.WithContext(ctx),
26 | ctx: ctx,
27 | svcCtx: svcCtx,
28 | }
29 | }
30 |
31 | func (l *FavoriteOptLogic) FavoriteOpt(req *types.FavoriteOptReq) (resp *types.FavoriteOptRes, err error) {
32 | var msgTemp messageTypes.UserFavoriteOptMessage
33 | _ = copier.Copy(&msgTemp, req)
34 |
35 | msgTemp.UserId = l.ctx.Value(myToken.CurrentUserId("CurrentUserId")).(int64)
36 |
37 | // 序列化
38 | msg, err := json.Marshal(msgTemp)
39 | if err != nil {
40 | logx.Errorf("FavoriteOpt json.Marshal err : %s", err.Error())
41 | return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), " json.Marshal err")
42 | }
43 |
44 | // 向消息队列发送消息
45 | err = l.svcCtx.FavoriteOptMsgProducer.Push(string(msg))
46 | if err != nil {
47 | logx.Errorf("FavoriteOpt msgProducer.Push err : %s", err.Error())
48 | return &types.FavoriteOptRes{
49 | Status: types.Status{
50 | Code: xerr.ERR,
51 | Msg: "send message to FavoriteOptMsgConsumer err",
52 | },
53 | }, nil
54 | }
55 | if req.ActionType == 1 {
56 | return &types.FavoriteOptRes{
57 | Status: types.Status{
58 | Code: xerr.OK,
59 | Msg: "user favorite success",
60 | },
61 | }, nil
62 | }
63 | if req.ActionType == 2 {
64 | return &types.FavoriteOptRes{
65 | Status: types.Status{
66 | Code: xerr.OK,
67 | Msg: "user cancel favorite success",
68 | },
69 | }, nil
70 | }
71 | return nil, nil
72 | }
73 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/logic/userOpt/followOptLogic.go:
--------------------------------------------------------------------------------
1 | package userOpt
2 |
3 | import (
4 | "context"
5 | myToken "douyin/common/help/token"
6 | "douyin/common/messageTypes"
7 | "douyin/common/xerr"
8 | "douyin/pkg/gateway/internal/svc"
9 | "douyin/pkg/gateway/internal/types"
10 | "encoding/json"
11 | "github.com/jinzhu/copier"
12 | "github.com/pkg/errors"
13 |
14 | "github.com/zeromicro/go-zero/core/logx"
15 | )
16 |
17 | type FollowOptLogic struct {
18 | logx.Logger
19 | ctx context.Context
20 | svcCtx *svc.ServiceContext
21 | }
22 |
23 | func NewFollowOptLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FollowOptLogic {
24 | return &FollowOptLogic{
25 | Logger: logx.WithContext(ctx),
26 | ctx: ctx,
27 | svcCtx: svcCtx,
28 | }
29 | }
30 |
31 | func (l *FollowOptLogic) FollowOpt(req *types.FollowOptReq) (resp *types.FollowOptRes, err error) {
32 | var followTemp messageTypes.UserFollowOptMessage
33 | _ = copier.Copy(&followTemp, req)
34 |
35 | followTemp.UserId = l.ctx.Value(myToken.CurrentUserId("CurrentUserId")).(int64)
36 | followTemp.ToUserId = req.FollowId
37 | followTemp.ActionType = req.ActionType
38 | // 序列化
39 | msg, err := json.Marshal(followTemp)
40 | if err != nil {
41 | logx.Errorf("FollowOpt json.Marshal err : %s", err.Error())
42 | return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), " json.Marshal err")
43 | }
44 | // 向消息队列发送消息
45 | err = l.svcCtx.FollowOptMsgProducer.Push(string(msg))
46 | if err != nil {
47 | logx.Errorf("FollowOpt msgProducer.Push err : %s", err.Error())
48 | return &types.FollowOptRes{
49 | Status: types.Status{
50 | Code: xerr.ERR,
51 | Msg: "send message to FollowOptMsgConsumer err",
52 | },
53 | }, nil
54 | }
55 | if req.ActionType == 1 {
56 | return &types.FollowOptRes{
57 | Status: types.Status{
58 | Code: xerr.OK,
59 | Msg: "user follow success",
60 | },
61 | }, nil
62 | }
63 | if req.ActionType == 2 {
64 | return &types.FollowOptRes{
65 | Status: types.Status{
66 | Code: xerr.OK,
67 | Msg: "user cancel follow success",
68 | },
69 | }, nil
70 | }
71 | return nil, nil
72 | }
73 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/logic/userOpt/getFollowListLogic.go:
--------------------------------------------------------------------------------
1 | package userOpt
2 |
3 | import (
4 | "context"
5 | "douyin/common/xerr"
6 | "douyin/pkg/follow/followservice"
7 | "douyin/pkg/gateway/internal/svc"
8 | "douyin/pkg/gateway/internal/types"
9 |
10 | "github.com/zeromicro/go-zero/core/logx"
11 | )
12 |
13 | type GetFollowListLogic struct {
14 | logx.Logger
15 | ctx context.Context
16 | svcCtx *svc.ServiceContext
17 | }
18 |
19 | func NewGetFollowListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetFollowListLogic {
20 | return &GetFollowListLogic{
21 | Logger: logx.WithContext(ctx),
22 | ctx: ctx,
23 | svcCtx: svcCtx,
24 | }
25 | }
26 |
27 | func (l *GetFollowListLogic) GetFollowList(req *types.FollowListReq) (resp *types.FollowListRes, err error) {
28 | result, err := l.svcCtx.FollowRPC.GetFollowList(l.ctx, &followservice.GetFollowListReq{
29 | Token: req.Token,
30 | UserId: req.UserId,
31 | })
32 | if err != nil {
33 | logx.Errorf("UserFollowList->followRpc err : %v , val : %s , message:%+v", err)
34 | return &types.FollowListRes{
35 | Status: types.Status{
36 | Code: xerr.ERR,
37 | Msg: "send message to followRpc err",
38 | },
39 | }, nil
40 | }
41 | userList := make([]*types.User, len(result.UserList))
42 | for i, v := range result.UserList {
43 | userList[i] = &types.User{}
44 | userList[i].UserId = v.Id
45 | userList[i].UserName = v.Name
46 | userList[i].FollowCount = v.FollowCount
47 | userList[i].FollowerCount = v.FollowerCount
48 | userList[i].IsFollow = v.IsFollow
49 | userList[i].Avatar = v.Avatar
50 | userList[i].BackgroundImage = v.BackgroundImage
51 | userList[i].Signature = v.Signature
52 | userList[i].TotalFavorited = v.TotalFavorited
53 | userList[i].WorkCount = v.WorkCount
54 | userList[i].FavoriteCount = v.FavoriteCount
55 | }
56 | return &types.FollowListRes{
57 | Status: types.Status{
58 | Code: xerr.OK,
59 | Msg: "Get favorite list success",
60 | },
61 | UserFollowlist: userList,
62 | }, nil
63 | }
64 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/logic/userOpt/getFollowerListLogic.go:
--------------------------------------------------------------------------------
1 | package userOpt
2 |
3 | import (
4 | "context"
5 | "douyin/common/xerr"
6 | "douyin/pkg/follow/followservice"
7 | "douyin/pkg/gateway/internal/svc"
8 | "douyin/pkg/gateway/internal/types"
9 |
10 | "github.com/zeromicro/go-zero/core/logx"
11 | )
12 |
13 | type GetFollowerListLogic struct {
14 | logx.Logger
15 | ctx context.Context
16 | svcCtx *svc.ServiceContext
17 | }
18 |
19 | func NewGetFollowerListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetFollowerListLogic {
20 | return &GetFollowerListLogic{
21 | Logger: logx.WithContext(ctx),
22 | ctx: ctx,
23 | svcCtx: svcCtx,
24 | }
25 | }
26 |
27 | func (l *GetFollowerListLogic) GetFollowerList(req *types.FollowerListReq) (resp *types.FollowerListRes, err error) {
28 | result, err := l.svcCtx.FollowRPC.GetFollowerList(l.ctx, &followservice.GetFollowerListReq{
29 | Token: req.Token,
30 | UserId: req.UserId,
31 | })
32 | if err != nil {
33 | logx.Errorf("UserFollowerList->followerRpc err : %v , val : %s , message:%+v", err)
34 | return &types.FollowerListRes{
35 | Status: types.Status{
36 | Code: xerr.ERR,
37 | Msg: "send message to followRpc err",
38 | },
39 | }, nil
40 | }
41 | userList := make([]*types.User, len(result.UserList))
42 | for i, v := range result.UserList {
43 | userList[i] = &types.User{}
44 | userList[i].UserId = v.Id
45 | userList[i].UserName = v.Name
46 | userList[i].FollowCount = v.FollowCount
47 | userList[i].FollowerCount = v.FollowerCount
48 | userList[i].IsFollow = v.IsFollow
49 | userList[i].Avatar = v.Avatar
50 | userList[i].BackgroundImage = v.BackgroundImage
51 | userList[i].Signature = v.Signature
52 | userList[i].TotalFavorited = v.TotalFavorited
53 | userList[i].WorkCount = v.WorkCount
54 | userList[i].FavoriteCount = v.FavoriteCount
55 | }
56 | return &types.FollowerListRes{
57 | Status: types.Status{
58 | Code: xerr.OK,
59 | Msg: "Get favorite list success",
60 | },
61 | UserFollowerlist: userList,
62 | }, nil
63 | }
64 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/logic/userOpt/getFriendListLogic.go:
--------------------------------------------------------------------------------
1 | package userOpt
2 |
3 | import (
4 | "context"
5 | "douyin/pkg/follow/followservice"
6 | "douyin/pkg/logger"
7 | "sync"
8 |
9 | "douyin/pkg/gateway/internal/svc"
10 | "douyin/pkg/gateway/internal/types"
11 |
12 | "github.com/zeromicro/go-zero/core/logx"
13 | )
14 |
15 | type GetFriendListLogic struct {
16 | logx.Logger
17 | ctx context.Context
18 | svcCtx *svc.ServiceContext
19 | }
20 |
21 | func NewGetFriendListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetFriendListLogic {
22 | return &GetFriendListLogic{
23 | Logger: logx.WithContext(ctx),
24 | ctx: ctx,
25 | svcCtx: svcCtx,
26 | }
27 | }
28 |
29 | func (l *GetFriendListLogic) GetFriendList(req *types.FriendListReq) (resp *types.FriendListRes, err error) {
30 | friendRes, err := l.svcCtx.FollowRPC.GetFriendList(l.ctx, &followservice.GetFriendListReq{
31 | UserId: req.UserId,
32 | Token: req.Token,
33 | })
34 | if err != nil {
35 | logger.Error("GetFriendList RPC failed %s", err.Error())
36 | return &types.FriendListRes{
37 | Status: types.Status{
38 | Code: -1,
39 | Msg: "get friend list failed",
40 | },
41 | }, err
42 | }
43 | userList := make([]*types.FriendUser, len(friendRes.UserList))
44 | var wg sync.WaitGroup
45 | for index, queryUser := range friendRes.UserList {
46 | i := index
47 | user := queryUser
48 | wg.Add(1)
49 | go func() {
50 | userList[i] = &types.FriendUser{}
51 | userList[i].Message = *user.Message
52 | userList[i].MsgType = user.MsgType
53 | userList[i].UserId = user.Id
54 | userList[i].UserName = user.Name
55 | userList[i].FollowCount = user.FollowCount
56 | userList[i].FollowerCount = user.FollowerCount
57 | userList[i].IsFollow = user.IsFollow
58 | userList[i].Avatar = user.Avatar
59 | userList[i].BackgroundImage = user.BackgroundImage
60 | userList[i].Signature = user.Signature
61 | userList[i].TotalFavorited = user.TotalFavorited
62 | userList[i].WorkCount = user.WorkCount
63 | userList[i].FavoriteCount = user.FavoriteCount
64 | defer wg.Done()
65 | }()
66 | }
67 | wg.Wait()
68 | return &types.FriendListRes{
69 | Status: types.Status{
70 | Code: 0,
71 | Msg: "success",
72 | },
73 | UserFriendlist: userList,
74 | }, nil
75 | }
76 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/middleware/authjwtMiddleware.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "context"
5 | myToken "douyin/common/help/token"
6 | "douyin/common/xerr"
7 | "douyin/pkg/gateway/internal/types"
8 | "encoding/json"
9 | "net/http"
10 | "time"
11 | )
12 |
13 | type AuthJWTMiddleware struct {
14 | }
15 |
16 | func NewAuthJWTMiddleware() *AuthJWTMiddleware {
17 | return &AuthJWTMiddleware{}
18 | }
19 |
20 | func (m *AuthJWTMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
21 | return func(w http.ResponseWriter, r *http.Request) {
22 | status := new(types.Status)
23 | token := r.FormValue("token")
24 |
25 | if token == "" {
26 | status.Code = xerr.REUQEST_PARAM_ERROR
27 | status.Msg = "no token"
28 | res, _ := json.Marshal(status)
29 | _, _ = w.Write(res)
30 | return
31 | }
32 | // 解析token 判断是否有效
33 | var parseClaims myToken.ParseToken
34 | claims, err := parseClaims.ParseToken(token)
35 | if err != nil {
36 | status.Code = xerr.REUQEST_PARAM_ERROR
37 | status.Msg = "param error " + err.Error()
38 | res, _ := json.Marshal(status)
39 | _, _ = w.Write(res)
40 | return
41 | }
42 |
43 | // 过期时间点 小于当前时间 表示过期
44 | if claims.ExpireAt < time.Now().Unix() {
45 | status.Code = xerr.REUQEST_PARAM_ERROR
46 | status.Msg = "please login again"
47 | res, _ := json.Marshal(status)
48 | _, _ = w.Write(res)
49 | return
50 | }
51 | r = r.Clone(context.WithValue(r.Context(), myToken.CurrentUserId("CurrentUserId"), claims.UserId))
52 |
53 | next(w, r)
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/middleware/isloginMiddleware.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "context"
5 | myToken "douyin/common/help/token"
6 | "douyin/common/xerr"
7 | "douyin/pkg/gateway/internal/types"
8 | "encoding/json"
9 | "net/http"
10 | "time"
11 | )
12 |
13 | type IsLoginMiddleware struct {
14 | }
15 |
16 | func NewIsLoginMiddleware() *IsLoginMiddleware {
17 | return &IsLoginMiddleware{}
18 | }
19 |
20 | func (m *IsLoginMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
21 | return func(w http.ResponseWriter, r *http.Request) {
22 | status := new(types.Status)
23 | token := r.FormValue("token")
24 | if token != "" {
25 | // 解析token 判断是否有效
26 | var parseClaims myToken.ParseToken
27 | claims, err := parseClaims.ParseToken(token)
28 | if err != nil {
29 | status.Code = xerr.REUQEST_PARAM_ERROR
30 | status.Msg = "param error " + err.Error()
31 | res, _ := json.Marshal(status)
32 | _, _ = w.Write(res)
33 | return
34 | }
35 |
36 | // 过期时间点 小于当前时间 表示过期
37 | if claims.ExpireAt < time.Now().Unix() {
38 | status.Code = xerr.REUQEST_PARAM_ERROR
39 | status.Msg = "please login again"
40 | res, _ := json.Marshal(status)
41 | _, _ = w.Write(res)
42 | return
43 | }
44 |
45 | r = r.Clone(context.WithValue(r.Context(), myToken.CurrentUserId("LoginUserId"), claims.UserId))
46 |
47 | // 把r传递给下一个handler
48 | next(w, r)
49 | } else {
50 | next(w, r)
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/pkg/gateway/internal/svc/serviceContext.go:
--------------------------------------------------------------------------------
1 | package svc
2 |
3 | import (
4 | "douyin/pkg/comment/usercomment"
5 | "douyin/pkg/favorite/useroptservice"
6 | "douyin/pkg/follow/followservice"
7 | "douyin/pkg/gateway/internal/config"
8 | "douyin/pkg/gateway/internal/middleware"
9 | "douyin/pkg/message/usermessage"
10 | "douyin/pkg/user/userservice"
11 | "douyin/pkg/video/videoservice"
12 | "github.com/zeromicro/go-queue/kq"
13 | "github.com/zeromicro/go-zero/rest"
14 | "github.com/zeromicro/go-zero/zrpc"
15 | )
16 |
17 | type ServiceContext struct {
18 | Config config.Config
19 |
20 | UserRpc userservice.UserService
21 | UserCommentRpc usercomment.UserComment
22 | UserFavoriteRpc useroptservice.UserOptService
23 | VideoRPC videoservice.VideoService
24 | FollowRPC followservice.FollowService
25 | MessageRpc usermessage.UserMessage
26 |
27 | CommentOptMsgProducer *kq.Pusher
28 | FavoriteOptMsgProducer *kq.Pusher
29 | FollowOptMsgProducer *kq.Pusher
30 |
31 | AuthJWT rest.Middleware
32 | IsLogin rest.Middleware
33 | }
34 |
35 | func NewServiceContext(c config.Config) *ServiceContext {
36 | return &ServiceContext{
37 | Config: c,
38 | AuthJWT: middleware.NewAuthJWTMiddleware().Handle,
39 | IsLogin: middleware.NewIsLoginMiddleware().Handle,
40 |
41 | UserRpc: userservice.NewUserService(zrpc.MustNewClient(c.UserRpc)),
42 | UserCommentRpc: usercomment.NewUserComment(zrpc.MustNewClient(c.UserCommentRpc)),
43 | FollowRPC: followservice.NewFollowService(zrpc.MustNewClient(c.FollowRPC)),
44 | FavoriteOptMsgProducer: kq.NewPusher(c.UserFavoriteOptServiceConf.Brokers, c.UserFavoriteOptServiceConf.Topic),
45 | MessageRpc: usermessage.NewUserMessage(zrpc.MustNewClient(c.MessageRpc)),
46 | UserFavoriteRpc: useroptservice.NewUserOptService(zrpc.MustNewClient(c.UserFavoriteRpc)),
47 | VideoRPC: videoservice.NewVideoService(zrpc.MustNewClient(c.VideoRPC)),
48 | CommentOptMsgProducer: kq.NewPusher(c.UserCommentOptServiceConf.Brokers, c.UserCommentOptServiceConf.Topic),
49 | FollowOptMsgProducer: kq.NewPusher(c.UserFollowOptServiceConf.Brokers, c.UserFollowOptServiceConf.Topic),
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/pkg/kafka/docs.go:
--------------------------------------------------------------------------------
1 | package kafkax
2 |
3 | /*
4 | Autor: godot42
5 | Date: 2023-2-7 07:31:32
6 | Descripe:
7 | A packing of kafka-go
8 | */
9 |
--------------------------------------------------------------------------------
/pkg/kafka/manager.go:
--------------------------------------------------------------------------------
1 | package kafkax
2 |
3 | import "github.com/segmentio/kafka-go"
4 |
5 | type Manager struct {
6 | reader *kafka.Reader
7 | writer *kafka.Writer
8 | operator
9 | }
10 |
11 | func New() *Manager {
12 | return nil
13 | }
14 |
15 | func (m *Manager) GetWriter() (*kafka.Writer, error) {
16 | m.reader = kafka.NewReader(kafka.ReaderConfig{})
17 | return nil, nil
18 | }
19 |
20 | func (m *Manager) GetReader() (*kafka.Reader, error) {
21 | m.writer = kafka.NewWriter(kafka.WriterConfig{})
22 | return nil, nil
23 | }
24 |
--------------------------------------------------------------------------------
/pkg/kafka/operator.go:
--------------------------------------------------------------------------------
1 | package kafkax
2 |
3 | import (
4 | "github.com/segmentio/kafka-go"
5 | )
6 |
7 | // TODO: define and implent
8 | type operator interface {
9 | writerOnce(topic, broker string, msg interface{})
10 | readOnce()
11 | CreateTopics()
12 | Pull()
13 | Push()
14 | PrintTopics(broker string) error
15 | }
16 |
17 | func (m *Manager) PrintTopics(broker string) error {
18 |
19 | conn, err := kafka.Dial("tcp", broker)
20 | if err != nil {
21 | return err
22 | }
23 | defer conn.Close()
24 |
25 | partitions, err := conn.ReadPartitions()
26 | if err != nil {
27 | return err
28 | }
29 |
30 | mp := map[string]struct{}{}
31 |
32 | for _, p := range partitions {
33 | mp[p.Topic] = struct{}{}
34 | }
35 |
36 | for k := range mp {
37 | println(k)
38 | }
39 |
40 | return nil
41 | }
42 |
--------------------------------------------------------------------------------
/pkg/logger/log.go:
--------------------------------------------------------------------------------
1 | package logger
2 |
3 | import (
4 | "go.uber.org/zap"
5 | "sync"
6 | )
7 |
8 | var zlog *zap.SugaredLogger
9 | var once sync.Once
10 |
11 | func init() {
12 | once.Do(func() {
13 | zlog = NewLogger()
14 | zlog = zlog.WithOptions(zap.AddCallerSkip(1))
15 | })
16 | }
17 |
18 | func NewLogger() *zap.SugaredLogger {
19 | // Todo: Production level
20 | level := zap.NewAtomicLevel()
21 | level.SetLevel(zap.DebugLevel)
22 |
23 | cfg := zap.NewProductionConfig()
24 | cfg.Level = level
25 | logger := zap.Must(cfg.Build())
26 | sugaredLogger := logger.Sugar()
27 | return sugaredLogger
28 | }
29 |
30 | func DebugF(format string, args ...interface{}) {
31 | zlog.Debugf(format, args...)
32 | }
33 |
34 | func InfoF(format string, args ...interface{}) {
35 | zlog.Infof(format, args...)
36 | }
37 |
38 | func Errorf(format string, args ...interface{}) {
39 | zlog.Errorf(format, args...)
40 | }
41 |
42 | func Debug(args ...interface{}) {
43 | zlog.Debug(args...)
44 | }
45 |
46 | func Info(args ...interface{}) {
47 | zlog.Info(args...)
48 | }
49 |
50 | func Error(args ...interface{}) {
51 | zlog.Error(args...)
52 | }
53 |
--------------------------------------------------------------------------------
/pkg/message/etc/userMessage.yaml:
--------------------------------------------------------------------------------
1 | Name: usermessage.rpc
2 | ListenOn: 0.0.0.0:8080
3 | Etcd:
4 | Hosts:
5 | - etcd.etcd.svc.cluster.local:2379
6 | Key: usermessage.rpc
7 | DB:
8 | DataSource: douyin:Z4eEXbWWCApby8dE@tcp(bt.vacant.zone:3306)/douyin?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai
9 | CacheConf:
10 | - Host: redis-master.redis.svc.cluster.local:6379
11 | Pass: redispwd123
12 | FollowRPC:
13 | Etcd:
14 | Hosts:
15 | - etcd.etcd.svc.cluster.local:2379
16 | Key: follow.rpc
--------------------------------------------------------------------------------
/pkg/message/internal/config/config.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import (
4 | "github.com/zeromicro/go-zero/core/stores/cache"
5 | "github.com/zeromicro/go-zero/zrpc"
6 | )
7 |
8 | type Config struct {
9 | zrpc.RpcServerConf
10 | DB struct {
11 | DataSource string
12 | }
13 | CacheConf cache.CacheConf
14 | FollowRPC zrpc.RpcClientConf
15 | }
16 |
--------------------------------------------------------------------------------
/pkg/message/internal/logic/getMessageListLogic.go:
--------------------------------------------------------------------------------
1 | package logic
2 |
3 | import (
4 | "context"
5 | "douyin/common/help/token"
6 | "douyin/pkg/message/internal/svc"
7 | "douyin/pkg/message/userMessagePb"
8 | "github.com/zeromicro/go-zero/core/logx"
9 | )
10 |
11 | type GetMessageListLogic struct {
12 | ctx context.Context
13 | svcCtx *svc.ServiceContext
14 | logx.Logger
15 | }
16 |
17 | func NewGetMessageListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetMessageListLogic {
18 | return &GetMessageListLogic{
19 | ctx: ctx,
20 | svcCtx: svcCtx,
21 | Logger: logx.WithContext(ctx),
22 | }
23 | }
24 |
25 | // -----------------------GetMessageList-----------------------
26 | func (l *GetMessageListLogic) GetMessageList(in *userMessagePb.MessageListReq) (*userMessagePb.MessageListRes, error) {
27 | parseToken := token.ParseToken{}
28 | userid, _ := parseToken.ParseToken(in.Token)
29 | allMessageData, err := l.svcCtx.MessageModel.FindMessageListByUserID(l.ctx, userid.UserId, in.UserId, in.PreTime)
30 | if err != nil {
31 | logx.Errorf("GetCommentList------->SELECT err : %s", err.Error())
32 | return &userMessagePb.MessageListRes{
33 | Code: 1,
34 | Msg: "failure",
35 | MessageList: nil,
36 | }, err
37 | }
38 |
39 | var MessageList []*userMessagePb.Message
40 | for _, v := range allMessageData {
41 | var message userMessagePb.Message
42 | message.Id = v.Id
43 | message.ToUserId = v.ToUserId
44 | message.Content = v.Content
45 | message.FromUserId = v.FromUserId
46 | message.CreateTime = v.CreateTime
47 | MessageList = append(MessageList, &message)
48 | }
49 | return &userMessagePb.MessageListRes{
50 | Code: 0,
51 | Msg: "Success",
52 | MessageList: MessageList,
53 | }, nil
54 | }
55 |
--------------------------------------------------------------------------------
/pkg/message/internal/logic/sendMessageLogic.go:
--------------------------------------------------------------------------------
1 | package logic
2 |
3 | import (
4 | "context"
5 | "douyin/common/help/token"
6 | "douyin/common/model/messageModel"
7 | "douyin/pkg/logger"
8 | "douyin/pkg/message/internal/svc"
9 | "douyin/pkg/message/userMessagePb"
10 | "github.com/zeromicro/go-zero/core/logx"
11 | "time"
12 | )
13 |
14 | type SendMessageLogic struct {
15 | ctx context.Context
16 | svcCtx *svc.ServiceContext
17 | logx.Logger
18 | }
19 |
20 | func NewSendMessageLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SendMessageLogic {
21 | return &SendMessageLogic{
22 | ctx: ctx,
23 | svcCtx: svcCtx,
24 | Logger: logx.WithContext(ctx),
25 | }
26 | }
27 |
28 | func (l *SendMessageLogic) SendMessage(in *userMessagePb.MessageReq) (*userMessagePb.MessageRes, error) {
29 | message := &messageModel.Message{}
30 | var parseToken token.ParseToken
31 | claims, err := parseToken.ParseToken(in.Token)
32 | if err != nil {
33 | logger.InfoF("Token解析错误 %s ", err.Error())
34 | return &userMessagePb.MessageRes{
35 | Code: -1,
36 | Msg: "Token解析错误",
37 | }, err
38 | }
39 |
40 | message.ToUserId = in.ToUserId
41 | message.Content = in.Content
42 | message.FromUserId = claims.UserId
43 | message.CreateTime = time.Now().Unix()
44 |
45 | _, err = l.svcCtx.MessageModel.Insert(l.ctx, message)
46 |
47 | if err != nil {
48 | logx.Errorf("SendMessage------->SELECT err : %s", err.Error())
49 | return &userMessagePb.MessageRes{
50 | Code: -1,
51 | Msg: "failure",
52 | }, err
53 | }
54 |
55 | err = l.svcCtx.FollowModel.UpdateMsg(l.ctx, claims.UserId, in.ToUserId, message.Content)
56 | if err != nil {
57 | logx.Errorf("Update First Msg failed : %s", err.Error())
58 | return &userMessagePb.MessageRes{
59 | Code: -1,
60 | Msg: "failure",
61 | }, err
62 | }
63 |
64 | return &userMessagePb.MessageRes{
65 | Code: 0,
66 | Msg: "Success",
67 | }, nil
68 | }
69 |
--------------------------------------------------------------------------------
/pkg/message/internal/server/userMessageServer.go:
--------------------------------------------------------------------------------
1 | // Code generated by goctl. DO NOT EDIT!
2 | // Source: UserMessage.proto
3 |
4 | package server
5 |
6 | import (
7 | "context"
8 |
9 | "douyin/pkg/message/internal/logic"
10 | "douyin/pkg/message/internal/svc"
11 | "douyin/pkg/message/userMessagePb"
12 | )
13 |
14 | type UserMessageServer struct {
15 | svcCtx *svc.ServiceContext
16 | userMessagePb.UnimplementedUserMessageServer
17 | }
18 |
19 | func NewUserMessageServer(svcCtx *svc.ServiceContext) *UserMessageServer {
20 | return &UserMessageServer{
21 | svcCtx: svcCtx,
22 | }
23 | }
24 |
25 | // -----------------------SendMessage-----------------------
26 | func (s *UserMessageServer) SendMessage(ctx context.Context, in *userMessagePb.MessageReq) (*userMessagePb.MessageRes, error) {
27 | l := logic.NewSendMessageLogic(ctx, s.svcCtx)
28 | return l.SendMessage(in)
29 | }
30 |
31 | // -----------------------GetMessageList-----------------------
32 | func (s *UserMessageServer) GetMessageList(ctx context.Context, in *userMessagePb.MessageListReq) (*userMessagePb.MessageListRes, error) {
33 | l := logic.NewGetMessageListLogic(ctx, s.svcCtx)
34 | return l.GetMessageList(in)
35 | }
36 |
--------------------------------------------------------------------------------
/pkg/message/internal/svc/serviceContext.go:
--------------------------------------------------------------------------------
1 | package svc
2 |
3 | import (
4 | "douyin/common/model/followModel"
5 | "douyin/common/model/messageModel"
6 | "douyin/pkg/follow/followservice"
7 | "douyin/pkg/message/internal/config"
8 | "github.com/zeromicro/go-zero/core/stores/sqlx"
9 | "github.com/zeromicro/go-zero/zrpc"
10 | )
11 |
12 | type ServiceContext struct {
13 | Config config.Config
14 | MessageModel messageModel.MessageModel
15 | FollowModel followModel.FollowModel
16 | FollowRPC followservice.FollowService
17 | }
18 |
19 | func NewServiceContext(c config.Config) *ServiceContext {
20 | conn := sqlx.NewMysql(c.DB.DataSource)
21 | return &ServiceContext{
22 | Config: c,
23 | MessageModel: messageModel.NewMessageModel(conn, c.CacheConf),
24 | FollowModel: followModel.NewFollowModel(conn, c.CacheConf),
25 | FollowRPC: followservice.NewFollowService(zrpc.MustNewClient(c.FollowRPC)),
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/pkg/message/userMessage.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "douyin/pkg/message/internal/config"
5 | "douyin/pkg/message/internal/server"
6 | "douyin/pkg/message/internal/svc"
7 | "douyin/pkg/message/userMessagePb"
8 | "flag"
9 | "fmt"
10 |
11 | "github.com/zeromicro/go-zero/core/conf"
12 | "github.com/zeromicro/go-zero/core/service"
13 | "github.com/zeromicro/go-zero/zrpc"
14 | "google.golang.org/grpc"
15 | "google.golang.org/grpc/reflection"
16 | )
17 |
18 | var configFile = flag.String("f", "etc/userMessage.yaml", "the config file")
19 |
20 | func main() {
21 | flag.Parse()
22 |
23 | var c config.Config
24 | conf.MustLoad(*configFile, &c)
25 | ctx := svc.NewServiceContext(c)
26 |
27 | s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
28 | userMessagePb.RegisterUserMessageServer(grpcServer, server.NewUserMessageServer(ctx))
29 |
30 | if c.Mode == service.DevMode || c.Mode == service.TestMode {
31 | reflection.Register(grpcServer)
32 | }
33 | })
34 | defer s.Stop()
35 |
36 | fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
37 | s.Start()
38 | }
39 |
--------------------------------------------------------------------------------
/pkg/message/userMessagePb/GenPb/UserMessage.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | option go_package ="./userMessagePb";
4 |
5 | package pb;
6 |
7 | // ------------------------------------
8 | // Messages
9 | // ------------------------------------
10 |
11 | message MessageReq {
12 | string Token = 1;
13 | int64 ToUserId = 2;
14 | int64 ActionType = 3;
15 | string Content = 4;
16 | }
17 |
18 | message MessageRes {
19 | int64 Code = 1;
20 | string Msg = 2;
21 | }
22 |
23 | message MessageListReq {
24 | int64 UserId = 1;
25 | string Token = 2;
26 | int64 PreTime = 3;
27 | }
28 |
29 | message MessageListRes {
30 | int64 Code = 1;
31 | string Msg = 2;
32 | repeated Message MessageList = 3;
33 | }
34 |
35 | message Message {
36 | int64 Id = 1;
37 | int64 ToUserId = 2;
38 | int64 FromUserId = 3;
39 | string Content = 4;
40 | int64 CreateTime = 5;
41 | }
42 |
43 |
44 | // ------------------------------------
45 | // Rpc Func
46 | // ------------------------------------
47 |
48 | service UserMessage{
49 | //-----------------------SendMessage-----------------------
50 | rpc SendMessage(MessageReq) returns (MessageRes);
51 | //-----------------------GetMessageList-----------------------
52 | rpc GetMessageList(MessageListReq) returns (MessageListRes);
53 | }
54 |
--------------------------------------------------------------------------------
/pkg/message/userMessagePb/GenPb/build.sh:
--------------------------------------------------------------------------------
1 | #goctl rpc protoc UserCommentService.proto --go_out=../../ --go-grpc_out=../../ --zrpc_out=../../ --style=goZero --home=../../../../tpl
2 | # 当有多个proto文件时 需要先生成其他的文件 再生成主要的pb文件
3 |
4 |
5 | goctl rpc protoc UserMessage.proto --go_out=../../ --go-grpc_out=../../ --zrpc_out=../../ --style=goZero
6 |
--------------------------------------------------------------------------------
/pkg/message/usermessage/userMessage.go:
--------------------------------------------------------------------------------
1 | // Code generated by goctl. DO NOT EDIT!
2 | // Source: UserMessage.proto
3 |
4 | package usermessage
5 |
6 | import (
7 | "context"
8 |
9 | "douyin/pkg/message/userMessagePb"
10 |
11 | "github.com/zeromicro/go-zero/zrpc"
12 | "google.golang.org/grpc"
13 | )
14 |
15 | type (
16 | Message = userMessagePb.Message
17 | MessageListReq = userMessagePb.MessageListReq
18 | MessageListRes = userMessagePb.MessageListRes
19 | MessageReq = userMessagePb.MessageReq
20 | MessageRes = userMessagePb.MessageRes
21 |
22 | UserMessage interface {
23 | // -----------------------SendMessage-----------------------
24 | SendMessage(ctx context.Context, in *MessageReq, opts ...grpc.CallOption) (*MessageRes, error)
25 | // -----------------------GetMessageList-----------------------
26 | GetMessageList(ctx context.Context, in *MessageListReq, opts ...grpc.CallOption) (*MessageListRes, error)
27 | }
28 |
29 | defaultUserMessage struct {
30 | cli zrpc.Client
31 | }
32 | )
33 |
34 | func NewUserMessage(cli zrpc.Client) UserMessage {
35 | return &defaultUserMessage{
36 | cli: cli,
37 | }
38 | }
39 |
40 | // -----------------------SendMessage-----------------------
41 | func (m *defaultUserMessage) SendMessage(ctx context.Context, in *MessageReq, opts ...grpc.CallOption) (*MessageRes, error) {
42 | client := userMessagePb.NewUserMessageClient(m.cli.Conn())
43 | return client.SendMessage(ctx, in, opts...)
44 | }
45 |
46 | // -----------------------GetMessageList-----------------------
47 | func (m *defaultUserMessage) GetMessageList(ctx context.Context, in *MessageListReq, opts ...grpc.CallOption) (*MessageListRes, error) {
48 | client := userMessagePb.NewUserMessageClient(m.cli.Conn())
49 | return client.GetMessageList(ctx, in, opts...)
50 | }
51 |
--------------------------------------------------------------------------------
/pkg/minio-client/etc/minioclient.yaml:
--------------------------------------------------------------------------------
1 | Name: minioclient.rpc
2 | ListenOn: 0.0.0.0:30001
3 | Etcd:
4 | Hosts:
5 | - etcd.etcd.svc.cluster.local:2379
6 | Key: minioclient.rpc
7 |
--------------------------------------------------------------------------------
/pkg/minio-client/internal/config/config.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import "github.com/zeromicro/go-zero/zrpc"
4 |
5 | type Config struct {
6 | zrpc.RpcServerConf
7 | }
8 |
--------------------------------------------------------------------------------
/pkg/minio-client/internal/logic/uploadfilelogic.go:
--------------------------------------------------------------------------------
1 | package logic
2 |
3 | import (
4 | "bytes"
5 | "context"
6 | "douyin/pkg/logger"
7 | "douyin/pkg/minio-client/internal/svc"
8 | "douyin/pkg/minio-client/types/minio-client"
9 | "fmt"
10 | "time"
11 |
12 | "github.com/zeromicro/go-zero/core/logx"
13 | )
14 |
15 | type UploadFileLogic struct {
16 | ctx context.Context
17 | svcCtx *svc.ServiceContext
18 | logx.Logger
19 | }
20 |
21 | func NewUploadFileLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UploadFileLogic {
22 | return &UploadFileLogic{
23 | ctx: ctx,
24 | svcCtx: svcCtx,
25 | Logger: logx.WithContext(ctx),
26 | }
27 | }
28 |
29 | func (l *UploadFileLogic) UploadFile(in *minio_client.UploadFileRequest) (*minio_client.UploadFileReply, error) {
30 | pngFrame, err := getVideoFrame(in.Data, 1)
31 | if err != nil {
32 | logger.Errorf("Fail to get video frame, err: %v", err)
33 | return nil, err
34 | }
35 |
36 | client := makeMinIOClient()
37 | bucket := "douyin"
38 | if in.Data == nil || in.Title == "" {
39 | logger.Error("UploadFile's parameter cant be nil")
40 | panic("UploadFile's parameter cant be nil")
41 | }
42 |
43 | videoUrl, err := uploadFile(client, bytes.NewReader(in.Data), fmt.Sprintf("%v.mp4", time.Now().Unix()), bucket, "")
44 | if err != nil {
45 | logger.Errorf("Fail to upload video file, err: %v", err)
46 | return nil, err
47 | }
48 |
49 | frameUrl, err := uploadFile(client, pngFrame, fmt.Sprintf("%v.png", time.Now().Unix()), bucket, "")
50 | if err != nil {
51 | logger.Errorf("Fail to upload frame file, err: %v, err")
52 | return nil, err
53 | }
54 |
55 | return &minio_client.UploadFileReply{
56 | Success: true,
57 | VideoUrl: videoUrl,
58 | FrontImgUrl: frameUrl,
59 | }, nil
60 | }
61 |
--------------------------------------------------------------------------------
/pkg/minio-client/internal/logic/utils.go:
--------------------------------------------------------------------------------
1 | package logic
2 |
3 | import (
4 | "bytes"
5 | "context"
6 | "douyin/pkg/logger"
7 | "fmt"
8 | "github.com/minio/minio-go/v7"
9 | ffmpeg "github.com/u2takey/ffmpeg-go"
10 | "os"
11 | )
12 |
13 | import (
14 | "github.com/minio/minio-go/v7/pkg/credentials"
15 | )
16 |
17 | func makeMinIOClient() *minio.Client {
18 | var endpoint = "minio.minio.svc.cluster.local:9000"
19 | var accessKeyID = "douyin"
20 | var secretAccessKey = "douyin_pass"
21 |
22 | // Create a client, all operations must use it
23 | client, err := minio.New(endpoint, &minio.Options{
24 | Creds: credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
25 | })
26 | if err != nil {
27 | logger.Errorf("Make MinIO client error:", err)
28 | panic(err)
29 | }
30 | return client
31 | }
32 |
33 | func getVideoFrame(data []byte, frame int) (*bytes.Reader, error) {
34 | tmp, _ := os.Create("tmp.mp4")
35 | tmp.Write(data)
36 | tmp.Close()
37 |
38 | pngBuffer := bytes.NewBuffer(nil)
39 | err := ffmpeg.Input("tmp.mp4").Filter("select", ffmpeg.Args{fmt.Sprintf("gte(n,%d)", frame)}).
40 | Output("pipe:", ffmpeg.KwArgs{"vframes": 1, "format": "image2", "vcodec": "mjpeg"}).
41 | WithOutput(pngBuffer).Run()
42 | if err != nil {
43 | return nil, err
44 | }
45 |
46 | return bytes.NewReader(pngBuffer.Bytes()), nil
47 | }
48 |
49 | func uploadFile(client *minio.Client, reader *bytes.Reader, fileName string, bucket string, contentType string) (string, error) {
50 | _, err := client.PutObject(context.Background(),
51 | bucket, fileName, reader, reader.Size(), minio.PutObjectOptions{})
52 | if err != nil {
53 | logger.Errorf("Fail to upload file, name: %v, err: %v", fileName, err)
54 | return "", err
55 | }
56 |
57 | url := fmt.Sprintf("http://192.168.10.2:9000/%s/%s", bucket, fileName)
58 |
59 | logger.InfoF("Success to upload object to minio, fileName: %v, url: %v", fileName, url)
60 | return url, nil
61 | }
62 |
--------------------------------------------------------------------------------
/pkg/minio-client/internal/server/minioclientserver.go:
--------------------------------------------------------------------------------
1 | // Code generated by goctl. DO NOT EDIT.
2 | // Source: minio-client.proto
3 |
4 | package server
5 |
6 | import (
7 | "context"
8 |
9 | "douyin/pkg/minio-client/internal/logic"
10 | "douyin/pkg/minio-client/internal/svc"
11 | "douyin/pkg/minio-client/types/minio-client"
12 | )
13 |
14 | type MinIOClientServer struct {
15 | svcCtx *svc.ServiceContext
16 | minio_client.UnimplementedMinIOClientServer
17 | }
18 |
19 | func NewMinIOClientServer(svcCtx *svc.ServiceContext) *MinIOClientServer {
20 | return &MinIOClientServer{
21 | svcCtx: svcCtx,
22 | }
23 | }
24 |
25 | func (s *MinIOClientServer) UploadFile(ctx context.Context, in *minio_client.UploadFileRequest) (*minio_client.UploadFileReply, error) {
26 | l := logic.NewUploadFileLogic(ctx, s.svcCtx)
27 | return l.UploadFile(in)
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/minio-client/internal/svc/servicecontext.go:
--------------------------------------------------------------------------------
1 | package svc
2 |
3 | import "douyin/pkg/minio-client/internal/config"
4 |
5 | type ServiceContext struct {
6 | Config config.Config
7 | }
8 |
9 | func NewServiceContext(c config.Config) *ServiceContext {
10 | return &ServiceContext{
11 | Config: c,
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/pkg/minio-client/minioclient.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 | "fmt"
6 |
7 | "douyin/pkg/minio-client/internal/config"
8 | "douyin/pkg/minio-client/internal/server"
9 | "douyin/pkg/minio-client/internal/svc"
10 | "douyin/pkg/minio-client/types/minio-client"
11 |
12 | "github.com/zeromicro/go-zero/core/conf"
13 | "github.com/zeromicro/go-zero/core/service"
14 | "github.com/zeromicro/go-zero/zrpc"
15 | "google.golang.org/grpc"
16 | "google.golang.org/grpc/reflection"
17 | )
18 |
19 | var configFile = flag.String("f", "etc/minioclient.yaml", "the config file")
20 |
21 | func main() {
22 | flag.Parse()
23 |
24 | var c config.Config
25 | conf.MustLoad(*configFile, &c)
26 | ctx := svc.NewServiceContext(c)
27 |
28 | s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
29 | minio_client.RegisterMinIOClientServer(grpcServer, server.NewMinIOClientServer(ctx))
30 |
31 | if c.Mode == service.DevMode || c.Mode == service.TestMode {
32 | reflection.Register(grpcServer)
33 | }
34 | })
35 | defer s.Stop()
36 |
37 | fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
38 | s.Start()
39 | }
40 |
--------------------------------------------------------------------------------
/pkg/minio-client/minioclient/minioclient.go:
--------------------------------------------------------------------------------
1 | // Code generated by goctl. DO NOT EDIT.
2 | // Source: minio-client.proto
3 |
4 | package minioclient
5 |
6 | import (
7 | "context"
8 |
9 | "douyin/pkg/minio-client/types/minio-client"
10 |
11 | "github.com/zeromicro/go-zero/zrpc"
12 | "google.golang.org/grpc"
13 | )
14 |
15 | type (
16 | UploadFileReply = minio_client.UploadFileReply
17 | UploadFileRequest = minio_client.UploadFileRequest
18 |
19 | MinIOClient interface {
20 | UploadFile(ctx context.Context, in *UploadFileRequest, opts ...grpc.CallOption) (*UploadFileReply, error)
21 | }
22 |
23 | defaultMinIOClient struct {
24 | cli zrpc.Client
25 | }
26 | )
27 |
28 | func NewMinIOClient(cli zrpc.Client) MinIOClient {
29 | return &defaultMinIOClient{
30 | cli: cli,
31 | }
32 | }
33 |
34 | func (m *defaultMinIOClient) UploadFile(ctx context.Context, in *UploadFileRequest, opts ...grpc.CallOption) (*UploadFileReply, error) {
35 | client := minio_client.NewMinIOClientClient(m.cli.Conn())
36 | return client.UploadFile(ctx, in, opts...)
37 | }
38 |
--------------------------------------------------------------------------------
/pkg/minio-client/proto/minio-client.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package minio_client;
4 |
5 | option go_package="./minio-client";
6 |
7 | message UploadFileRequest {
8 | bytes data = 1; // 视频数据
9 | string title = 2; // 视频名称(也是路径direction/filename)
10 | }
11 |
12 | message UploadFileReply {
13 | bool success = 1;
14 | string videoUrl = 2;
15 | string frontImgUrl = 3;
16 | }
17 |
18 | service MinIOClient {
19 | rpc UploadFile(UploadFileRequest) returns(UploadFileReply);
20 | }
21 |
--------------------------------------------------------------------------------
/pkg/mq/etc/mq.yaml:
--------------------------------------------------------------------------------
1 | Name: mq
2 | Host: 0.0.0.0
3 | Port: 3001
4 | Mode: dev
5 |
6 | UserCommentOptServiceConf:
7 | Name: UserCommentOptService
8 | Brokers:
9 | - kafka.kafka.svc.cluster.local:9092
10 | Group: UserCommentOptService-group
11 | Topic: UserCommentOptService-topic
12 | Offset: first
13 | Consumers: 1
14 | Processors: 1
15 |
16 | UserFollowOptServiceConf:
17 | Name: UserFollowOptService
18 | Brokers:
19 | - kafka.kafka.svc.cluster.local:9092
20 | Group: UserFollowOptService-group
21 | Topic: UserFollowOptService-topic
22 | Offset: first
23 | Consumers: 1
24 | Processors: 1
25 |
26 | UserFavoriteOptServiceConf:
27 | Name: UserFavoriteOptService
28 | Brokers:
29 | - kafka.kafka.svc.cluster.local:9092
30 | Group: UserFavoriteOptService-group
31 | Topic: UserFavoriteOptService-topic
32 | Offset: first
33 | Consumers: 1
34 | Processors: 1
35 |
36 | UserCommentRpc:
37 | Etcd:
38 | Hosts:
39 | - etcd.etcd.svc.cluster.local:2379
40 | Key: usercomment.rpc
41 | NonBlock: true
42 |
43 | UserFavoriteRpc:
44 | Etcd:
45 | Hosts:
46 | - etcd.etcd.svc.cluster.local:2379
47 | Key: useropt.rpc
48 |
49 | UserFollowRpc:
50 | Etcd:
51 | Hosts:
52 | - etcd.etcd.svc.cluster.local:2379
53 | Key: follow.rpc
54 |
55 | RedisCacheConf:
56 | Host: redis-master.redis.svc.cluster.local:6379
57 | Pass: redispwd123
58 |
--------------------------------------------------------------------------------
/pkg/mq/internal/config/config.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import (
4 | "github.com/zeromicro/go-queue/kq"
5 | "github.com/zeromicro/go-zero/core/service"
6 | "github.com/zeromicro/go-zero/core/stores/redis"
7 | "github.com/zeromicro/go-zero/zrpc"
8 | )
9 |
10 | type Config struct {
11 | service.ServiceConf
12 |
13 | // redis
14 | RedisCacheConf redis.RedisConf
15 |
16 | // kq : pub sub
17 | UserCommentOptServiceConf kq.KqConf
18 | UserFavoriteOptServiceConf kq.KqConf
19 | UserFollowOptServiceConf kq.KqConf
20 |
21 | // rpc
22 | UserCommentRpc zrpc.RpcClientConf
23 | UserFavoriteRpc zrpc.RpcClientConf
24 | UserFollowRpc zrpc.RpcClientConf
25 | }
26 |
--------------------------------------------------------------------------------
/pkg/mq/internal/listen/kqMqs.go:
--------------------------------------------------------------------------------
1 | package listen
2 |
3 | import (
4 | "context"
5 | "douyin/pkg/mq/internal/config"
6 | kqMq "douyin/pkg/mq/internal/mqs/kq"
7 | "douyin/pkg/mq/internal/svc"
8 | "github.com/zeromicro/go-queue/kq"
9 | "github.com/zeromicro/go-zero/core/service"
10 | )
11 |
12 | // pub sub use kq (kafka)
13 | func KqMqs(c config.Config, ctx context.Context, svcContext *svc.ServiceContext) []service.Service {
14 |
15 | return []service.Service{
16 | //Listening for changes in consumption flow status
17 | kq.MustNewQueue(c.UserCommentOptServiceConf, kqMq.NewUserCommentUpdateMq(ctx, svcContext)),
18 | kq.MustNewQueue(c.UserFavoriteOptServiceConf, kqMq.NewUserFavoriteUpdateMq(ctx, svcContext)),
19 | kq.MustNewQueue(c.UserFollowOptServiceConf, kqMq.NewUserFollowUpdateMq(ctx, svcContext)),
20 | //.....
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/pkg/mq/internal/listen/listen.go:
--------------------------------------------------------------------------------
1 | package listen
2 |
3 | import (
4 | "context"
5 | "douyin/pkg/mq/internal/config"
6 | "douyin/pkg/mq/internal/svc"
7 |
8 | "github.com/zeromicro/go-zero/core/service"
9 | )
10 |
11 | // back to all consumers
12 | func Mqs(c config.Config) []service.Service {
13 |
14 | svcContext := svc.NewServiceContext(c)
15 | ctx := context.Background()
16 |
17 | var services []service.Service
18 |
19 | //kq :pub sub
20 | services = append(services, KqMqs(c, ctx, svcContext)...)
21 |
22 | return services
23 | }
24 |
--------------------------------------------------------------------------------
/pkg/mq/internal/mqs/kq/userCommentUpdate.go:
--------------------------------------------------------------------------------
1 | package kq
2 |
3 | import (
4 | "context"
5 | "douyin/common/messageTypes"
6 | "douyin/pkg/comment/usercomment"
7 | "douyin/pkg/mq/internal/svc"
8 | "encoding/json"
9 | "fmt"
10 | "github.com/pkg/errors"
11 | "github.com/zeromicro/go-zero/core/logx"
12 | )
13 |
14 | /*
15 | Listening to the payment flow status change notification message queue
16 | */
17 | type UserCommentOpt struct {
18 | ctx context.Context
19 | svcCtx *svc.ServiceContext
20 | }
21 |
22 | func NewUserCommentUpdateMq(ctx context.Context, svcCtx *svc.ServiceContext) *UserCommentOpt {
23 | return &UserCommentOpt{
24 | ctx: ctx,
25 | svcCtx: svcCtx,
26 | }
27 | }
28 |
29 | func (l *UserCommentOpt) Consume(_, val string) error {
30 | var message messageTypes.UserCommentOptMessage
31 | if err := json.Unmarshal([]byte(val), &message); err != nil {
32 | logx.WithContext(l.ctx).Error("UserCommentOptMessage->Consume Unmarshal err : %v , val : %s", err, val)
33 | return err
34 | }
35 |
36 | if err := l.execService(message); err != nil {
37 | logx.WithContext(l.ctx).Error("UserCommentOptMessage->execService err : %v , val : %s , message:%+v", err, val, message)
38 | return err
39 | }
40 |
41 | return nil
42 | }
43 |
44 | // 处理逻辑
45 | func (l *UserCommentOpt) execService(message messageTypes.UserCommentOptMessage) error {
46 | fmt.Printf("消费者开始消费------------------------------\n")
47 | if message.ActionType != messageTypes.ActionADD && message.ActionType != messageTypes.ActionCancel {
48 | return errors.New("UserCommentOptMessage->execService getActionType err")
49 | }
50 |
51 | // 调用rpc 更新user_comment表
52 | _, err := l.svcCtx.UserCommentRpc.UpdateCommentStatus(l.ctx, &usercomment.UpdateCommentStatusReq{
53 | VideoId: message.VideoId,
54 | UserId: message.UserId,
55 | Content: message.CommentText,
56 | CommentId: message.CommentId,
57 | ActionType: message.ActionType,
58 | })
59 |
60 | if err != nil {
61 | logx.Errorf("UserCommentOptMessage->execService err : %v , val : %s , message:%+v", err, message)
62 | return err
63 | }
64 | fmt.Printf("消费者消费成功------------------------------\n")
65 | return nil
66 | }
67 |
--------------------------------------------------------------------------------
/pkg/mq/internal/mqs/kq/userFavoriteUpdate.go:
--------------------------------------------------------------------------------
1 | package kq
2 |
3 | import (
4 | "context"
5 | "douyin/common/messageTypes"
6 | "douyin/pkg/favorite/useroptservice"
7 | "douyin/pkg/mq/internal/svc"
8 | "encoding/json"
9 | "errors"
10 | "fmt"
11 | "github.com/zeromicro/go-zero/core/logx"
12 | )
13 |
14 | /*
15 | Listening to the payment flow status change notification message queue
16 | */
17 | type UserFavoriteOpt struct {
18 | ctx context.Context
19 | svcCtx *svc.ServiceContext
20 | }
21 |
22 | func NewUserFavoriteUpdateMq(ctx context.Context, svcCtx *svc.ServiceContext) *UserFavoriteOpt {
23 | return &UserFavoriteOpt{
24 | ctx: ctx,
25 | svcCtx: svcCtx,
26 | }
27 | }
28 |
29 | func (l *UserFavoriteOpt) Consume(_, val string) error {
30 | var message messageTypes.UserFavoriteOptMessage
31 |
32 | if err := json.Unmarshal([]byte(val), &message); err != nil {
33 | logx.WithContext(l.ctx).Error("UserFavoriteOptMessage->Consume Unmarshal err : %v , val : %s", err, val)
34 | return err
35 | }
36 |
37 | if err := l.execService(message); err != nil {
38 | logx.WithContext(l.ctx).Error("UserFavoriteOptMessage->execService err : %v , val : %s , message:%+v", err, val, message)
39 | logx.Errorf("UserFavoriteOptMessage->execService err : %v , val : %s , message:%+v", err, val, message)
40 | return err
41 | }
42 | return nil
43 | }
44 |
45 | // 处理逻辑
46 | func (l *UserFavoriteOpt) execService(message messageTypes.UserFavoriteOptMessage) error {
47 | fmt.Printf("消费者开始消费------------------------------\n")
48 | if message.ActionType != messageTypes.ActionADD && message.ActionType != messageTypes.ActionCancel {
49 | return errors.New("UserCommentOptMessage->execService getActionType err")
50 | }
51 |
52 | _, err := l.svcCtx.UserFavoriteRpc.UpdateFavoriteStatus(l.ctx, &useroptservice.UpdateFavoriteStatusReq{
53 | VideoId: message.VideoId,
54 | UserId: message.UserId,
55 | ActionType: message.ActionType,
56 | })
57 |
58 | if err != nil {
59 | logx.Errorf("UserCommentOptMessage->execService err : %v , val : %s , message:%+v", err, message)
60 | return err
61 | }
62 | fmt.Printf("消费者消费成功------------------------------\n")
63 | return nil
64 | }
65 |
--------------------------------------------------------------------------------
/pkg/mq/internal/mqs/kq/userFollowUpdate.go:
--------------------------------------------------------------------------------
1 | package kq
2 |
3 | import (
4 | "context"
5 | "douyin/common/messageTypes"
6 | "douyin/pkg/follow/followservice"
7 | "douyin/pkg/mq/internal/svc"
8 | "encoding/json"
9 | "errors"
10 | "fmt"
11 | "github.com/zeromicro/go-zero/core/logx"
12 | )
13 |
14 | /*
15 | Listening to the payment flow status change notification message queue
16 | */
17 | type UserFollowOpt struct {
18 | ctx context.Context
19 | svcCtx *svc.ServiceContext
20 | }
21 |
22 | func NewUserFollowUpdateMq(ctx context.Context, svcCtx *svc.ServiceContext) *UserFollowOpt {
23 | return &UserFollowOpt{
24 | ctx: ctx,
25 | svcCtx: svcCtx,
26 | }
27 | }
28 |
29 | func (l *UserFollowOpt) Consume(_, val string) error {
30 | var message messageTypes.UserFollowOptMessage
31 |
32 | if err := json.Unmarshal([]byte(val), &message); err != nil {
33 | logx.WithContext(l.ctx).Error("UserFollowOptMessage->Consume Unmarshal err : %v , val : %s", err, val)
34 | return err
35 | }
36 |
37 | if err := l.execService(message); err != nil {
38 | logx.WithContext(l.ctx).Error("UserFollowOptMessage->execService err : %v , val : %s , message:%+v", err, val, message)
39 | logx.Errorf("UserFollowOptMessage->execService err : %v , val : %s , message:%+v", err, val, message)
40 | return err
41 | }
42 | return nil
43 | }
44 |
45 | // 处理逻辑
46 | func (l *UserFollowOpt) execService(message messageTypes.UserFollowOptMessage) error {
47 | if message.ActionType != messageTypes.ActionADD && message.ActionType != messageTypes.ActionCancel {
48 | return errors.New("UserCommentOptMessage->execService getActionType err")
49 | }
50 |
51 | _, err := l.svcCtx.UserFollowRPC.Follow(l.ctx, &followservice.FollowReq{
52 | ToUserId: message.ToUserId,
53 | ActionType: message.ActionType,
54 | UserId: message.UserId,
55 | })
56 |
57 | if err != nil {
58 | logx.Errorf("UserFollowOptMessage->execService err : %v , val : %s , message:%+v", err, message)
59 | return err
60 | }
61 | fmt.Printf("消费者消费成功------------------------------\n")
62 | return nil
63 | }
64 |
--------------------------------------------------------------------------------
/pkg/mq/internal/svc/serviceContext.go:
--------------------------------------------------------------------------------
1 | package svc
2 |
3 | import (
4 | "douyin/pkg/comment/usercomment"
5 | "douyin/pkg/favorite/useroptservice"
6 | "douyin/pkg/follow/followservice"
7 | "douyin/pkg/mq/internal/config"
8 | "github.com/zeromicro/go-zero/zrpc"
9 | )
10 |
11 | type ServiceContext struct {
12 | Config config.Config
13 | UserCommentRpc usercomment.UserComment
14 | UserFavoriteRpc useroptservice.UserOptService
15 | UserFollowRPC followservice.FollowService
16 | }
17 |
18 | func NewServiceContext(c config.Config) *ServiceContext {
19 | return &ServiceContext{
20 | Config: c,
21 | UserCommentRpc: usercomment.NewUserComment(zrpc.MustNewClient(c.UserCommentRpc)),
22 | UserFavoriteRpc: useroptservice.NewUserOptService(zrpc.MustNewClient(c.UserFavoriteRpc)),
23 | UserFollowRPC: followservice.NewFollowService(zrpc.MustNewClient(c.UserFollowRpc)),
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/pkg/mq/mq.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "douyin/pkg/mq/internal/config"
5 | "douyin/pkg/mq/internal/listen"
6 | "flag"
7 | "github.com/zeromicro/go-zero/core/conf"
8 | "github.com/zeromicro/go-zero/core/service"
9 | )
10 |
11 | var configFile = flag.String("f", "etc/mq.yaml", "Specify the config file")
12 |
13 | func main() {
14 | flag.Parse()
15 | var c config.Config
16 |
17 | conf.MustLoad(*configFile, &c)
18 |
19 | // log、prometheus、trace、metricsUrl.
20 | if err := c.SetUp(); err != nil {
21 | panic(err)
22 | }
23 |
24 | serviceGroup := service.NewServiceGroup()
25 | defer serviceGroup.Stop()
26 | for _, mq := range listen.Mqs(c) {
27 | serviceGroup.Add(mq)
28 | }
29 |
30 | serviceGroup.Start()
31 | }
32 |
--------------------------------------------------------------------------------
/pkg/sql/01_test.go:
--------------------------------------------------------------------------------
1 | package pack
2 |
3 | import (
4 | "context"
5 | "douyin/pkg/sql/dal/model"
6 | "douyin/pkg/sql/dal/query"
7 | "douyin/pkg/sql/pack"
8 | "testing"
9 | )
10 |
11 | func TestTransaction(t *testing.T) {
12 | db := pack.GetConn()
13 | q := pack.GetQuery(db)
14 |
15 | err := q.Transaction(func(tx *query.Query) error {
16 | e := tx.WithContext(context.Background()).Chat.Create(
17 | &model.Chat{
18 | Sender: 1,
19 | Receiver: 2,
20 | Msg: "hahahah"},
21 | )
22 | if e != nil {
23 | return e
24 | }
25 |
26 | e = tx.Video.WithContext(context.Background()).Create(&model.Video{
27 | Title: "let other all be null, coming error?",
28 | })
29 | // no error will be a error
30 | if e == nil {
31 | return e
32 | }
33 |
34 | return nil
35 | })
36 | pack.Check(err)
37 |
38 | }
39 |
40 | func TestWithHandle(t *testing.T) {
41 | // User
42 | db := pack.GetConn()
43 | {
44 | icd := pack.GetIChatDO(db)
45 | icd.Create(&model.Chat{
46 | Msg: "[01_test::TestWithHandle]",
47 | Sender: 1,
48 | Receiver: 2,
49 | })
50 |
51 | Chats, err := icd.FindByReceiver(2)
52 | check(err, t)
53 |
54 | bFound := false
55 | for _, chat := range Chats {
56 | if chat.Msg == "[01_test::TestWithHandle]" &&
57 | chat.Sender == 1 &&
58 | chat.Receiver == 2 {
59 | bFound = true
60 | break
61 | }
62 | }
63 | if !bFound {
64 | t.Error("Did not find the message that I send!!!!")
65 | }
66 |
67 | }
68 | }
69 |
70 | func check(e error, t *testing.T) {
71 | if e != nil {
72 | t.Error(e)
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/pkg/sql/README.md:
--------------------------------------------------------------------------------
1 | # package sql
2 |
3 | > Query methods were defined in `pkg/dal/methos.go`
4 |
5 | > Please rerun `make mysql-regenerate-codes` or `cmd/mysqlgen/gen.go` to update codes
6 |
7 | You can get the specific `handle` of a table, or a raw `query` from pack.
8 |
9 | For more infos, see tests.
10 |
11 |
12 |
--------------------------------------------------------------------------------
/pkg/sql/dal/dal.go:
--------------------------------------------------------------------------------
1 | package dal
2 |
3 | import (
4 | "fmt"
5 | "sync"
6 |
7 | constantx "douyin/pkg/constant"
8 |
9 | "gorm.io/driver/mysql"
10 | "gorm.io/gorm"
11 | )
12 |
13 | var DBI *gorm.DB
14 | var once sync.Once
15 |
16 | func init() {
17 | once.Do(func() {
18 | DBI = ConnectDB()
19 | err := DBI.AutoMigrate()
20 | if err != nil {
21 | panic(err)
22 | }
23 | })
24 | }
25 |
26 | func ConnectDB() (conn *gorm.DB) {
27 | conn, err := gorm.Open(mysql.Open(constantx.MYSQL_Dsn), &gorm.Config{
28 | SkipDefaultTransaction: constantx.MYSQL_SkipDefaultTransaction, // close default tx
29 | PrepareStmt: constantx.MYSQL_PrepareStmt, // cache precompile sentence
30 | })
31 | if err != nil {
32 | panic(fmt.Errorf("cannot setup db conn: %v", err))
33 | }
34 | if conn == nil {
35 | panic("conn is null")
36 | }
37 | return conn
38 | }
39 |
--------------------------------------------------------------------------------
/pkg/sql/dal/method.go:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 |
4 | @Desc: Define your sql methods here
5 |
6 | *
7 | */
8 | package dal
9 |
10 | import (
11 | "time"
12 |
13 | "gorm.io/gen"
14 | )
15 |
16 | type DefaultMethod interface {
17 |
18 | // sql(select * from @@table)
19 | FindAll() ([]gen.T, error)
20 |
21 | // Where("id=@id")
22 | FindById(id uint) (gen.T, error)
23 |
24 | // Where("removed=@removed")
25 | FindByRemoved(removed uint) ([]gen.T, error)
26 | }
27 |
28 | type UserMethod interface {
29 |
30 | // Where("username=@username")
31 | FindByUsernmae(username string) ([]gen.T, error)
32 |
33 | // Where("type=@theType")
34 | FindByType(theType uint) ([]gen.T, error)
35 |
36 | // Where("enable=@enable")
37 | FindByEnable(enable uint) ([]gen.T, error)
38 | }
39 |
40 | type ChatMethod interface {
41 |
42 | // Where("sender=@sender")
43 | FindBySender(sender uint) ([]gen.T, error)
44 |
45 | // Where("receiver=@receiver")
46 | FindByReceiver(receiver uint) ([]gen.T, error)
47 |
48 | // Where("sender=@userId or receiver=@userId")
49 | FindMessageByUserId(userId uint) ([]gen.T, error)
50 | }
51 |
52 | type FollowMethod interface {
53 |
54 | // Where("user_id=@userId")
55 | FindFolloweesByUserId(userId uint) ([]gen.T, error)
56 |
57 | // Where("fun_id=@userId")
58 | FindFollowersByUserId(userId uint) ([]gen.T, error)
59 | }
60 |
61 | type VideoMethod interface {
62 | // Where("user_id=@userId")
63 | FindByAuthor(userId uint) ([]gen.T, error)
64 |
65 | // Where("play_url=@playUrl")
66 | FindByPlayUrl(playUrl string) (gen.T, error)
67 |
68 | // Where("time=@time")
69 | FindByTime(time uint) ([]gen.T, error)
70 | // Where("time>=@time")
71 | FindByTimeLongerThan(time uint) ([]gen.T, error)
72 |
73 | // where("title=@title or title like @title")
74 | FindByTitle(title string) ([]gen.T, error)
75 | }
76 |
77 | type CommentMethod interface {
78 |
79 | // where("user_id=@userId")
80 | FindByUserId(userId uint) ([]gen.T, error)
81 |
82 | // Where("video_id=@videoId")
83 | FindByVideoId(videoId uint) ([]gen.T, error)
84 |
85 | // Where("create_time >= @createTime")
86 | FindNewerThanCreateTime(createTime *time.Time)
87 |
88 | // Where("deleted=@deleted")
89 | FindByDeleted(deleted uint) ([]gen.T, error)
90 | }
91 |
92 | type FavoriteMethod interface {
93 | // where("user_id=@userId")
94 | FindByUserId(userId uint) ([]gen.T, error)
95 |
96 | // Where("video_id=@videoId")
97 | FindByVideoId(videoId uint) ([]gen.T, error)
98 | }
99 |
--------------------------------------------------------------------------------
/pkg/sql/dal/model/chat.gen.go:
--------------------------------------------------------------------------------
1 | // Code generated by gorm.io/gen. DO NOT EDIT.
2 | // Code generated by gorm.io/gen. DO NOT EDIT.
3 | // Code generated by gorm.io/gen. DO NOT EDIT.
4 |
5 | package model
6 |
7 | import (
8 | "time"
9 | )
10 |
11 | const TableNameChat = "chat"
12 |
13 | // Chat mapped from table
14 | type Chat struct {
15 | ID uint `gorm:"column:id;type:int;primaryKey;autoIncrement:true" json:"id"`
16 | Msg string `gorm:"column:msg;type:text;not null" json:"msg"`
17 | Sender uint `gorm:"column:sender;type:int;not null" json:"sender"`
18 | Receiver uint `gorm:"column:receiver;type:int;not null" json:"receiver"`
19 | Createtime time.Time `gorm:"column:createtime;type:datetime;not null;default:CURRENT_TIMESTAMP" json:"createtime"`
20 | }
21 |
22 | // TableName Chat's table name
23 | func (*Chat) TableName() string {
24 | return TableNameChat
25 | }
26 |
--------------------------------------------------------------------------------
/pkg/sql/dal/model/comment.gen.go:
--------------------------------------------------------------------------------
1 | // Code generated by gorm.io/gen. DO NOT EDIT.
2 | // Code generated by gorm.io/gen. DO NOT EDIT.
3 | // Code generated by gorm.io/gen. DO NOT EDIT.
4 |
5 | package model
6 |
7 | import (
8 | "time"
9 | )
10 |
11 | const TableNameComment = "comment"
12 |
13 | // Comment mapped from table
14 | type Comment struct {
15 | ID uint `gorm:"column:id;type:int;primaryKey;autoIncrement:true" json:"id"`
16 | UserID uint `gorm:"column:user_id;type:int;not null" json:"user_id"`
17 | VideoID uint `gorm:"column:video_id;type:int;not null" json:"video_id"`
18 | CreateTime time.Time `gorm:"column:create_time;type:datetime;not null;default:CURRENT_TIMESTAMP" json:"create_time"`
19 | Removed uint `gorm:"column:removed;type:tinyint;not null" json:"removed"`
20 | Deleted uint `gorm:"column:deleted;type:tinyint;not null" json:"deleted"`
21 | Content string `gorm:"column:content;type:text;not null" json:"content"`
22 | }
23 |
24 | // TableName Comment's table name
25 | func (*Comment) TableName() string {
26 | return TableNameComment
27 | }
28 |
--------------------------------------------------------------------------------
/pkg/sql/dal/model/favorite.gen.go:
--------------------------------------------------------------------------------
1 | // Code generated by gorm.io/gen. DO NOT EDIT.
2 | // Code generated by gorm.io/gen. DO NOT EDIT.
3 | // Code generated by gorm.io/gen. DO NOT EDIT.
4 |
5 | package model
6 |
7 | const TableNameFavorite = "favorite"
8 |
9 | // Favorite mapped from table
10 | type Favorite struct {
11 | ID uint `gorm:"column:id;type:int;primaryKey;autoIncrement:true" json:"id"`
12 | VideoID uint `gorm:"column:video_id;type:int;not null" json:"video_id"`
13 | UserID uint `gorm:"column:user_id;type:int;not null" json:"user_id"`
14 | Removed uint `gorm:"column:removed;type:tinyint;not null" json:"removed"`
15 | }
16 |
17 | // TableName Favorite's table name
18 | func (*Favorite) TableName() string {
19 | return TableNameFavorite
20 | }
21 |
--------------------------------------------------------------------------------
/pkg/sql/dal/model/follow.gen.go:
--------------------------------------------------------------------------------
1 | // Code generated by gorm.io/gen. DO NOT EDIT.
2 | // Code generated by gorm.io/gen. DO NOT EDIT.
3 | // Code generated by gorm.io/gen. DO NOT EDIT.
4 |
5 | package model
6 |
7 | const TableNameFollow = "follow"
8 |
9 | // Follow mapped from table
10 | type Follow struct {
11 | ID uint `gorm:"column:id;type:int;primaryKey;autoIncrement:true" json:"id"`
12 | UserID uint `gorm:"column:user_id;type:int" json:"user_id"`
13 | FunID uint `gorm:"column:fun_id;type:int;not null" json:"fun_id"`
14 | Removed uint `gorm:"column:removed;type:tinyint;not null" json:"removed"`
15 | Msg string `gorm:"column:msg;type:text" json:"msg"`
16 | }
17 |
18 | // TableName Follow's table name
19 | func (*Follow) TableName() string {
20 | return TableNameFollow
21 | }
22 |
--------------------------------------------------------------------------------
/pkg/sql/dal/model/user.gen.go:
--------------------------------------------------------------------------------
1 | // Code generated by gorm.io/gen. DO NOT EDIT.
2 | // Code generated by gorm.io/gen. DO NOT EDIT.
3 | // Code generated by gorm.io/gen. DO NOT EDIT.
4 |
5 | package model
6 |
7 | import (
8 | "time"
9 | )
10 |
11 | const TableNameUser = "user"
12 |
13 | // User mapped from table
14 | type User struct {
15 | ID uint `gorm:"column:id;type:int;primaryKey;autoIncrement:true" json:"id"`
16 | Username string `gorm:"column:username;type:varchar(32);not null" json:"username"`
17 | Password string `gorm:"column:password;type:varchar(32);not null" json:"password"`
18 | Enable uint `gorm:"column:enable;type:tinyint;default:1" json:"enable"`
19 | Type uint `gorm:"column:type;type:tinyint;not null" json:"type"`
20 | LoginTime time.Time `gorm:"column:login_time;type:datetime;default:CURRENT_TIMESTAMP" json:"login_time"`
21 | CreateTime time.Time `gorm:"column:create_time;type:timestamp;default:CURRENT_TIMESTAMP" json:"create_time"`
22 | }
23 |
24 | // TableName User's table name
25 | func (*User) TableName() string {
26 | return TableNameUser
27 | }
28 |
--------------------------------------------------------------------------------
/pkg/sql/dal/model/video.gen.go:
--------------------------------------------------------------------------------
1 | // Code generated by gorm.io/gen. DO NOT EDIT.
2 | // Code generated by gorm.io/gen. DO NOT EDIT.
3 | // Code generated by gorm.io/gen. DO NOT EDIT.
4 |
5 | package model
6 |
7 | const TableNameVideo = "video"
8 |
9 | // Video mapped from table