Merge branch 'feature/mir' into feature/lightship

pull/198/head
Michael Li 2 years ago
commit d6e4b794ca
No known key found for this signature in database

2
.gitignore vendored

@ -1,7 +1,7 @@
.idea
.vscode
!*.example
config.yaml
/config.yaml
*.log
paopao-ce*
/release

@ -68,6 +68,28 @@ windows-x64:
@echo Build paopao-ce [windows-x64] CGO_ENABLED=$(CGO_ENABLED)
@CGO_ENABLED=$(CGO_ENABLED) GOOS=windows GOARCH=amd64 go build -trimpath -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o $(RELEASE_WINDOWS_AMD64)/$(basename $(TARGET)).exe
.PHONY: generate
generate: gen-mir gen-grpc
.PHONY: gen-mir
gen-mir:
@go generate mirc/main.go
@go fmt ./auto/api/...
.PHONY: gen-grpc
gen-grpc:
@rm -rf auto/rpc
@buf generate proto
@go fmt ./auto/rpc/...
.PHONY: proto-mod
proto-mod:
@cd proto/ && buf mod update
.PHONY: proto-lint
proto-lint:
@cd proto/ && buf lint
clean:
@go clean
@find ./release -type f -exec rm -r {} +
@ -83,7 +105,15 @@ test:
@go test ./...
pre-commit: fmt
go mod tidy
@go mod tidy
.PHONY: install-protobuf-plugins
install-protobuf-plugins:
@go install github.com/bufbuild/buf/cmd/buf@v1.11.0
@go install github.com/bufbuild/buf/cmd/protoc-gen-buf-breaking@v1.11.0
@go install github.com/bufbuild/buf/cmd/protoc-gen-buf-lint@v1.11.0
@go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
@go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
help:
@echo "make: make"

@ -39,7 +39,7 @@ Web端
更多演示请前往[官网](https://www.paopao.info)体验(谢绝灌水)
桌面端:
![](docs/proposal/.assets/00-00.png)
![](docs/proposal/.assets/000-00.png)
<p align="right">(<a href="#top">back to top</a>)</p>
@ -316,13 +316,15 @@ release/paopao-ce --no-default-features --features sqlite3,localoss,loggerfile,r
目前支持的功能集合:
| 功能项 | 类别 | 状态 | 备注 |
| ----- | ----- | ----- | ----- |
|`OldWeb` | 子服务 | 稳定(默认) | 开启旧的Web服务 |
|`Web` | 子服务 | WIP | 开启Web服务|
|`Web` | 子服务 | 内测 | 开启Web服务|
|`Admin` | 子服务 | WIP | 开启Admin后台运维服务|
|`SpaceX` | 子服务 | WIP | 开启SpaceX服务|
|`Bot` | 子服务 | WIP | 开启Bot服务|
|`NativeOBS` | 子服务 | WIP | 开启NativeOBS服务|
|`Deprecated:Web` | 子服务 | 稳定 | Deprecated(关闭) OldWeb服务|
|`Docs` | 子服务 | WIP | 开启开发者文档服务|
|`Frontend:Web` | 子服务 | 内测 | 开启独立前端服务|
|`Frontend:EmbedWeb` | 子服务 | 内测 | 开启内嵌于后端Web API服务中的前端服务|
|`Deprecated:Web` | 子服务 | 稳定 | 开启旧的Web服务|
|`Gorm` | 数据库 | 稳定(默认) | 使用[gorm](https://github.com/go-gorm/gorm)作为数据库的ORM默认使用 `Gorm` + `MySQL`组合|
|`Sqlx`| 数据库 | WIP | 使用[sqlx](https://github.com/jmoiron/sqlx)作为数据库的ORM|
|`MySQL`| 数据库 | 稳定(默认) | 使用MySQL作为数据库|
@ -494,7 +496,7 @@ jc/alimy
* `jc/*`是代码库维护者的开发分支一般包含一些局部优化或者bug修复代码有时可以直接将代码merge到`dev/beta`分支原则上不允许直接merge代码到`main`主分支。
**代码分支演进图**
![](docs/proposal/.assets/00-01.png)
![](docs/proposal/.assets/000-01.png)
### 其他说明

@ -0,0 +1,30 @@
## Roadmap for paopao-ce
paopao-ce roadmap.
### v0.2.0
* [x] add `Friendship` feature
* [ ] add `Lightship` feature
* [ ] add `Sqlx` feature
* [ ] add new `Web` service
* [x] add `Deprecated:OldWeb` feature
* [x] support run multiple service in single paopao-ce instance
* [x] use [go-mir](https://github.com/alimy/mir) optimize paopao-ce source code architecture
### Next
* [ ] add `Followship` feature
* [ ] add `Bleve` feature
* [ ] add `SpaceX` feature
* [ ] add `Bot` feature
* [ ] add `Admin` feature
* [ ] add `NativeOBS` feature
* [ ] add `Mobile` gRPC API service feature
* [ ] add admin web frontend
* [ ] add tweet forwarding support
* [ ] add tweet resource access control base on simple RBAC support
* [ ] add user's `Activation Code` feature support
* [ ] add user block feature support
* [ ] optimize current message push logic service use `ims` module
* [ ] optimize media tweet submit logic
* [ ] optimize topics service
* [ ] optimize backend data logic service(optimize database CRUD operate)
* [ ] optimize search logic service

@ -0,0 +1,140 @@
// Code generated by go-mir. DO NOT EDIT.
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin"
)
type LoginReq struct {
AgentInfo AgentInfo `json:"agent_info"`
Name string `json:"name"`
Passwd string `json:"passwd"`
}
type AgentInfo struct {
Platform string `json:"platform"`
UserAgent string `json:"user_agent"`
}
type LoginResp struct {
UserInfo
ServerInfo ServerInfo `json:"server_info"`
JwtToken string `json:"jwt_token"`
}
type ServerInfo struct {
ApiVer string `json:"api_ver"`
}
type UserInfo struct {
Name string `json:"name"`
}
type User interface {
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
Logout() mir.Error
Login(*LoginReq) (*LoginResp, mir.Error)
mustEmbedUnimplementedUserServant()
}
type UserBinding interface {
BindLogin(*gin.Context) (*LoginReq, mir.Error)
mustEmbedUnimplementedUserBinding()
}
type UserRender interface {
RenderLogout(*gin.Context, mir.Error)
RenderLogin(*gin.Context, *LoginResp, mir.Error)
mustEmbedUnimplementedUserRender()
}
// RegisterUserServant register User servant to gin
func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) {
router := e.Group("m/v1")
// use chain for router
middlewares := s.Chain()
router.Use(middlewares...)
// register routes info to router
router.Handle("POST", "/user/logout/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
r.RenderLogout(c, s.Logout())
})
router.Handle("POST", "/user/login/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindLogin(c)
if err != nil {
r.RenderLogin(c, nil, err)
return
}
resp, err := s.Login(req)
r.RenderLogin(c, resp, err)
})
}
// UnimplementedUserServant can be embedded to have forward compatible implementations.
type UnimplementedUserServant struct {
}
func (UnimplementedUserServant) Chain() gin.HandlersChain {
return nil
}
func (UnimplementedUserServant) Logout() mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedUserServant) Login(req *LoginReq) (*LoginResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedUserServant) mustEmbedUnimplementedUserServant() {}
// UnimplementedUserRender can be embedded to have forward compatible implementations.
type UnimplementedUserRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedUserRender) RenderLogout(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedUserRender) RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedUserRender) mustEmbedUnimplementedUserRender() {}
// UnimplementedUserBinding can be embedded to have forward compatible implementations.
type UnimplementedUserBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedUserBinding) BindLogin(c *gin.Context) (*LoginReq, mir.Error) {
obj := new(LoginReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedUserBinding) mustEmbedUnimplementedUserBinding() {}

@ -0,0 +1,140 @@
// Code generated by go-mir. DO NOT EDIT.
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin"
)
type LoginReq struct {
AgentInfo AgentInfo `json:"agent_info"`
Name string `json:"name"`
Passwd string `json:"passwd"`
}
type AgentInfo struct {
Platform string `json:"platform"`
UserAgent string `json:"user_agent"`
}
type LoginResp struct {
UserInfo
ServerInfo ServerInfo `json:"server_info"`
JwtToken string `json:"jwt_token"`
}
type ServerInfo struct {
ApiVer string `json:"api_ver"`
}
type UserInfo struct {
Name string `json:"name"`
}
type User interface {
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
Logout() mir.Error
Login(*LoginReq) (*LoginResp, mir.Error)
mustEmbedUnimplementedUserServant()
}
type UserBinding interface {
BindLogin(*gin.Context) (*LoginReq, mir.Error)
mustEmbedUnimplementedUserBinding()
}
type UserRender interface {
RenderLogout(*gin.Context, mir.Error)
RenderLogin(*gin.Context, *LoginResp, mir.Error)
mustEmbedUnimplementedUserRender()
}
// RegisterUserServant register User servant to gin
func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) {
router := e.Group("r/v1")
// use chain for router
middlewares := s.Chain()
router.Use(middlewares...)
// register routes info to router
router.Handle("POST", "/user/logout/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
r.RenderLogout(c, s.Logout())
})
router.Handle("POST", "/user/login/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindLogin(c)
if err != nil {
r.RenderLogin(c, nil, err)
return
}
resp, err := s.Login(req)
r.RenderLogin(c, resp, err)
})
}
// UnimplementedUserServant can be embedded to have forward compatible implementations.
type UnimplementedUserServant struct {
}
func (UnimplementedUserServant) Chain() gin.HandlersChain {
return nil
}
func (UnimplementedUserServant) Logout() mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedUserServant) Login(req *LoginReq) (*LoginResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedUserServant) mustEmbedUnimplementedUserServant() {}
// UnimplementedUserRender can be embedded to have forward compatible implementations.
type UnimplementedUserRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedUserRender) RenderLogout(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedUserRender) RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedUserRender) mustEmbedUnimplementedUserRender() {}
// UnimplementedUserBinding can be embedded to have forward compatible implementations.
type UnimplementedUserBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedUserBinding) BindLogin(c *gin.Context) (*LoginReq, mir.Error) {
obj := new(LoginReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedUserBinding) mustEmbedUnimplementedUserBinding() {}

@ -0,0 +1,150 @@
// Code generated by go-mir. DO NOT EDIT.
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin"
)
type LoginReq struct {
AgentInfo AgentInfo `json:"agent_info"`
Name string `json:"name"`
Passwd string `json:"passwd"`
}
type AgentInfo struct {
Platform string `json:"platform"`
UserAgent string `json:"user_agent"`
}
type LoginResp struct {
UserInfo
ServerInfo ServerInfo `json:"server_info"`
JwtToken string `json:"jwt_token"`
}
type ServerInfo struct {
ApiVer string `json:"api_ver"`
}
type UserInfo struct {
Name string `json:"name"`
}
type User interface {
Logout() mir.Error
Login(*LoginReq) (*LoginResp, mir.Error)
Index() mir.Error
mustEmbedUnimplementedUserServant()
}
type UserBinding interface {
BindLogin(*gin.Context) (*LoginReq, mir.Error)
mustEmbedUnimplementedUserBinding()
}
type UserRender interface {
RenderLogout(*gin.Context, mir.Error)
RenderLogin(*gin.Context, *LoginResp, mir.Error)
RenderIndex(*gin.Context, mir.Error)
mustEmbedUnimplementedUserRender()
}
// RegisterUserServant register User servant to gin
func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) {
router := e.Group("s/v1")
// register routes info to router
router.Handle("POST", "/user/logout/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
r.RenderLogout(c, s.Logout())
})
router.Handle("POST", "/user/login/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindLogin(c)
if err != nil {
r.RenderLogin(c, nil, err)
return
}
resp, err := s.Login(req)
r.RenderLogin(c, resp, err)
})
router.Handle("GET", "/index/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
r.RenderIndex(c, s.Index())
})
}
// UnimplementedUserServant can be embedded to have forward compatible implementations.
type UnimplementedUserServant struct {
}
func (UnimplementedUserServant) Logout() mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedUserServant) Login(req *LoginReq) (*LoginResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedUserServant) Index() mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedUserServant) mustEmbedUnimplementedUserServant() {}
// UnimplementedUserRender can be embedded to have forward compatible implementations.
type UnimplementedUserRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedUserRender) RenderLogout(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedUserRender) RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedUserRender) RenderIndex(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedUserRender) mustEmbedUnimplementedUserRender() {}
// UnimplementedUserBinding can be embedded to have forward compatible implementations.
type UnimplementedUserBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedUserBinding) BindLogin(c *gin.Context) (*LoginReq, mir.Error) {
obj := new(LoginReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedUserBinding) mustEmbedUnimplementedUserBinding() {}

@ -0,0 +1,95 @@
// Code generated by go-mir. DO NOT EDIT.
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/model/web"
)
type Admin interface {
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
ChangeUserStatus(*web.ChangeUserStatusReq) mir.Error
mustEmbedUnimplementedAdminServant()
}
type AdminBinding interface {
BindChangeUserStatus(*gin.Context) (*web.ChangeUserStatusReq, mir.Error)
mustEmbedUnimplementedAdminBinding()
}
type AdminRender interface {
RenderChangeUserStatus(*gin.Context, mir.Error)
mustEmbedUnimplementedAdminRender()
}
// RegisterAdminServant register Admin servant to gin
func RegisterAdminServant(e *gin.Engine, s Admin, b AdminBinding, r AdminRender) {
router := e.Group("v1")
// use chain for router
middlewares := s.Chain()
router.Use(middlewares...)
// register routes info to router
router.Handle("POST", "/admin/user/status", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindChangeUserStatus(c)
if err != nil {
r.RenderChangeUserStatus(c, err)
return
}
r.RenderChangeUserStatus(c, s.ChangeUserStatus(req))
})
}
// UnimplementedAdminServant can be embedded to have forward compatible implementations.
type UnimplementedAdminServant struct {
}
func (UnimplementedAdminServant) Chain() gin.HandlersChain {
return nil
}
func (UnimplementedAdminServant) ChangeUserStatus(req *web.ChangeUserStatusReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedAdminServant) mustEmbedUnimplementedAdminServant() {}
// UnimplementedAdminRender can be embedded to have forward compatible implementations.
type UnimplementedAdminRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedAdminRender) RenderChangeUserStatus(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedAdminRender) mustEmbedUnimplementedAdminRender() {}
// UnimplementedAdminBinding can be embedded to have forward compatible implementations.
type UnimplementedAdminBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedAdminBinding) BindChangeUserStatus(c *gin.Context) (*web.ChangeUserStatusReq, mir.Error) {
obj := new(web.ChangeUserStatusReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedAdminBinding) mustEmbedUnimplementedAdminBinding() {}

@ -0,0 +1,162 @@
// Code generated by go-mir. DO NOT EDIT.
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/model/web"
)
type AlipayPriv interface {
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
UserWalletBills(*web.UserWalletBillsReq) (*web.UserWalletBillsResp, mir.Error)
UserRechargeResult(*web.UserRechargeResultReq) (*web.UserRechargeResultResp, mir.Error)
UserRechargeLink(*web.UserRechargeLinkReq) (*web.UserRechargeLinkResp, mir.Error)
mustEmbedUnimplementedAlipayPrivServant()
}
type AlipayPrivBinding interface {
BindUserWalletBills(*gin.Context) (*web.UserWalletBillsReq, mir.Error)
BindUserRechargeResult(*gin.Context) (*web.UserRechargeResultReq, mir.Error)
BindUserRechargeLink(*gin.Context) (*web.UserRechargeLinkReq, mir.Error)
mustEmbedUnimplementedAlipayPrivBinding()
}
type AlipayPrivRender interface {
RenderUserWalletBills(*gin.Context, *web.UserWalletBillsResp, mir.Error)
RenderUserRechargeResult(*gin.Context, *web.UserRechargeResultResp, mir.Error)
RenderUserRechargeLink(*gin.Context, *web.UserRechargeLinkResp, mir.Error)
mustEmbedUnimplementedAlipayPrivRender()
}
// RegisterAlipayPrivServant register AlipayPriv servant to gin
func RegisterAlipayPrivServant(e *gin.Engine, s AlipayPriv, b AlipayPrivBinding, r AlipayPrivRender) {
router := e.Group("v1")
// use chain for router
middlewares := s.Chain()
router.Use(middlewares...)
// register routes info to router
router.Handle("GET", "/user/wallet/bills", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindUserWalletBills(c)
if err != nil {
r.RenderUserWalletBills(c, nil, err)
return
}
resp, err := s.UserWalletBills(req)
r.RenderUserWalletBills(c, resp, err)
})
router.Handle("GET", "/user/recharge", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindUserRechargeResult(c)
if err != nil {
r.RenderUserRechargeResult(c, nil, err)
return
}
resp, err := s.UserRechargeResult(req)
r.RenderUserRechargeResult(c, resp, err)
})
router.Handle("POST", "/user/recharge", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindUserRechargeLink(c)
if err != nil {
r.RenderUserRechargeLink(c, nil, err)
return
}
resp, err := s.UserRechargeLink(req)
r.RenderUserRechargeLink(c, resp, err)
})
}
// UnimplementedAlipayPrivServant can be embedded to have forward compatible implementations.
type UnimplementedAlipayPrivServant struct {
}
func (UnimplementedAlipayPrivServant) Chain() gin.HandlersChain {
return nil
}
func (UnimplementedAlipayPrivServant) UserWalletBills(req *web.UserWalletBillsReq) (*web.UserWalletBillsResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedAlipayPrivServant) UserRechargeResult(req *web.UserRechargeResultReq) (*web.UserRechargeResultResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedAlipayPrivServant) UserRechargeLink(req *web.UserRechargeLinkReq) (*web.UserRechargeLinkResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedAlipayPrivServant) mustEmbedUnimplementedAlipayPrivServant() {}
// UnimplementedAlipayPrivRender can be embedded to have forward compatible implementations.
type UnimplementedAlipayPrivRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedAlipayPrivRender) RenderUserWalletBills(c *gin.Context, data *web.UserWalletBillsResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedAlipayPrivRender) RenderUserRechargeResult(c *gin.Context, data *web.UserRechargeResultResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedAlipayPrivRender) RenderUserRechargeLink(c *gin.Context, data *web.UserRechargeLinkResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedAlipayPrivRender) mustEmbedUnimplementedAlipayPrivRender() {}
// UnimplementedAlipayPrivBinding can be embedded to have forward compatible implementations.
type UnimplementedAlipayPrivBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedAlipayPrivBinding) BindUserWalletBills(c *gin.Context) (*web.UserWalletBillsReq, mir.Error) {
obj := new(web.UserWalletBillsReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedAlipayPrivBinding) BindUserRechargeResult(c *gin.Context) (*web.UserRechargeResultReq, mir.Error) {
obj := new(web.UserRechargeResultReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedAlipayPrivBinding) BindUserRechargeLink(c *gin.Context) (*web.UserRechargeLinkReq, mir.Error) {
obj := new(web.UserRechargeLinkReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedAlipayPrivBinding) mustEmbedUnimplementedAlipayPrivBinding() {}

@ -0,0 +1,85 @@
// Code generated by go-mir. DO NOT EDIT.
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/model/web"
)
type AlipayPub interface {
AlipayNotify(*web.AlipayNotifyReq) mir.Error
mustEmbedUnimplementedAlipayPubServant()
}
type AlipayPubBinding interface {
BindAlipayNotify(*gin.Context) (*web.AlipayNotifyReq, mir.Error)
mustEmbedUnimplementedAlipayPubBinding()
}
type AlipayPubRender interface {
RenderAlipayNotify(*gin.Context, mir.Error)
mustEmbedUnimplementedAlipayPubRender()
}
// RegisterAlipayPubServant register AlipayPub servant to gin
func RegisterAlipayPubServant(e *gin.Engine, s AlipayPub, b AlipayPubBinding, r AlipayPubRender) {
router := e.Group("v1")
// register routes info to router
router.Handle("POST", "/alipay/notify", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindAlipayNotify(c)
if err != nil {
r.RenderAlipayNotify(c, err)
return
}
r.RenderAlipayNotify(c, s.AlipayNotify(req))
})
}
// UnimplementedAlipayPubServant can be embedded to have forward compatible implementations.
type UnimplementedAlipayPubServant struct {
}
func (UnimplementedAlipayPubServant) AlipayNotify(req *web.AlipayNotifyReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedAlipayPubServant) mustEmbedUnimplementedAlipayPubServant() {}
// UnimplementedAlipayPubRender can be embedded to have forward compatible implementations.
type UnimplementedAlipayPubRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedAlipayPubRender) RenderAlipayNotify(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedAlipayPubRender) mustEmbedUnimplementedAlipayPubRender() {}
// UnimplementedAlipayPubBinding can be embedded to have forward compatible implementations.
type UnimplementedAlipayPubBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedAlipayPubBinding) BindAlipayNotify(c *gin.Context) (*web.AlipayNotifyReq, mir.Error) {
obj := new(web.AlipayNotifyReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedAlipayPubBinding) mustEmbedUnimplementedAlipayPubBinding() {}

@ -0,0 +1,584 @@
// Code generated by go-mir. DO NOT EDIT.
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/model/web"
)
type Core interface {
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
TweetCollectionStatus(*web.TweetCollectionStatusReq) (*web.TweetCollectionStatusResp, mir.Error)
TweetStarStatus(*web.TweetStarStatusReq) (*web.TweetStarStatusResp, mir.Error)
SuggestTags(*web.SuggestTagsReq) (*web.SuggestTagsResp, mir.Error)
SuggestUsers(*web.SuggestUsersReq) (*web.SuggestUsersResp, mir.Error)
ChangeAvatar(*web.ChangeAvatarReq) mir.Error
ChangeNickname(*web.ChangeNicknameReq) mir.Error
ChangePassword(*web.ChangePasswordReq) mir.Error
UserPhoneBind(*web.UserPhoneBindReq) mir.Error
GetStars(*web.GetStarsReq) (*web.GetStarsResp, mir.Error)
GetCollections(*web.GetCollectionsReq) (*web.GetCollectionsResp, mir.Error)
SendUserWhisper(*web.SendWhisperReq) mir.Error
ReadMessage(*web.ReadMessageReq) mir.Error
GetMessages(*web.GetMessagesReq) (*web.GetMessagesResp, mir.Error)
GetUnreadMsgCount(*web.GetUnreadMsgCountReq) (*web.GetUnreadMsgCountResp, mir.Error)
GetUserInfo(*web.UserInfoReq) (*web.UserInfoResp, mir.Error)
SyncSearchIndex(*web.SyncSearchIndexReq) mir.Error
mustEmbedUnimplementedCoreServant()
}
type CoreBinding interface {
BindTweetCollectionStatus(*gin.Context) (*web.TweetCollectionStatusReq, mir.Error)
BindTweetStarStatus(*gin.Context) (*web.TweetStarStatusReq, mir.Error)
BindSuggestTags(*gin.Context) (*web.SuggestTagsReq, mir.Error)
BindSuggestUsers(*gin.Context) (*web.SuggestUsersReq, mir.Error)
BindChangeAvatar(*gin.Context) (*web.ChangeAvatarReq, mir.Error)
BindChangeNickname(*gin.Context) (*web.ChangeNicknameReq, mir.Error)
BindChangePassword(*gin.Context) (*web.ChangePasswordReq, mir.Error)
BindUserPhoneBind(*gin.Context) (*web.UserPhoneBindReq, mir.Error)
BindGetStars(*gin.Context) (*web.GetStarsReq, mir.Error)
BindGetCollections(*gin.Context) (*web.GetCollectionsReq, mir.Error)
BindSendUserWhisper(*gin.Context) (*web.SendWhisperReq, mir.Error)
BindReadMessage(*gin.Context) (*web.ReadMessageReq, mir.Error)
BindGetMessages(*gin.Context) (*web.GetMessagesReq, mir.Error)
BindGetUnreadMsgCount(*gin.Context) (*web.GetUnreadMsgCountReq, mir.Error)
BindGetUserInfo(*gin.Context) (*web.UserInfoReq, mir.Error)
BindSyncSearchIndex(*gin.Context) (*web.SyncSearchIndexReq, mir.Error)
mustEmbedUnimplementedCoreBinding()
}
type CoreRender interface {
RenderTweetCollectionStatus(*gin.Context, *web.TweetCollectionStatusResp, mir.Error)
RenderTweetStarStatus(*gin.Context, *web.TweetStarStatusResp, mir.Error)
RenderSuggestTags(*gin.Context, *web.SuggestTagsResp, mir.Error)
RenderSuggestUsers(*gin.Context, *web.SuggestUsersResp, mir.Error)
RenderChangeAvatar(*gin.Context, mir.Error)
RenderChangeNickname(*gin.Context, mir.Error)
RenderChangePassword(*gin.Context, mir.Error)
RenderUserPhoneBind(*gin.Context, mir.Error)
RenderGetStars(*gin.Context, *web.GetStarsResp, mir.Error)
RenderGetCollections(*gin.Context, *web.GetCollectionsResp, mir.Error)
RenderSendUserWhisper(*gin.Context, mir.Error)
RenderReadMessage(*gin.Context, mir.Error)
RenderGetMessages(*gin.Context, *web.GetMessagesResp, mir.Error)
RenderGetUnreadMsgCount(*gin.Context, *web.GetUnreadMsgCountResp, mir.Error)
RenderGetUserInfo(*gin.Context, *web.UserInfoResp, mir.Error)
RenderSyncSearchIndex(*gin.Context, mir.Error)
mustEmbedUnimplementedCoreRender()
}
// RegisterCoreServant register Core servant to gin
func RegisterCoreServant(e *gin.Engine, s Core, b CoreBinding, r CoreRender) {
router := e.Group("v1")
// use chain for router
middlewares := s.Chain()
router.Use(middlewares...)
// register routes info to router
router.Handle("GET", "/post/collection", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindTweetCollectionStatus(c)
if err != nil {
r.RenderTweetCollectionStatus(c, nil, err)
return
}
resp, err := s.TweetCollectionStatus(req)
r.RenderTweetCollectionStatus(c, resp, err)
})
router.Handle("GET", "/post/star", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindTweetStarStatus(c)
if err != nil {
r.RenderTweetStarStatus(c, nil, err)
return
}
resp, err := s.TweetStarStatus(req)
r.RenderTweetStarStatus(c, resp, err)
})
router.Handle("GET", "/suggest/tags", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindSuggestTags(c)
if err != nil {
r.RenderSuggestTags(c, nil, err)
return
}
resp, err := s.SuggestTags(req)
r.RenderSuggestTags(c, resp, err)
})
router.Handle("GET", "/suggest/users", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindSuggestUsers(c)
if err != nil {
r.RenderSuggestUsers(c, nil, err)
return
}
resp, err := s.SuggestUsers(req)
r.RenderSuggestUsers(c, resp, err)
})
router.Handle("POST", "/user/avatar", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindChangeAvatar(c)
if err != nil {
r.RenderChangeAvatar(c, err)
return
}
r.RenderChangeAvatar(c, s.ChangeAvatar(req))
})
router.Handle("POST", "/user/nickname", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindChangeNickname(c)
if err != nil {
r.RenderChangeNickname(c, err)
return
}
r.RenderChangeNickname(c, s.ChangeNickname(req))
})
router.Handle("POST", "/user/password", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindChangePassword(c)
if err != nil {
r.RenderChangePassword(c, err)
return
}
r.RenderChangePassword(c, s.ChangePassword(req))
})
router.Handle("POST", "/user/phone", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindUserPhoneBind(c)
if err != nil {
r.RenderUserPhoneBind(c, err)
return
}
r.RenderUserPhoneBind(c, s.UserPhoneBind(req))
})
router.Handle("GET", "/user/stars", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindGetStars(c)
if err != nil {
r.RenderGetStars(c, nil, err)
return
}
resp, err := s.GetStars(req)
r.RenderGetStars(c, resp, err)
})
router.Handle("GET", "/user/collections", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindGetCollections(c)
if err != nil {
r.RenderGetCollections(c, nil, err)
return
}
resp, err := s.GetCollections(req)
r.RenderGetCollections(c, resp, err)
})
router.Handle("POST", "/user/whisper", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindSendUserWhisper(c)
if err != nil {
r.RenderSendUserWhisper(c, err)
return
}
r.RenderSendUserWhisper(c, s.SendUserWhisper(req))
})
router.Handle("POST", "/user/message/read", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindReadMessage(c)
if err != nil {
r.RenderReadMessage(c, err)
return
}
r.RenderReadMessage(c, s.ReadMessage(req))
})
router.Handle("GET", "/user/messages", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindGetMessages(c)
if err != nil {
r.RenderGetMessages(c, nil, err)
return
}
resp, err := s.GetMessages(req)
r.RenderGetMessages(c, resp, err)
})
router.Handle("GET", "/user/msgcount/unread", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindGetUnreadMsgCount(c)
if err != nil {
r.RenderGetUnreadMsgCount(c, nil, err)
return
}
resp, err := s.GetUnreadMsgCount(req)
r.RenderGetUnreadMsgCount(c, resp, err)
})
router.Handle("GET", "/user/info", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindGetUserInfo(c)
if err != nil {
r.RenderGetUserInfo(c, nil, err)
return
}
resp, err := s.GetUserInfo(req)
r.RenderGetUserInfo(c, resp, err)
})
router.Handle("GET", "/sync/index", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindSyncSearchIndex(c)
if err != nil {
r.RenderSyncSearchIndex(c, err)
return
}
r.RenderSyncSearchIndex(c, s.SyncSearchIndex(req))
})
}
// UnimplementedCoreServant can be embedded to have forward compatible implementations.
type UnimplementedCoreServant struct {
}
func (UnimplementedCoreServant) Chain() gin.HandlersChain {
return nil
}
func (UnimplementedCoreServant) TweetCollectionStatus(req *web.TweetCollectionStatusReq) (*web.TweetCollectionStatusResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedCoreServant) TweetStarStatus(req *web.TweetStarStatusReq) (*web.TweetStarStatusResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedCoreServant) SuggestTags(req *web.SuggestTagsReq) (*web.SuggestTagsResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedCoreServant) SuggestUsers(req *web.SuggestUsersReq) (*web.SuggestUsersResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedCoreServant) ChangeAvatar(req *web.ChangeAvatarReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedCoreServant) ChangeNickname(req *web.ChangeNicknameReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedCoreServant) ChangePassword(req *web.ChangePasswordReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedCoreServant) UserPhoneBind(req *web.UserPhoneBindReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedCoreServant) GetStars(req *web.GetStarsReq) (*web.GetStarsResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedCoreServant) GetCollections(req *web.GetCollectionsReq) (*web.GetCollectionsResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedCoreServant) SendUserWhisper(req *web.SendWhisperReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedCoreServant) ReadMessage(req *web.ReadMessageReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedCoreServant) GetMessages(req *web.GetMessagesReq) (*web.GetMessagesResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedCoreServant) GetUnreadMsgCount(req *web.GetUnreadMsgCountReq) (*web.GetUnreadMsgCountResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedCoreServant) GetUserInfo(req *web.UserInfoReq) (*web.UserInfoResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedCoreServant) SyncSearchIndex(req *web.SyncSearchIndexReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedCoreServant) mustEmbedUnimplementedCoreServant() {}
// UnimplementedCoreRender can be embedded to have forward compatible implementations.
type UnimplementedCoreRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedCoreRender) RenderTweetCollectionStatus(c *gin.Context, data *web.TweetCollectionStatusResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedCoreRender) RenderTweetStarStatus(c *gin.Context, data *web.TweetStarStatusResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedCoreRender) RenderSuggestTags(c *gin.Context, data *web.SuggestTagsResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedCoreRender) RenderSuggestUsers(c *gin.Context, data *web.SuggestUsersResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedCoreRender) RenderChangeAvatar(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedCoreRender) RenderChangeNickname(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedCoreRender) RenderChangePassword(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedCoreRender) RenderUserPhoneBind(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedCoreRender) RenderGetStars(c *gin.Context, data *web.GetStarsResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedCoreRender) RenderGetCollections(c *gin.Context, data *web.GetCollectionsResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedCoreRender) RenderSendUserWhisper(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedCoreRender) RenderReadMessage(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedCoreRender) RenderGetMessages(c *gin.Context, data *web.GetMessagesResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedCoreRender) RenderGetUnreadMsgCount(c *gin.Context, data *web.GetUnreadMsgCountResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedCoreRender) RenderGetUserInfo(c *gin.Context, data *web.UserInfoResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedCoreRender) RenderSyncSearchIndex(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedCoreRender) mustEmbedUnimplementedCoreRender() {}
// UnimplementedCoreBinding can be embedded to have forward compatible implementations.
type UnimplementedCoreBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedCoreBinding) BindTweetCollectionStatus(c *gin.Context) (*web.TweetCollectionStatusReq, mir.Error) {
obj := new(web.TweetCollectionStatusReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindTweetStarStatus(c *gin.Context) (*web.TweetStarStatusReq, mir.Error) {
obj := new(web.TweetStarStatusReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindSuggestTags(c *gin.Context) (*web.SuggestTagsReq, mir.Error) {
obj := new(web.SuggestTagsReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindSuggestUsers(c *gin.Context) (*web.SuggestUsersReq, mir.Error) {
obj := new(web.SuggestUsersReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindChangeAvatar(c *gin.Context) (*web.ChangeAvatarReq, mir.Error) {
obj := new(web.ChangeAvatarReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindChangeNickname(c *gin.Context) (*web.ChangeNicknameReq, mir.Error) {
obj := new(web.ChangeNicknameReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindChangePassword(c *gin.Context) (*web.ChangePasswordReq, mir.Error) {
obj := new(web.ChangePasswordReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindUserPhoneBind(c *gin.Context) (*web.UserPhoneBindReq, mir.Error) {
obj := new(web.UserPhoneBindReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindGetStars(c *gin.Context) (*web.GetStarsReq, mir.Error) {
obj := new(web.GetStarsReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindGetCollections(c *gin.Context) (*web.GetCollectionsReq, mir.Error) {
obj := new(web.GetCollectionsReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindSendUserWhisper(c *gin.Context) (*web.SendWhisperReq, mir.Error) {
obj := new(web.SendWhisperReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindReadMessage(c *gin.Context) (*web.ReadMessageReq, mir.Error) {
obj := new(web.ReadMessageReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindGetMessages(c *gin.Context) (*web.GetMessagesReq, mir.Error) {
obj := new(web.GetMessagesReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindGetUnreadMsgCount(c *gin.Context) (*web.GetUnreadMsgCountReq, mir.Error) {
obj := new(web.GetUnreadMsgCountReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindGetUserInfo(c *gin.Context) (*web.UserInfoReq, mir.Error) {
obj := new(web.UserInfoReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindSyncSearchIndex(c *gin.Context) (*web.SyncSearchIndexReq, mir.Error) {
obj := new(web.SyncSearchIndexReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) mustEmbedUnimplementedCoreBinding() {}

@ -0,0 +1,193 @@
// Code generated by go-mir. DO NOT EDIT.
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/model/web"
)
type Followship interface {
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
ListFollowers(*web.ListFollowersReq) (*web.ListFollowersResp, mir.Error)
ListFollowings(*web.ListFollowingsReq) (*web.ListFollowingsResp, mir.Error)
DeleteFollowing(*web.DeleteFollowingReq) mir.Error
AddFollowing(*web.AddFollowingReq) mir.Error
mustEmbedUnimplementedFollowshipServant()
}
type FollowshipBinding interface {
BindListFollowers(*gin.Context) (*web.ListFollowersReq, mir.Error)
BindListFollowings(*gin.Context) (*web.ListFollowingsReq, mir.Error)
BindDeleteFollowing(*gin.Context) (*web.DeleteFollowingReq, mir.Error)
BindAddFollowing(*gin.Context) (*web.AddFollowingReq, mir.Error)
mustEmbedUnimplementedFollowshipBinding()
}
type FollowshipRender interface {
RenderListFollowers(*gin.Context, *web.ListFollowersResp, mir.Error)
RenderListFollowings(*gin.Context, *web.ListFollowingsResp, mir.Error)
RenderDeleteFollowing(*gin.Context, mir.Error)
RenderAddFollowing(*gin.Context, mir.Error)
mustEmbedUnimplementedFollowshipRender()
}
// RegisterFollowshipServant register Followship servant to gin
func RegisterFollowshipServant(e *gin.Engine, s Followship, b FollowshipBinding, r FollowshipRender) {
router := e.Group("v1")
// use chain for router
middlewares := s.Chain()
router.Use(middlewares...)
// register routes info to router
router.Handle("GET", "/follower/list", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindListFollowers(c)
if err != nil {
r.RenderListFollowers(c, nil, err)
return
}
resp, err := s.ListFollowers(req)
r.RenderListFollowers(c, resp, err)
})
router.Handle("GET", "/following/list", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindListFollowings(c)
if err != nil {
r.RenderListFollowings(c, nil, err)
return
}
resp, err := s.ListFollowings(req)
r.RenderListFollowings(c, resp, err)
})
router.Handle("POST", "/following/delete", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindDeleteFollowing(c)
if err != nil {
r.RenderDeleteFollowing(c, err)
return
}
r.RenderDeleteFollowing(c, s.DeleteFollowing(req))
})
router.Handle("POST", "/following/add", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindAddFollowing(c)
if err != nil {
r.RenderAddFollowing(c, err)
return
}
r.RenderAddFollowing(c, s.AddFollowing(req))
})
}
// UnimplementedFollowshipServant can be embedded to have forward compatible implementations.
type UnimplementedFollowshipServant struct {
}
func (UnimplementedFollowshipServant) Chain() gin.HandlersChain {
return nil
}
func (UnimplementedFollowshipServant) ListFollowers(req *web.ListFollowersReq) (*web.ListFollowersResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedFollowshipServant) ListFollowings(req *web.ListFollowingsReq) (*web.ListFollowingsResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedFollowshipServant) DeleteFollowing(req *web.DeleteFollowingReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedFollowshipServant) AddFollowing(req *web.AddFollowingReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedFollowshipServant) mustEmbedUnimplementedFollowshipServant() {}
// UnimplementedFollowshipRender can be embedded to have forward compatible implementations.
type UnimplementedFollowshipRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedFollowshipRender) RenderListFollowers(c *gin.Context, data *web.ListFollowersResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedFollowshipRender) RenderListFollowings(c *gin.Context, data *web.ListFollowingsResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedFollowshipRender) RenderDeleteFollowing(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedFollowshipRender) RenderAddFollowing(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedFollowshipRender) mustEmbedUnimplementedFollowshipRender() {}
// UnimplementedFollowshipBinding can be embedded to have forward compatible implementations.
type UnimplementedFollowshipBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedFollowshipBinding) BindListFollowers(c *gin.Context) (*web.ListFollowersReq, mir.Error) {
obj := new(web.ListFollowersReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedFollowshipBinding) BindListFollowings(c *gin.Context) (*web.ListFollowingsReq, mir.Error) {
obj := new(web.ListFollowingsReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedFollowshipBinding) BindDeleteFollowing(c *gin.Context) (*web.DeleteFollowingReq, mir.Error) {
obj := new(web.DeleteFollowingReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedFollowshipBinding) BindAddFollowing(c *gin.Context) (*web.AddFollowingReq, mir.Error) {
obj := new(web.AddFollowingReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedFollowshipBinding) mustEmbedUnimplementedFollowshipBinding() {}

@ -0,0 +1,224 @@
// Code generated by go-mir. DO NOT EDIT.
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/model/web"
)
type Friendship interface {
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
GetContacts(*web.GetContactsReq) (*web.GetContactsResp, mir.Error)
DeleteFriend(*web.DeleteFriendReq) mir.Error
RejectFriend(*web.RejectFriendReq) mir.Error
AddFriend(*web.AddFriendReq) mir.Error
RequestingFriend(*web.RequestingFriendReq) mir.Error
mustEmbedUnimplementedFriendshipServant()
}
type FriendshipBinding interface {
BindGetContacts(*gin.Context) (*web.GetContactsReq, mir.Error)
BindDeleteFriend(*gin.Context) (*web.DeleteFriendReq, mir.Error)
BindRejectFriend(*gin.Context) (*web.RejectFriendReq, mir.Error)
BindAddFriend(*gin.Context) (*web.AddFriendReq, mir.Error)
BindRequestingFriend(*gin.Context) (*web.RequestingFriendReq, mir.Error)
mustEmbedUnimplementedFriendshipBinding()
}
type FriendshipRender interface {
RenderGetContacts(*gin.Context, *web.GetContactsResp, mir.Error)
RenderDeleteFriend(*gin.Context, mir.Error)
RenderRejectFriend(*gin.Context, mir.Error)
RenderAddFriend(*gin.Context, mir.Error)
RenderRequestingFriend(*gin.Context, mir.Error)
mustEmbedUnimplementedFriendshipRender()
}
// RegisterFriendshipServant register Friendship servant to gin
func RegisterFriendshipServant(e *gin.Engine, s Friendship, b FriendshipBinding, r FriendshipRender) {
router := e.Group("v1")
// use chain for router
middlewares := s.Chain()
router.Use(middlewares...)
// register routes info to router
router.Handle("GET", "/user/contacts", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindGetContacts(c)
if err != nil {
r.RenderGetContacts(c, nil, err)
return
}
resp, err := s.GetContacts(req)
r.RenderGetContacts(c, resp, err)
})
router.Handle("POST", "/friend/delete", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindDeleteFriend(c)
if err != nil {
r.RenderDeleteFriend(c, err)
return
}
r.RenderDeleteFriend(c, s.DeleteFriend(req))
})
router.Handle("POST", "/friend/reject", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindRejectFriend(c)
if err != nil {
r.RenderRejectFriend(c, err)
return
}
r.RenderRejectFriend(c, s.RejectFriend(req))
})
router.Handle("POST", "/friend/add", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindAddFriend(c)
if err != nil {
r.RenderAddFriend(c, err)
return
}
r.RenderAddFriend(c, s.AddFriend(req))
})
router.Handle("POST", "/friend/requesting", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindRequestingFriend(c)
if err != nil {
r.RenderRequestingFriend(c, err)
return
}
r.RenderRequestingFriend(c, s.RequestingFriend(req))
})
}
// UnimplementedFriendshipServant can be embedded to have forward compatible implementations.
type UnimplementedFriendshipServant struct {
}
func (UnimplementedFriendshipServant) Chain() gin.HandlersChain {
return nil
}
func (UnimplementedFriendshipServant) GetContacts(req *web.GetContactsReq) (*web.GetContactsResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedFriendshipServant) DeleteFriend(req *web.DeleteFriendReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedFriendshipServant) RejectFriend(req *web.RejectFriendReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedFriendshipServant) AddFriend(req *web.AddFriendReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedFriendshipServant) RequestingFriend(req *web.RequestingFriendReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedFriendshipServant) mustEmbedUnimplementedFriendshipServant() {}
// UnimplementedFriendshipRender can be embedded to have forward compatible implementations.
type UnimplementedFriendshipRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedFriendshipRender) RenderGetContacts(c *gin.Context, data *web.GetContactsResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedFriendshipRender) RenderDeleteFriend(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedFriendshipRender) RenderRejectFriend(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedFriendshipRender) RenderAddFriend(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedFriendshipRender) RenderRequestingFriend(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedFriendshipRender) mustEmbedUnimplementedFriendshipRender() {}
// UnimplementedFriendshipBinding can be embedded to have forward compatible implementations.
type UnimplementedFriendshipBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedFriendshipBinding) BindGetContacts(c *gin.Context) (*web.GetContactsReq, mir.Error) {
obj := new(web.GetContactsReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedFriendshipBinding) BindDeleteFriend(c *gin.Context) (*web.DeleteFriendReq, mir.Error) {
obj := new(web.DeleteFriendReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedFriendshipBinding) BindRejectFriend(c *gin.Context) (*web.RejectFriendReq, mir.Error) {
obj := new(web.RejectFriendReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedFriendshipBinding) BindAddFriend(c *gin.Context) (*web.AddFriendReq, mir.Error) {
obj := new(web.AddFriendReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedFriendshipBinding) BindRequestingFriend(c *gin.Context) (*web.RequestingFriendReq, mir.Error) {
obj := new(web.RequestingFriendReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedFriendshipBinding) mustEmbedUnimplementedFriendshipBinding() {}

@ -0,0 +1,162 @@
// Code generated by go-mir. DO NOT EDIT.
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/model/web"
)
type Loose interface {
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
GetUserProfile(*web.GetUserProfileReq) (*web.GetUserProfileResp, mir.Error)
GetUserTweets(*web.GetUserTweetsReq) (*web.GetUserTweetsResp, mir.Error)
Timeline(*web.TimelineReq) (*web.TimelineResp, mir.Error)
mustEmbedUnimplementedLooseServant()
}
type LooseBinding interface {
BindGetUserProfile(*gin.Context) (*web.GetUserProfileReq, mir.Error)
BindGetUserTweets(*gin.Context) (*web.GetUserTweetsReq, mir.Error)
BindTimeline(*gin.Context) (*web.TimelineReq, mir.Error)
mustEmbedUnimplementedLooseBinding()
}
type LooseRender interface {
RenderGetUserProfile(*gin.Context, *web.GetUserProfileResp, mir.Error)
RenderGetUserTweets(*gin.Context, *web.GetUserTweetsResp, mir.Error)
RenderTimeline(*gin.Context, *web.TimelineResp, mir.Error)
mustEmbedUnimplementedLooseRender()
}
// RegisterLooseServant register Loose servant to gin
func RegisterLooseServant(e *gin.Engine, s Loose, b LooseBinding, r LooseRender) {
router := e.Group("v1")
// use chain for router
middlewares := s.Chain()
router.Use(middlewares...)
// register routes info to router
router.Handle("GET", "/user/profile", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindGetUserProfile(c)
if err != nil {
r.RenderGetUserProfile(c, nil, err)
return
}
resp, err := s.GetUserProfile(req)
r.RenderGetUserProfile(c, resp, err)
})
router.Handle("GET", "/user/posts", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindGetUserTweets(c)
if err != nil {
r.RenderGetUserTweets(c, nil, err)
return
}
resp, err := s.GetUserTweets(req)
r.RenderGetUserTweets(c, resp, err)
})
router.Handle("GET", "/posts", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindTimeline(c)
if err != nil {
r.RenderTimeline(c, nil, err)
return
}
resp, err := s.Timeline(req)
r.RenderTimeline(c, resp, err)
})
}
// UnimplementedLooseServant can be embedded to have forward compatible implementations.
type UnimplementedLooseServant struct {
}
func (UnimplementedLooseServant) Chain() gin.HandlersChain {
return nil
}
func (UnimplementedLooseServant) GetUserProfile(req *web.GetUserProfileReq) (*web.GetUserProfileResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedLooseServant) GetUserTweets(req *web.GetUserTweetsReq) (*web.GetUserTweetsResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedLooseServant) Timeline(req *web.TimelineReq) (*web.TimelineResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedLooseServant) mustEmbedUnimplementedLooseServant() {}
// UnimplementedLooseRender can be embedded to have forward compatible implementations.
type UnimplementedLooseRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedLooseRender) RenderGetUserProfile(c *gin.Context, data *web.GetUserProfileResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedLooseRender) RenderGetUserTweets(c *gin.Context, data *web.GetUserTweetsResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedLooseRender) RenderTimeline(c *gin.Context, data *web.TimelineResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedLooseRender) mustEmbedUnimplementedLooseRender() {}
// UnimplementedLooseBinding can be embedded to have forward compatible implementations.
type UnimplementedLooseBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedLooseBinding) BindGetUserProfile(c *gin.Context) (*web.GetUserProfileReq, mir.Error) {
obj := new(web.GetUserProfileReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedLooseBinding) BindGetUserTweets(c *gin.Context) (*web.GetUserTweetsReq, mir.Error) {
obj := new(web.GetUserTweetsReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedLooseBinding) BindTimeline(c *gin.Context) (*web.TimelineReq, mir.Error) {
obj := new(web.TimelineReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedLooseBinding) mustEmbedUnimplementedLooseBinding() {}

@ -0,0 +1,522 @@
// Code generated by go-mir. DO NOT EDIT.
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/model/web"
)
type Priv interface {
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
DeleteCommentReply(*web.DeleteCommentReplyReq) mir.Error
CreateCommentReply(*web.CreateCommentReplyReq) (*web.CreateCommentReplyResp, mir.Error)
DeleteComment(*web.DeleteCommentReq) mir.Error
CreateComment(*web.CreateCommentReq) (*web.CreateCommentResp, mir.Error)
VisiblePost(*web.VisiblePostReq) (*web.VisiblePostResp, mir.Error)
StickTweet(*web.StickTweetReq) (*web.StickTweetResp, mir.Error)
LockTweet(*web.LockTweetReq) (*web.LockTweetResp, mir.Error)
CollectionTweet(*web.CollectionTweetReq) (*web.CollectionTweetResp, mir.Error)
StarTweet(*web.StarTweetReq) (*web.StarTweetResp, mir.Error)
DeleteTweet(*web.DeleteTweetReq) mir.Error
CreateTweet(*web.CreateTweetReq) (*web.CreateTweetResp, mir.Error)
DownloadAttachment(*web.DownloadAttachmentReq) (*web.DownloadAttachmentResp, mir.Error)
DownloadAttachmentPrecheck(*web.DownloadAttachmentPrecheckReq) (*web.DownloadAttachmentPrecheckResp, mir.Error)
UploadAttachment(*web.UploadAttachmentReq) (*web.UploadAttachmentResp, mir.Error)
mustEmbedUnimplementedPrivServant()
}
type PrivBinding interface {
BindDeleteCommentReply(*gin.Context) (*web.DeleteCommentReplyReq, mir.Error)
BindCreateCommentReply(*gin.Context) (*web.CreateCommentReplyReq, mir.Error)
BindDeleteComment(*gin.Context) (*web.DeleteCommentReq, mir.Error)
BindCreateComment(*gin.Context) (*web.CreateCommentReq, mir.Error)
BindVisiblePost(*gin.Context) (*web.VisiblePostReq, mir.Error)
BindStickTweet(*gin.Context) (*web.StickTweetReq, mir.Error)
BindLockTweet(*gin.Context) (*web.LockTweetReq, mir.Error)
BindCollectionTweet(*gin.Context) (*web.CollectionTweetReq, mir.Error)
BindStarTweet(*gin.Context) (*web.StarTweetReq, mir.Error)
BindDeleteTweet(*gin.Context) (*web.DeleteTweetReq, mir.Error)
BindCreateTweet(*gin.Context) (*web.CreateTweetReq, mir.Error)
BindDownloadAttachment(*gin.Context) (*web.DownloadAttachmentReq, mir.Error)
BindDownloadAttachmentPrecheck(*gin.Context) (*web.DownloadAttachmentPrecheckReq, mir.Error)
BindUploadAttachment(*gin.Context) (*web.UploadAttachmentReq, mir.Error)
mustEmbedUnimplementedPrivBinding()
}
type PrivRender interface {
RenderDeleteCommentReply(*gin.Context, mir.Error)
RenderCreateCommentReply(*gin.Context, *web.CreateCommentReplyResp, mir.Error)
RenderDeleteComment(*gin.Context, mir.Error)
RenderCreateComment(*gin.Context, *web.CreateCommentResp, mir.Error)
RenderVisiblePost(*gin.Context, *web.VisiblePostResp, mir.Error)
RenderStickTweet(*gin.Context, *web.StickTweetResp, mir.Error)
RenderLockTweet(*gin.Context, *web.LockTweetResp, mir.Error)
RenderCollectionTweet(*gin.Context, *web.CollectionTweetResp, mir.Error)
RenderStarTweet(*gin.Context, *web.StarTweetResp, mir.Error)
RenderDeleteTweet(*gin.Context, mir.Error)
RenderCreateTweet(*gin.Context, *web.CreateTweetResp, mir.Error)
RenderDownloadAttachment(*gin.Context, *web.DownloadAttachmentResp, mir.Error)
RenderDownloadAttachmentPrecheck(*gin.Context, *web.DownloadAttachmentPrecheckResp, mir.Error)
RenderUploadAttachment(*gin.Context, *web.UploadAttachmentResp, mir.Error)
mustEmbedUnimplementedPrivRender()
}
// RegisterPrivServant register Priv servant to gin
func RegisterPrivServant(e *gin.Engine, s Priv, b PrivBinding, r PrivRender) {
router := e.Group("v1")
// use chain for router
middlewares := s.Chain()
router.Use(middlewares...)
// register routes info to router
router.Handle("DELETE", "/post/comment/reply", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindDeleteCommentReply(c)
if err != nil {
r.RenderDeleteCommentReply(c, err)
return
}
r.RenderDeleteCommentReply(c, s.DeleteCommentReply(req))
})
router.Handle("POST", "/post/comment/reply", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindCreateCommentReply(c)
if err != nil {
r.RenderCreateCommentReply(c, nil, err)
return
}
resp, err := s.CreateCommentReply(req)
r.RenderCreateCommentReply(c, resp, err)
})
router.Handle("DELETE", "/post/comment", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindDeleteComment(c)
if err != nil {
r.RenderDeleteComment(c, err)
return
}
r.RenderDeleteComment(c, s.DeleteComment(req))
})
router.Handle("POST", "/post/comment", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindCreateComment(c)
if err != nil {
r.RenderCreateComment(c, nil, err)
return
}
resp, err := s.CreateComment(req)
r.RenderCreateComment(c, resp, err)
})
router.Handle("POST", "/post/visibility", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindVisiblePost(c)
if err != nil {
r.RenderVisiblePost(c, nil, err)
return
}
resp, err := s.VisiblePost(req)
r.RenderVisiblePost(c, resp, err)
})
router.Handle("POST", "/post/stick", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindStickTweet(c)
if err != nil {
r.RenderStickTweet(c, nil, err)
return
}
resp, err := s.StickTweet(req)
r.RenderStickTweet(c, resp, err)
})
router.Handle("POST", "/post/lock", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindLockTweet(c)
if err != nil {
r.RenderLockTweet(c, nil, err)
return
}
resp, err := s.LockTweet(req)
r.RenderLockTweet(c, resp, err)
})
router.Handle("POST", "/post/collection", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindCollectionTweet(c)
if err != nil {
r.RenderCollectionTweet(c, nil, err)
return
}
resp, err := s.CollectionTweet(req)
r.RenderCollectionTweet(c, resp, err)
})
router.Handle("POST", "/post/start", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindStarTweet(c)
if err != nil {
r.RenderStarTweet(c, nil, err)
return
}
resp, err := s.StarTweet(req)
r.RenderStarTweet(c, resp, err)
})
router.Handle("DELETE", "/post", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindDeleteTweet(c)
if err != nil {
r.RenderDeleteTweet(c, err)
return
}
r.RenderDeleteTweet(c, s.DeleteTweet(req))
})
router.Handle("POST", "/post", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindCreateTweet(c)
if err != nil {
r.RenderCreateTweet(c, nil, err)
return
}
resp, err := s.CreateTweet(req)
r.RenderCreateTweet(c, resp, err)
})
router.Handle("GET", "/attachment", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindDownloadAttachment(c)
if err != nil {
r.RenderDownloadAttachment(c, nil, err)
return
}
resp, err := s.DownloadAttachment(req)
r.RenderDownloadAttachment(c, resp, err)
})
router.Handle("GET", "/attachment/precheck", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindDownloadAttachmentPrecheck(c)
if err != nil {
r.RenderDownloadAttachmentPrecheck(c, nil, err)
return
}
resp, err := s.DownloadAttachmentPrecheck(req)
r.RenderDownloadAttachmentPrecheck(c, resp, err)
})
router.Handle("POST", "/attachment", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindUploadAttachment(c)
if err != nil {
r.RenderUploadAttachment(c, nil, err)
return
}
resp, err := s.UploadAttachment(req)
r.RenderUploadAttachment(c, resp, err)
})
}
// UnimplementedPrivServant can be embedded to have forward compatible implementations.
type UnimplementedPrivServant struct {
}
func (UnimplementedPrivServant) Chain() gin.HandlersChain {
return nil
}
func (UnimplementedPrivServant) DeleteCommentReply(req *web.DeleteCommentReplyReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) CreateCommentReply(req *web.CreateCommentReplyReq) (*web.CreateCommentReplyResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) DeleteComment(req *web.DeleteCommentReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) CreateComment(req *web.CreateCommentReq) (*web.CreateCommentResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) VisiblePost(req *web.VisiblePostReq) (*web.VisiblePostResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) StickTweet(req *web.StickTweetReq) (*web.StickTweetResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) LockTweet(req *web.LockTweetReq) (*web.LockTweetResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) CollectionTweet(req *web.CollectionTweetReq) (*web.CollectionTweetResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) StarTweet(req *web.StarTweetReq) (*web.StarTweetResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) DeleteTweet(req *web.DeleteTweetReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) CreateTweet(req *web.CreateTweetReq) (*web.CreateTweetResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) DownloadAttachment(req *web.DownloadAttachmentReq) (*web.DownloadAttachmentResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) DownloadAttachmentPrecheck(req *web.DownloadAttachmentPrecheckReq) (*web.DownloadAttachmentPrecheckResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) UploadAttachment(req *web.UploadAttachmentReq) (*web.UploadAttachmentResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) mustEmbedUnimplementedPrivServant() {}
// UnimplementedPrivRender can be embedded to have forward compatible implementations.
type UnimplementedPrivRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedPrivRender) RenderDeleteCommentReply(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedPrivRender) RenderCreateCommentReply(c *gin.Context, data *web.CreateCommentReplyResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPrivRender) RenderDeleteComment(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedPrivRender) RenderCreateComment(c *gin.Context, data *web.CreateCommentResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPrivRender) RenderVisiblePost(c *gin.Context, data *web.VisiblePostResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPrivRender) RenderStickTweet(c *gin.Context, data *web.StickTweetResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPrivRender) RenderLockTweet(c *gin.Context, data *web.LockTweetResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPrivRender) RenderCollectionTweet(c *gin.Context, data *web.CollectionTweetResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPrivRender) RenderStarTweet(c *gin.Context, data *web.StarTweetResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPrivRender) RenderDeleteTweet(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedPrivRender) RenderCreateTweet(c *gin.Context, data *web.CreateTweetResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPrivRender) RenderDownloadAttachment(c *gin.Context, data *web.DownloadAttachmentResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPrivRender) RenderDownloadAttachmentPrecheck(c *gin.Context, data *web.DownloadAttachmentPrecheckResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPrivRender) RenderUploadAttachment(c *gin.Context, data *web.UploadAttachmentResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPrivRender) mustEmbedUnimplementedPrivRender() {}
// UnimplementedPrivBinding can be embedded to have forward compatible implementations.
type UnimplementedPrivBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedPrivBinding) BindDeleteCommentReply(c *gin.Context) (*web.DeleteCommentReplyReq, mir.Error) {
obj := new(web.DeleteCommentReplyReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindCreateCommentReply(c *gin.Context) (*web.CreateCommentReplyReq, mir.Error) {
obj := new(web.CreateCommentReplyReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindDeleteComment(c *gin.Context) (*web.DeleteCommentReq, mir.Error) {
obj := new(web.DeleteCommentReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindCreateComment(c *gin.Context) (*web.CreateCommentReq, mir.Error) {
obj := new(web.CreateCommentReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindVisiblePost(c *gin.Context) (*web.VisiblePostReq, mir.Error) {
obj := new(web.VisiblePostReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindStickTweet(c *gin.Context) (*web.StickTweetReq, mir.Error) {
obj := new(web.StickTweetReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindLockTweet(c *gin.Context) (*web.LockTweetReq, mir.Error) {
obj := new(web.LockTweetReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindCollectionTweet(c *gin.Context) (*web.CollectionTweetReq, mir.Error) {
obj := new(web.CollectionTweetReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindStarTweet(c *gin.Context) (*web.StarTweetReq, mir.Error) {
obj := new(web.StarTweetReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindDeleteTweet(c *gin.Context) (*web.DeleteTweetReq, mir.Error) {
obj := new(web.DeleteTweetReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindCreateTweet(c *gin.Context) (*web.CreateTweetReq, mir.Error) {
obj := new(web.CreateTweetReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindDownloadAttachment(c *gin.Context) (*web.DownloadAttachmentReq, mir.Error) {
obj := new(web.DownloadAttachmentReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindDownloadAttachmentPrecheck(c *gin.Context) (*web.DownloadAttachmentPrecheckReq, mir.Error) {
obj := new(web.DownloadAttachmentPrecheckReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindUploadAttachment(c *gin.Context) (*web.UploadAttachmentReq, mir.Error) {
obj := new(web.UploadAttachmentReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) mustEmbedUnimplementedPrivBinding() {}

@ -0,0 +1,292 @@
// Code generated by go-mir. DO NOT EDIT.
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/model/web"
)
type Pub interface {
TopicList(*web.TopicListReq) (*web.TopicListResp, mir.Error)
TweetComments(*web.TweetCommentsReq) (*web.TweetCommentsResp, mir.Error)
TweetDetail(*web.TweetDetailReq) (*web.TweetDetailResp, mir.Error)
SendCaptcha(*web.SendCaptchaReq) mir.Error
GetCaptcha() (*web.GetCaptchaResp, mir.Error)
Register(*web.RegisterReq) (*web.RegisterResp, mir.Error)
Login(*web.LoginReq) (*web.LoginResp, mir.Error)
Version() (*web.VersionResp, mir.Error)
mustEmbedUnimplementedPubServant()
}
type PubBinding interface {
BindTopicList(*gin.Context) (*web.TopicListReq, mir.Error)
BindTweetComments(*gin.Context) (*web.TweetCommentsReq, mir.Error)
BindTweetDetail(*gin.Context) (*web.TweetDetailReq, mir.Error)
BindSendCaptcha(*gin.Context) (*web.SendCaptchaReq, mir.Error)
BindRegister(*gin.Context) (*web.RegisterReq, mir.Error)
BindLogin(*gin.Context) (*web.LoginReq, mir.Error)
mustEmbedUnimplementedPubBinding()
}
type PubRender interface {
RenderTopicList(*gin.Context, *web.TopicListResp, mir.Error)
RenderTweetComments(*gin.Context, *web.TweetCommentsResp, mir.Error)
RenderTweetDetail(*gin.Context, *web.TweetDetailResp, mir.Error)
RenderSendCaptcha(*gin.Context, mir.Error)
RenderGetCaptcha(*gin.Context, *web.GetCaptchaResp, mir.Error)
RenderRegister(*gin.Context, *web.RegisterResp, mir.Error)
RenderLogin(*gin.Context, *web.LoginResp, mir.Error)
RenderVersion(*gin.Context, *web.VersionResp, mir.Error)
mustEmbedUnimplementedPubRender()
}
// RegisterPubServant register Pub servant to gin
func RegisterPubServant(e *gin.Engine, s Pub, b PubBinding, r PubRender) {
router := e.Group("v1")
// register routes info to router
router.Handle("GET", "/tags", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindTopicList(c)
if err != nil {
r.RenderTopicList(c, nil, err)
return
}
resp, err := s.TopicList(req)
r.RenderTopicList(c, resp, err)
})
router.Handle("GET", "/post/comments", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindTweetComments(c)
if err != nil {
r.RenderTweetComments(c, nil, err)
return
}
resp, err := s.TweetComments(req)
r.RenderTweetComments(c, resp, err)
})
router.Handle("GET", "/post", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindTweetDetail(c)
if err != nil {
r.RenderTweetDetail(c, nil, err)
return
}
resp, err := s.TweetDetail(req)
r.RenderTweetDetail(c, resp, err)
})
router.Handle("POST", "/captcha", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindSendCaptcha(c)
if err != nil {
r.RenderSendCaptcha(c, err)
return
}
r.RenderSendCaptcha(c, s.SendCaptcha(req))
})
router.Handle("GET", "/captcha", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
resp, err := s.GetCaptcha()
r.RenderGetCaptcha(c, resp, err)
})
router.Handle("POST", "/auth/register", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindRegister(c)
if err != nil {
r.RenderRegister(c, nil, err)
return
}
resp, err := s.Register(req)
r.RenderRegister(c, resp, err)
})
router.Handle("POST", "/auth/login", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindLogin(c)
if err != nil {
r.RenderLogin(c, nil, err)
return
}
resp, err := s.Login(req)
r.RenderLogin(c, resp, err)
})
router.Handle("GET", "/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
resp, err := s.Version()
r.RenderVersion(c, resp, err)
})
}
// UnimplementedPubServant can be embedded to have forward compatible implementations.
type UnimplementedPubServant struct {
}
func (UnimplementedPubServant) TopicList(req *web.TopicListReq) (*web.TopicListResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPubServant) TweetComments(req *web.TweetCommentsReq) (*web.TweetCommentsResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPubServant) TweetDetail(req *web.TweetDetailReq) (*web.TweetDetailResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPubServant) SendCaptcha(req *web.SendCaptchaReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPubServant) GetCaptcha() (*web.GetCaptchaResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPubServant) Register(req *web.RegisterReq) (*web.RegisterResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPubServant) Login(req *web.LoginReq) (*web.LoginResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPubServant) Version() (*web.VersionResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPubServant) mustEmbedUnimplementedPubServant() {}
// UnimplementedPubRender can be embedded to have forward compatible implementations.
type UnimplementedPubRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedPubRender) RenderTopicList(c *gin.Context, data *web.TopicListResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPubRender) RenderTweetComments(c *gin.Context, data *web.TweetCommentsResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPubRender) RenderTweetDetail(c *gin.Context, data *web.TweetDetailResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPubRender) RenderSendCaptcha(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedPubRender) RenderGetCaptcha(c *gin.Context, data *web.GetCaptchaResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPubRender) RenderRegister(c *gin.Context, data *web.RegisterResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPubRender) RenderLogin(c *gin.Context, data *web.LoginResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPubRender) RenderVersion(c *gin.Context, data *web.VersionResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPubRender) mustEmbedUnimplementedPubRender() {}
// UnimplementedPubBinding can be embedded to have forward compatible implementations.
type UnimplementedPubBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedPubBinding) BindTopicList(c *gin.Context) (*web.TopicListReq, mir.Error) {
obj := new(web.TopicListReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPubBinding) BindTweetComments(c *gin.Context) (*web.TweetCommentsReq, mir.Error) {
obj := new(web.TweetCommentsReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPubBinding) BindTweetDetail(c *gin.Context) (*web.TweetDetailReq, mir.Error) {
obj := new(web.TweetDetailReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPubBinding) BindSendCaptcha(c *gin.Context) (*web.SendCaptchaReq, mir.Error) {
obj := new(web.SendCaptchaReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPubBinding) BindRegister(c *gin.Context) (*web.RegisterReq, mir.Error) {
obj := new(web.RegisterReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPubBinding) BindLogin(c *gin.Context) (*web.LoginReq, mir.Error) {
obj := new(web.LoginReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPubBinding) mustEmbedUnimplementedPubBinding() {}

@ -0,0 +1,140 @@
// Code generated by go-mir. DO NOT EDIT.
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin"
)
type LoginReq struct {
AgentInfo AgentInfo `json:"agent_info"`
Name string `json:"name"`
Passwd string `json:"passwd"`
}
type AgentInfo struct {
Platform string `json:"platform"`
UserAgent string `json:"user_agent"`
}
type LoginResp struct {
UserInfo
ServerInfo ServerInfo `json:"server_info"`
JwtToken string `json:"jwt_token"`
}
type ServerInfo struct {
ApiVer string `json:"api_ver"`
}
type UserInfo struct {
Name string `json:"name"`
}
type User interface {
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
Logout() mir.Error
Login(*LoginReq) (*LoginResp, mir.Error)
mustEmbedUnimplementedUserServant()
}
type UserBinding interface {
BindLogin(*gin.Context) (*LoginReq, mir.Error)
mustEmbedUnimplementedUserBinding()
}
type UserRender interface {
RenderLogout(*gin.Context, mir.Error)
RenderLogin(*gin.Context, *LoginResp, mir.Error)
mustEmbedUnimplementedUserRender()
}
// RegisterUserServant register User servant to gin
func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) {
router := e.Group("x/v1")
// use chain for router
middlewares := s.Chain()
router.Use(middlewares...)
// register routes info to router
router.Handle("POST", "/user/logout/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
r.RenderLogout(c, s.Logout())
})
router.Handle("POST", "/user/login/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindLogin(c)
if err != nil {
r.RenderLogin(c, nil, err)
return
}
resp, err := s.Login(req)
r.RenderLogin(c, resp, err)
})
}
// UnimplementedUserServant can be embedded to have forward compatible implementations.
type UnimplementedUserServant struct {
}
func (UnimplementedUserServant) Chain() gin.HandlersChain {
return nil
}
func (UnimplementedUserServant) Logout() mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedUserServant) Login(req *LoginReq) (*LoginResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedUserServant) mustEmbedUnimplementedUserServant() {}
// UnimplementedUserRender can be embedded to have forward compatible implementations.
type UnimplementedUserRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedUserRender) RenderLogout(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedUserRender) RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedUserRender) mustEmbedUnimplementedUserRender() {}
// UnimplementedUserBinding can be embedded to have forward compatible implementations.
type UnimplementedUserBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedUserBinding) BindLogin(c *gin.Context) (*LoginReq, mir.Error) {
obj := new(LoginReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedUserBinding) mustEmbedUnimplementedUserBinding() {}

@ -0,0 +1,371 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.1
// protoc (unknown)
// source: v1/auth.proto
package v1
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type User struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
PhoneNum string `protobuf:"bytes,1,opt,name=phoneNum,proto3" json:"phoneNum,omitempty"`
}
func (x *User) Reset() {
*x = User{}
if protoimpl.UnsafeEnabled {
mi := &file_v1_auth_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *User) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*User) ProtoMessage() {}
func (x *User) ProtoReflect() protoreflect.Message {
mi := &file_v1_auth_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use User.ProtoReflect.Descriptor instead.
func (*User) Descriptor() ([]byte, []int) {
return file_v1_auth_proto_rawDescGZIP(), []int{0}
}
func (x *User) GetPhoneNum() string {
if x != nil {
return x.PhoneNum
}
return ""
}
type UserVerify struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
PhoneNum string `protobuf:"bytes,1,opt,name=phoneNum,proto3" json:"phoneNum,omitempty"`
VerificationCode string `protobuf:"bytes,2,opt,name=VerificationCode,proto3" json:"VerificationCode,omitempty"`
}
func (x *UserVerify) Reset() {
*x = UserVerify{}
if protoimpl.UnsafeEnabled {
mi := &file_v1_auth_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *UserVerify) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UserVerify) ProtoMessage() {}
func (x *UserVerify) ProtoReflect() protoreflect.Message {
mi := &file_v1_auth_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UserVerify.ProtoReflect.Descriptor instead.
func (*UserVerify) Descriptor() ([]byte, []int) {
return file_v1_auth_proto_rawDescGZIP(), []int{1}
}
func (x *UserVerify) GetPhoneNum() string {
if x != nil {
return x.PhoneNum
}
return ""
}
func (x *UserVerify) GetVerificationCode() string {
if x != nil {
return x.VerificationCode
}
return ""
}
type LoginReply struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
StatuCode int32 `protobuf:"varint,1,opt,name=statuCode,proto3" json:"statuCode,omitempty"`
Token string `protobuf:"bytes,2,opt,name=token,proto3" json:"token,omitempty"`
}
func (x *LoginReply) Reset() {
*x = LoginReply{}
if protoimpl.UnsafeEnabled {
mi := &file_v1_auth_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *LoginReply) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*LoginReply) ProtoMessage() {}
func (x *LoginReply) ProtoReflect() protoreflect.Message {
mi := &file_v1_auth_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use LoginReply.ProtoReflect.Descriptor instead.
func (*LoginReply) Descriptor() ([]byte, []int) {
return file_v1_auth_proto_rawDescGZIP(), []int{2}
}
func (x *LoginReply) GetStatuCode() int32 {
if x != nil {
return x.StatuCode
}
return 0
}
func (x *LoginReply) GetToken() string {
if x != nil {
return x.Token
}
return ""
}
type ActionReply struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
StatusCode int32 `protobuf:"varint,1,opt,name=statusCode,proto3" json:"statusCode,omitempty"`
}
func (x *ActionReply) Reset() {
*x = ActionReply{}
if protoimpl.UnsafeEnabled {
mi := &file_v1_auth_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ActionReply) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ActionReply) ProtoMessage() {}
func (x *ActionReply) ProtoReflect() protoreflect.Message {
mi := &file_v1_auth_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ActionReply.ProtoReflect.Descriptor instead.
func (*ActionReply) Descriptor() ([]byte, []int) {
return file_v1_auth_proto_rawDescGZIP(), []int{3}
}
func (x *ActionReply) GetStatusCode() int32 {
if x != nil {
return x.StatusCode
}
return 0
}
var File_v1_auth_proto protoreflect.FileDescriptor
var file_v1_auth_proto_rawDesc = []byte{
0x0a, 0x0d, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x04, 0x61, 0x75, 0x74, 0x68, 0x22, 0x22, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1a, 0x0a,
0x08, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x08, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x22, 0x54, 0x0a, 0x0a, 0x55, 0x73, 0x65,
0x72, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x68, 0x6f, 0x6e, 0x65,
0x4e, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x68, 0x6f, 0x6e, 0x65,
0x4e, 0x75, 0x6d, 0x12, 0x2a, 0x0a, 0x10, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x56,
0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x22,
0x40, 0x0a, 0x0a, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x1c, 0x0a,
0x09, 0x73, 0x74, 0x61, 0x74, 0x75, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x75, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74,
0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65,
0x6e, 0x22, 0x2d, 0x0a, 0x0b, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79,
0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65,
0x32, 0x89, 0x01, 0x0a, 0x0c, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74,
0x65, 0x12, 0x29, 0x0a, 0x08, 0x70, 0x72, 0x65, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x0a, 0x2e,
0x61, 0x75, 0x74, 0x68, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x1a, 0x11, 0x2e, 0x61, 0x75, 0x74, 0x68,
0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x25, 0x0a, 0x05,
0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x0a, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x55, 0x73, 0x65,
0x72, 0x1a, 0x10, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65,
0x70, 0x6c, 0x79, 0x12, 0x27, 0x0a, 0x06, 0x6c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x12, 0x0a, 0x2e,
0x61, 0x75, 0x74, 0x68, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x1a, 0x11, 0x2e, 0x61, 0x75, 0x74, 0x68,
0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x42, 0x6f, 0x0a, 0x08,
0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x42, 0x09, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72,
0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
0x6d, 0x2f, 0x72, 0x6f, 0x63, 0x62, 0x6f, 0x73, 0x73, 0x2f, 0x70, 0x61, 0x6f, 0x70, 0x61, 0x6f,
0x2d, 0x63, 0x65, 0x2f, 0x61, 0x75, 0x74, 0x6f, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x76, 0x31, 0xa2,
0x02, 0x03, 0x41, 0x58, 0x58, 0xaa, 0x02, 0x04, 0x41, 0x75, 0x74, 0x68, 0xca, 0x02, 0x04, 0x41,
0x75, 0x74, 0x68, 0xe2, 0x02, 0x10, 0x41, 0x75, 0x74, 0x68, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65,
0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x04, 0x41, 0x75, 0x74, 0x68, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_v1_auth_proto_rawDescOnce sync.Once
file_v1_auth_proto_rawDescData = file_v1_auth_proto_rawDesc
)
func file_v1_auth_proto_rawDescGZIP() []byte {
file_v1_auth_proto_rawDescOnce.Do(func() {
file_v1_auth_proto_rawDescData = protoimpl.X.CompressGZIP(file_v1_auth_proto_rawDescData)
})
return file_v1_auth_proto_rawDescData
}
var file_v1_auth_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_v1_auth_proto_goTypes = []interface{}{
(*User)(nil), // 0: auth.User
(*UserVerify)(nil), // 1: auth.UserVerify
(*LoginReply)(nil), // 2: auth.LoginReply
(*ActionReply)(nil), // 3: auth.ActionReply
}
var file_v1_auth_proto_depIdxs = []int32{
0, // 0: auth.Authenticate.preLogin:input_type -> auth.User
0, // 1: auth.Authenticate.login:input_type -> auth.User
0, // 2: auth.Authenticate.logout:input_type -> auth.User
3, // 3: auth.Authenticate.preLogin:output_type -> auth.ActionReply
2, // 4: auth.Authenticate.login:output_type -> auth.LoginReply
3, // 5: auth.Authenticate.logout:output_type -> auth.ActionReply
3, // [3:6] is the sub-list for method output_type
0, // [0:3] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_v1_auth_proto_init() }
func file_v1_auth_proto_init() {
if File_v1_auth_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_v1_auth_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*User); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_v1_auth_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UserVerify); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_v1_auth_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*LoginReply); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_v1_auth_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ActionReply); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_v1_auth_proto_rawDesc,
NumEnums: 0,
NumMessages: 4,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_v1_auth_proto_goTypes,
DependencyIndexes: file_v1_auth_proto_depIdxs,
MessageInfos: file_v1_auth_proto_msgTypes,
}.Build()
File_v1_auth_proto = out.File
file_v1_auth_proto_rawDesc = nil
file_v1_auth_proto_goTypes = nil
file_v1_auth_proto_depIdxs = nil
}

@ -0,0 +1,177 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.2.0
// - protoc (unknown)
// source: v1/auth.proto
package v1
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// AuthenticateClient is the client API for Authenticate service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type AuthenticateClient interface {
PreLogin(ctx context.Context, in *User, opts ...grpc.CallOption) (*ActionReply, error)
Login(ctx context.Context, in *User, opts ...grpc.CallOption) (*LoginReply, error)
Logout(ctx context.Context, in *User, opts ...grpc.CallOption) (*ActionReply, error)
}
type authenticateClient struct {
cc grpc.ClientConnInterface
}
func NewAuthenticateClient(cc grpc.ClientConnInterface) AuthenticateClient {
return &authenticateClient{cc}
}
func (c *authenticateClient) PreLogin(ctx context.Context, in *User, opts ...grpc.CallOption) (*ActionReply, error) {
out := new(ActionReply)
err := c.cc.Invoke(ctx, "/auth.Authenticate/preLogin", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *authenticateClient) Login(ctx context.Context, in *User, opts ...grpc.CallOption) (*LoginReply, error) {
out := new(LoginReply)
err := c.cc.Invoke(ctx, "/auth.Authenticate/login", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *authenticateClient) Logout(ctx context.Context, in *User, opts ...grpc.CallOption) (*ActionReply, error) {
out := new(ActionReply)
err := c.cc.Invoke(ctx, "/auth.Authenticate/logout", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// AuthenticateServer is the server API for Authenticate service.
// All implementations must embed UnimplementedAuthenticateServer
// for forward compatibility
type AuthenticateServer interface {
PreLogin(context.Context, *User) (*ActionReply, error)
Login(context.Context, *User) (*LoginReply, error)
Logout(context.Context, *User) (*ActionReply, error)
mustEmbedUnimplementedAuthenticateServer()
}
// UnimplementedAuthenticateServer must be embedded to have forward compatible implementations.
type UnimplementedAuthenticateServer struct {
}
func (UnimplementedAuthenticateServer) PreLogin(context.Context, *User) (*ActionReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method PreLogin not implemented")
}
func (UnimplementedAuthenticateServer) Login(context.Context, *User) (*LoginReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method Login not implemented")
}
func (UnimplementedAuthenticateServer) Logout(context.Context, *User) (*ActionReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method Logout not implemented")
}
func (UnimplementedAuthenticateServer) mustEmbedUnimplementedAuthenticateServer() {}
// UnsafeAuthenticateServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to AuthenticateServer will
// result in compilation errors.
type UnsafeAuthenticateServer interface {
mustEmbedUnimplementedAuthenticateServer()
}
func RegisterAuthenticateServer(s grpc.ServiceRegistrar, srv AuthenticateServer) {
s.RegisterService(&Authenticate_ServiceDesc, srv)
}
func _Authenticate_PreLogin_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(User)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthenticateServer).PreLogin(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/auth.Authenticate/preLogin",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthenticateServer).PreLogin(ctx, req.(*User))
}
return interceptor(ctx, in, info, handler)
}
func _Authenticate_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(User)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthenticateServer).Login(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/auth.Authenticate/login",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthenticateServer).Login(ctx, req.(*User))
}
return interceptor(ctx, in, info, handler)
}
func _Authenticate_Logout_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(User)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthenticateServer).Logout(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/auth.Authenticate/logout",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthenticateServer).Logout(ctx, req.(*User))
}
return interceptor(ctx, in, info, handler)
}
// Authenticate_ServiceDesc is the grpc.ServiceDesc for Authenticate service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var Authenticate_ServiceDesc = grpc.ServiceDesc{
ServiceName: "auth.Authenticate",
HandlerType: (*AuthenticateServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "preLogin",
Handler: _Authenticate_PreLogin_Handler,
},
{
MethodName: "login",
Handler: _Authenticate_Login_Handler,
},
{
MethodName: "logout",
Handler: _Authenticate_Logout_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "v1/auth.proto",
}

@ -0,0 +1,16 @@
version: v1
managed:
enabled: true
go_package_prefix:
default: github.com/rocboss/paopao-ce/auto/rpc
except:
- buf.build/googleapis/googleapis
plugins:
- plugin: go
out: auto/rpc
opt: paths=source_relative
- plugin: go-grpc
out: auto/rpc
opt:
- paths=source_relative
- require_unimplemented_servers=true

@ -0,0 +1,3 @@
version: v1
directories:
- proto

@ -1,4 +1,5 @@
App: # APP基础设置项
RunMode: debug
AttachmentIncomeRate: 0.8
MaxCommentCount: 10
DefaultContextTimeout: 60
@ -11,19 +12,59 @@ Server: # 服务设置
ReadTimeout: 60
WriteTimeout: 60
Features:
Default: ["Base", "MySQL", "Option", "Zinc", "LocalOSS", "LoggerFile", "Friendship"]
Default: ["Base", "MySQL", "Option", "Zinc", "LocalOSS", "LoggerFile", "Friendship", "Deprecated"]
Develop: ["Base", "MySQL", "BigCacheIndex", "Meili", "Sms", "AliOSS", "LoggerMeili", "OSS:Retention"]
Demo: ["Base", "MySQL", "Option", "Zinc", "Sms", "MinIO", "LoggerZinc", "Migration"]
Slim: ["Base", "Sqlite3", "LocalOSS", "LoggerFile", "OSS:TempDir"]
Base: ["Redis", "PhoneBind"]
Docs: ["Docs:OpenAPI"]
Deprecated: ["Deprecated:OldWeb"]
Service: ["Web", "Admin", "SpaceX", "Bot", "LocalOSS", "Mobile", "Frontend:Web", "Fronetend:EmbedWeb", "Docs"]
Option: ["SimpleCacheIndex"]
Sms: "SmsJuhe"
WebServer: # Web服务
HttpIp: 0.0.0.0
HttpPort: 8010
ReadTimeout: 60
WriteTimeout: 60
AdminServer: # Admin后台运维服务
HttpIp: 0.0.0.0
HttpPort: 8014
ReadTimeout: 60
WriteTimeout: 60
SpaceXServer: # SpaceX服务
HttpIp: 0.0.0.0
HttpPort: 8012
ReadTimeout: 60
WriteTimeout: 60
BotServer: # Bot服务
HttpIp: 0.0.0.0
HttpPort: 8016
ReadTimeout: 60
WriteTimeout: 60
LocalossServer: # Localoss服务
HttpIp: 0.0.0.0
HttpPort: 8018
ReadTimeout: 60
WriteTimeout: 60
FrontendWebServer: # Web前端服务
HttpIp: 0.0.0.0
HttpPort: 8006
ReadTimeout: 60
WriteTimeout: 60
DocsServer: # 开发文档服务
HttpIp: 0.0.0.0
HttpPort: 8011
ReadTimeout: 60
WriteTimeout: 60
MobileServer: # 移动端grpc api服务
Host: 0.0.0.0
Port: 8020
SmsJuhe:
Gateway: https://v.juhe.cn/sms/send
Key:
TplID:
TplVal: "#code#=%d&#m#=%d"
TplVal: "#code#=%s&#m#=%d"
Alipay:
AppID:
InProduction: True

@ -4,3 +4,4 @@
* [openapi](openapi): api相关文档
* [proposal](proposal): 开发/设计 提按相关文档
* [deploy](deploy): 部署相关文档
* [discuss](discuss): 开发者交流

@ -1,2 +1,9 @@
## 部署文档
TODO
本目录包含一些paopao-ce部署相关的帮助文档
* [core](./core) - paopao-ce部署帮助文档
* [aliyun](./aliyun) - Aliyun平台部署文档
* [huawei](./huawei) - Huawei Cloud平台部署文档
* [tencnet](./tencent) - Tencent Cloud平台部署文档
* [local](./local) - 本地部署文档
* [k8s](./k8s) - 使用Kubernetes部署paopao-ce相关文档

@ -0,0 +1,2 @@
### Aliyun平台部署文档
本目录包含一些阿里云平台部署paopao-ce的一些帮助文档。

@ -0,0 +1,95 @@
### 配置文件说明
paopao-ce使用YAML格式的`conf.yml`作为配置文件。[`config.yaml.sample`](../../../config.yaml.sample) 是一份完整的配置文件模版paopao-ce启动时会读取`./custom/config.yaml`、`./config.yaml`任意一份配置文件(优先读取最先找到的文件)。
```sh
cp config.yaml.sample config.yaml
vim config.yaml # 修改参数
paopao-ce
```
配置文件中的 `Features` 小节是声明paopao-ce运行时开启哪些功能项:
```yaml
...
Features:
Default: ["Base", "MySQL", "Option", "LocalOSS", "LoggerFile"]
Develop: ["Base", "MySQL", "Option", "Sms", "AliOSS", "LoggerZinc"]
Demo: ["Base", "MySQL", "Option", "Sms", "MinIO", "LoggerZinc"]
Slim: ["Base", "Sqlite3", "LocalOSS", "LoggerFile"]
Base: ["Zinc", "Redis", "Alipay",]
Option: ["SimpleCacheIndex"]
Sms: "SmsJuhe"
...
```
如上:
Default/Develop/Demo/Slim 是不同 功能集套件(Features Suite) Base/Option 是子功能套件, Sms是关于短信验证码功能的参数选项。
这里 `Default`套件 代表的意思是: 使用`Base/Option` 中的功能,外加 `MySQL/LocalOSS/LoggerFile`功能,也就是说开启了`Zinc/Redis/Alipay/SimpleCacheIndex/MySQL/LocalOSS/LoggerFile` 7项功能
`Develop`套件依例类推。
使用Feautures:
```sh
release/paopao-ce --help
Usage of release/paopao-ce:
-features value
use special features
-no-default-features
whether use default features
# 默认使用 Default 功能套件
release/paopao-ce
# 不包含 default 中的功能集,仅仅使用 develop 中声明的功能集
release/paopao-ce --no-default-features --features develop
# 使用 default 中的功能集,外加 sms 功能
release/paopao-ce --features sms
# 手动指定需要开启的功能集
release/paopao-ce --no-default-features --features sqlite3,localoss,loggerfile,redis
```
目前支持的功能集合:
| 功能项 | 类别 | 状态 | 备注 |
| ----- | ----- | ----- | ----- |
|`OldWeb` | 子服务 | 稳定(默认) | 开启旧的Web服务 |
|`Web` | 子服务 | WIP | 开启Web服务|
|`Admin` | 子服务 | WIP | 开启Admin后台运维服务|
|`SpaceX` | 子服务 | WIP | 开启SpaceX服务|
|`Bot` | 子服务 | WIP | 开启Bot服务|
|`NativeOBS` | 子服务 | WIP | 开启NativeOBS服务|
|`Deprecated:Web` | 子服务 | 稳定 | Deprecated(关闭) OldWeb服务|
|`Gorm` | 数据库 | 稳定(默认) | 使用[gorm](https://github.com/go-gorm/gorm)作为数据库的ORM默认使用 `Gorm` + `MySQL`组合|
|`Sqlx`| 数据库 | WIP | 使用[sqlx](https://github.com/jmoiron/sqlx)作为数据库的ORM|
|`MySQL`| 数据库 | 稳定(默认) | 使用MySQL作为数据库|
|`Postgres`| 数据库 | 稳定 | 使用PostgreSQL作为数据库|
|`Sqlite3`| 数据库 | 稳定 | 使用Sqlite3作为数据库|
|`AliOSS` | 对象存储 | 稳定(推荐) |阿里云对象存储服务|
|`COS` | 对象存储 | 内测 |腾讯云对象存储服务|
|`HuaweiOBS` | 对象存储 | 内测 |华为云对象存储服务|
|`MinIO` | 对象存储 | 稳定 |[MinIO](https://github.com/minio/minio)对象存储服务|
|`S3` | 对象存储 | 内测 |AWS S3兼容的对象存储服务|
|`LocalOSS` | 对象存储 | 内测 |提供使用本地目录文件作为对象存储的功能,仅用于开发调试环境|
|`OSS:Retention` | 对象存储 | 内测 |基于对象存储系统的对象过期自动删除特性实现 先创建临时对象再持久化的功能|
|`OSS:TempDir` | 对象存储 | 内测 |基于对象存储系统的对象拷贝/移动特性实现 先创建临时对象再持久化的功能|
|`Redis` | 缓存 | 稳定 | Redis缓存功能 |
|`SimpleCacheIndex` | 缓存 | 稳定 | 提供简单的 广场推文列表 的缓存功能 |
|`BigCacheIndex` | 缓存 | 稳定(推荐) | 使用[BigCache](https://github.com/allegro/bigcache)缓存 广场推文列表,缓存每个用户每一页,简单做到千人千面 |
|`Zinc` | 搜索 | 稳定(推荐) | 基于[Zinc](https://github.com/zinclabs/zinc)搜索引擎提供推文搜索服务 |
|`Meili` | 搜索 | 稳定(推荐) | 基于[Meilisearch](https://github.com/meilisearch/meilisearch)搜索引擎提供推文搜索服务 |
|`Bleve` | 搜索 | WIP | 基于[Bleve](https://github.com/blevesearch/bleve)搜索引擎提供推文搜索服务 |
|`LoggerFile` | 日志 | 稳定 | 使用文件写日志 |
|`LoggerZinc` | 日志 | 稳定(推荐) | 使用[Zinc](https://github.com/zinclabs/zinc)写日志 |
|`LoggerMeili` | 日志 | 内测 | 使用[Meilisearch](https://github.com/meilisearch/meilisearch)写日志 |
|`Friendship` | 关系模式 | 内测(默认) | 弱关系好友模式,类似微信朋友圈 |
|`Followship` | 关系模式 | WIP | 关注者模式类似Twitter的Follow模式 |
|`Alipay` | 支付 | 稳定 | 开启基于[支付宝开放平台](https://open.alipay.com/)的钱包功能 |
|`Sms` | 短信验证 | 稳定 | 开启短信验证码功能,用于手机绑定验证手机是否注册者的;功能如果没有开启,手机绑定时任意短信验证码都可以绑定手机 |
|`Docs:OpenAPI` | 开发文档 | 稳定 | 开启openapi文档功能提供web api文档说明(visit http://127.0.0.1:8008/docs/openapi) |
|`PhoneBind` | 其他 | 稳定 | 手机绑定功能 |
> 功能项状态详情参考 [features-status](../../../features-status.md).

@ -0,0 +1,4 @@
### paopao-ce部署帮助文档
本目录包含一些部署paopao-ce的一些帮助文档。
* [001-配置文件说明](./001-配置文件说明.md '001-配置文件说明')

@ -0,0 +1,2 @@
### Huawei Cloud平台部署文档
本目录包含一些华为云平台部署paopao-ce的一些帮助文档。

@ -0,0 +1,2 @@
### 使用Kubernetes部署paopao-ce相关文档
本目录包含一些k8s环境部署paopao-ce的一些帮助文档。

@ -0,0 +1,119 @@
### 本地开发依赖环境部署
本地开发依赖的环境部署帮助文档包括Zinc/Meili/Minio的部署。
#### [Zinc](https://github.com/zinclabs/zinc) 搜索引擎:
* Zinc运行
```sh
# 创建用于存放zinc数据的目录
mkdir -p data/zinc/data
# 使用Docker运行zinc
docker run -d --name zinc --user root -v ${PWD}/data/zinc/data:/data -p 4080:4080 -e ZINC_FIRST_ADMIN_USER=admin -e ZINC_FIRST_ADMIN_PASSWORD=admin -e DATA_PATH=/data public.ecr.aws/zinclabs/zinc:latest
# 查看zinc运行状态
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
41465feea2ff getmeili/meilisearch:v0.27.0 "tini -- /bin/sh -c …" 20 hours ago Up 20 hours 0.0.0.0:7700->7700/tcp paopao-ce-meili-1
7daf982ca062 public.ecr.aws/prabhat/zinc:latest "/go/bin/zinc" 3 weeks ago Up 6 days 0.0.0.0:4080->4080/tcp zinc
# 使用docker compose运行
docker compose up -d zinc
# visit http://localhost:4080 打开自带的ui管理界面
```
* 修改Zinc配置
```yaml
# features中加上 Zinc 和 LoggerZinc
Features:
Default: ["Zinc", "LoggerZinc", "Base", "Sqlite3", "BigCacheIndex","MinIO"]
...
LoggerZinc: # 使用Zinc写日志
Host: 127.0.0.1:4080 # 这里的host就是paopao-ce能访问到的zinc主机
Index: paopao-log
User: admin
Password: admin
Secure: False # 如果使用https访问zinc就设置为True
...
Zinc: # Zinc搜索配置
Host: 127.0.0.1:4080
Index: paopao-data
User: admin
Password: admin
Secure: False
```
#### [Meilisearch](https://github.com/meilisearch/meilisearch) 搜索引擎:
* Meili运行
```sh
mkdir -p data/meili/data
# 使用Docker运行
docker run -d --name meili -v ${PWD}/data/meili/data:/meili_data -p 7700:7700 -e MEILI_MASTER_KEY=paopao-meilisearch getmeili/meilisearch:v0.29.0
# visit http://localhost:7700 打开自带的搜索前端ui
# 使用docker compose运行需要删除docker-compose.yaml中关于meili的注释
docker compose up -d meili
# 使用docker运行meilisearch的ui管理前端
docker run -d --name uirecord -p 7701:3000 bitriory/uirecord
# visit http://localhost:7701
# 使用docker compose运行meilisearch的ui管理前端需要删除docker-compose.yaml中关于uirecord的注释
docker compose up -d uirecord
# visit http://loclahost:7701
# 查看meili运行状态
docker compose ps
NAME COMMAND SERVICE STATUS PORTS
paopao-ce-meili-1 "tini -- /bin/sh -c …" meili running 0.0.0.0:7700->7700/tcp
paopao-ce-uirecord-1 "docker-entrypoint.s…" uirecord running 0.0.0.0:7701->3000/tcp
```
* 修改Meili配置
```yaml
# features中加上 Meili 和 LoggerMeili
Features:
Default: ["Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex","MinIO"]
...
LoggerMeili: # 使用Meili写日志
Host: 127.0.0.1:7700
Index: paopao-log
ApiKey: paopao-meilisearch
Secure: False
MinWorker: 5 # 最小后台工作者, 设置范围[5, 100], 默认5
MaxLogBuffer: 100 # 最大log缓存条数, 设置范围[10, 10000], 默认100
...
Meili: # Meili搜索配置
Host: 127.0.0.1:7700 # 这里的host就是paopao-ce能访问到的meili主机
Index: paopao-data
ApiKey: paopao-meilisearch
Secure: False # 如果使用https访问meili就设置为True
```
#### [MinIO](https://github.com/minio/minio) 对象存储服务
* MinIO运行
```sh
mkdir -p data/minio/data
# 使用Docker运行
docker run -d --name minio -v ${PWD}/data/minio/data:/data -p 9000:9000 -p 9001:9001 -e MINIO_ROOT_USER=minio-root-user -e MINIO_ROOT_PASSWORD=minio-root-password -e MINIO_DEFAULT_BUCKETS=paopao:public bitnami/minio:latest
# 使用docker compose运行 需要删除docker-compose.yaml中关于minio的注释
docker compose up -d minio
```
* 修改Minio配置
```yaml
# features中加上 MinIO
Features:
Default: ["MinIO", "Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex"]
...
MinIO: # MinIO 存储配置
AccessKey: Q3AM3UQ867SPQQA43P2F # AccessKey/SecretKey 需要登入minio管理界面手动创建管理界面地址: http://127.0.0.1:9001
SecretKey: zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG
Secure: False
Endpoint: 127.0.0.1:9000 # 根据部署的minio主机修改对应地址
Bucket: paopao # 如上需要在管理界面创建bucket并赋予外部可读写权限
Domain: 127.0.0.1:9000 # minio外网访问的地址(如果想让外网访问这里需要设置为外网可访问到的minio主机地址)
...
```

@ -0,0 +1,4 @@
### 本地部署文档
本目录包含一些本地开发环境部署paopao-ce的一些帮助文档。
* [001-本地开发依赖环境部署](001-本地开发依赖环境部署.md '001-本地开发依赖环境部署')

@ -0,0 +1,2 @@
### Tencent Cloud平台部署文档
本目录包含一些腾讯云平台部署paopao-ce的一些帮助文档。

@ -0,0 +1,26 @@
### <主题标题>
====== <这里写主题描述> =====
#### <话题标题>
====== <这里写话题描述> =====
* [北野](https://alimy.me) - 2022/12/14 10:07
> 这里就是你的观点论述了
* [北野](https://alimy.me) - 2022/12/14 10:07
> 这里就是你的观点论述了
* [北野](https://alimy.me) - 2022/12/14 10:07
> 这里就是你的观点论述了
* [北野](https://alimy.me) - 2022/12/14 10:07
> 这里就是你的观点论述了
* [北野](https://alimy.me) - 2022/12/14 10:07
> 这里就是你的回复
>> 这里就是你的观点论述了
* [北野](https://alimy.me) - 2022/12/14 10:07
> 你的回复
>> 这里就是你的回复
>>> 这里就是你的观点论述了

@ -0,0 +1,19 @@
### FAQs 常见问题
一些常见问题的解答。
#### 为什么要在代码库[docs](../../docs/)中写开发文档,比如[proposal](../proposal/)提按文档?
* [北野](https://alimy.me) - 2022/12/14 10:20
> 这里有几个原因
> * 开发文档跟随代码库对开发者友好;
> * paopao-ce的开发是离散组织式开发代码寄存在GitHub并没有一个统一的开发平台
> * 为什么没有使用GitHub的Wiki写档这个后续会把一些文档Copy到WiKi。
> * 文档跟随代码将更好的与代码共存而且Markdown足够用于写文档这才是最核心的怎么简单怎么来。
#### 为什么要在代码库[docs](../../docs/)中包含一个[discuss](../discuss/)?难道没有其他可用工具更好完成这种工作吗比瑞slack/discord
* [北野](https://alimy.me) - 2022/12/14 10:32
> discuss目录包含一些关于代码库开发的一些方案讨论偏静态内容代码库内置这些方案讨论也便于git进行跟踪归档。
> 确实有其他一些社交类开发聊天工具可用比如slack/discord但是目前paopao-ce的开发者社区还比较小暂时还没有开通的必要。
* [北野](https://alimy.me) - 2022/12/14 10:50
> 再一个国内访问也不是特别方便,暂时采用目前这种土办法过渡一下,或许后期会选择一个社交平台供开发者交流,比如飞书~

@ -0,0 +1,5 @@
### Discuss 开发者交流
本目录包含一些开发相关的问题交流论述。
* [0000-讨论样式模版](./0000-讨论样式模版.md "讨论样式模版")
* [0001-FAQs](./0001-FAQs.md "FAQs")

@ -1,3 +1,7 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
//go:build docs
// +build docs

Before

Width:  |  Height:  |  Size: 598 KiB

After

Width:  |  Height:  |  Size: 598 KiB

Before

Width:  |  Height:  |  Size: 211 KiB

After

Width:  |  Height:  |  Size: 211 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

@ -0,0 +1 @@
<mxfile host="Electron" modified="2022-12-18T02:37:17.424Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.3.0 Chrome/104.0.5112.114 Electron/20.1.3 Safari/537.36" etag="wuUvG6m6S7FGdLUCFJyX" version="20.3.0" type="device"><diagram id="VpmZCMjdPAEy3pG4oY4d" name="Page-1">7Ztbc6M2FIB/jWbah2SQhAA/+rbdmaZNut6Zbh4xyDYNRh4ir+3++kpGYJDkeNPgS2s7mQQdXYDznSN0DjLA/fn6lzxczH5jMU0BcuI1wAOAEPRdV/yTkk0h6WAlmOZJrBrtBKPkb6qEjpIuk5i+NhpyxlKeLJrCiGUZjXhDFuY5WzWbTVjaPOsinFJDMIrC1JT+mcR8VkgD5O/kn2kynZVnhl6nqJmHZWN1J6+zMGarmggPAe7njPHiaL7u01Qqr9RL0e/TntrqwnKa8R/p8OUJr1d3vz4/Pj0PvqGHh8Fw9eWuo2h8D9OlumN1tXxTqiBnyyymchQH4N5qlnA6WoSRrF0J6EI24/NUlKA4fH2hPJqptpMkTUdqoHDJmRSxjCvK0FNN+ixluRBkLKNyCJ6zF6oJ1WXSnNP1XgXASq3CHimbU55vRJOyA1RolCkiR5FZ7cCSjpLNalCJr4ShMqZpNfZO3+JAqfw96ieG+hchE793Qr0f4lDTM3LKshqrwQlqEADCFMaE+gYJUdPxfBx6drItEMLEbRByPWgQgshCyD0aIM/0jyEBAQE9DIa+/NvrgaEHBMmeIw+CAegOZZteF3RwS84ELZ4jNZ2IiaqbJtNMCDlbaJyJKIeqNqUT3pIb4aYbkcCERIgFEjyeG/kGpdEfD4buxQy8kIfRJk0EhBwfJjAucD2MK0EYvUy3EB+XXAxT+ZMiQzRSwV5SJlx1pagNSKQJyUMWT8IWSJ2jMQoMRr+HPPne3jwHkaHIt+e5OKTBJLLNc14U0PFEm+deWSrvsBUfCjQ8pXZqeHwLHUSORadz8yDtWeSigx6ET+pBsFyv1CAJhWyW2flcaDKZoMjqQrE39oi+VGjRhbAPL8uFoAMNPF9pFsn7ucIpzi3XZJfDBxl8Pi/DFU3O6D5BRO3uMw6IS/QYqkU8BF4cHmzgud9+2sPjaXjwITxE/qhONXnxsXrV9rMHm/4UmydxnLYU3Far8MvhaUktiLCo+wn0OmAYgB4EXbiVDIC4WBlVIdANPkb7PxExIctS4sQRE3TMzMNjb3TNCz49ZEL+uUMm6JjZh1vMVPLB7tlnODPt8Dga/fQ4/ktmopEz4iyX6WVxtHnldP7zNbuXHk/Z3OvU8ZSZkjhLPKU7y/tjrDb4aPHUBbiXmZO4xVMXxAea6YhbPHVBeMx0xMnjqb0Rz3EDrTZ4BhfH00xfbF88OaDT376KckF3G2H1+vJtlKzCIBh+jPZFxlNEe5HrQstK3QYHHu09IYRm9mILpS8pVEHu/4+FHttaWXgnZmFmHkY0zIXukDPMpnKJfMULcaItxF0X3xOT2WmX4tBMR5wl0j2wFP+B5V8bhPwmITHfWQid+OljpiL6YTS7ak+CRPckdAGeZCYlrjlnpHtScH5PMrMOBhqaxV25eRFU+99qKJrc9I1eQjP55pusvCdl8Vn13BYGa9WzKG3K0jrhtW6i9Fyr2XWShbJPcd00NrZQanzEvbFlHtE31FLuhONhPqX8Lf0V7xVM5PVkum0Tn5LlNC3coX55NsrqDE8skQmHKgzX1juepw1R3KnqtbMVcyB9CwjUBio0YQy0Nbrqtj9ih2Z65WaH1Ya/g3ZYGOzNDD9qhsjMIrVqhsqcYN2YKtOym9POdOuGW7PjPabbohlW8eTNDk9lh2a67DjT4fts6t/Y71key0V66maHe+1QFHdf9iia774yg4f/AA==</diagram></mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

@ -0,0 +1 @@
<mxfile host="Electron" modified="2022-12-18T03:08:45.142Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.3.0 Chrome/104.0.5112.114 Electron/20.1.3 Safari/537.36" etag="5KgVRO2EoCvSEdzXInGm" version="20.3.0" type="device"><diagram id="WArqh_x3Gwkc2ZFlfPv4" name="Page-1">7Vxdc5s4FP01zOw+JAMS4uPRjp3tzrZNd/LQ7dOObGSbDQYX48Tur18JJBAI2ySBGCdOOwm6ErK45+j66iDQ4M1y+0eMV4svkUcCDejeVoMjDQADIUD/MMsus7jQzAzz2Pd4o8Jw7/8i3Khz68b3yLrUMImiIPFXZeM0CkMyTUo2HMfRU7nZLArKn7rCc6IY7qc4UK3ffS9ZZFYH2IX9E/HnC/HJhuVmNUssGvMrWS+wFz1JJjjW4E0cRUl2tNzekIA5T/glO+92T20+sJiESZMTfv5aPPl/TR7n/66mzv1/Xx6/bu+uLD64Rxxs+BXz0SY74YI42oQeYb3oGhw+LfyE3K/wlNU+UdCpbZEsA1oy6GGAJyQY4unDPD3tJgqimFaFUUjbD9cPJJkueE/rJI4ecq+yk2dRmHAKGBYr+0FQ7SE9qWLk10DihGz3esfIfU7JSqIlSeIdbZIzlXuC89TkxacCdCRsCwlwSxAVc6LN864LLOgBh+M50BgKNN/iaLt7HT6Si4EuyrwvJCNkVPyvAegh4nimAgKtccAEWgIx0R3eJBE1MVh8OqEGgT8PqTmJ2JAwL00pPiRuB0Mg5h7HEECggAj1GhDtzjAECoYrHNH/VxSeznA0juBIDIqkXYeja9kQ78GxjUnmlgGCDlQAMkANQGZnAMELQBJAEPUOIFMB6Dr9+YDoIL136KDj6QMJvQFLxIqvawmHMmhk6yf/sONrxEs/pJrRVi7sRCGkF5KdBJAo/+Ddp4XivLQkTswGSjwl/6vAQS8m2sRT0iDMJziek+Tod7oKsJxl1OAnbDEJcOI/lgdcByr/hG+RTy+lmN1uOcdBeoUX2YXys+RUstKRaVaSJVTpKHOE0lHKsfyyX0E7q0+0Oxnr4IV1b8o6u0+ss09GO/NCuzelnaPQboQTPMFrmqHe3g3v6e97gmOaroDbGzxddJi4HlshzmbEmk7rUiPPdie6fvIVom6WSQHUDMqEhkpKt7MMylXQvf/7s4LgeoFX7HC6C3wKZQyP4zjJQP88yQ25KnO3SWg3ea7LFRcF3DYcDsopK3JUXcWqk1W68rdY6kv+TqeQFSTs8lc4LDne+rlh+txwmjF5wOLSfIJ/o73Qz9crf35PnaazGXM1w0s/2GWnLKMwWmdA5fWZ11mtvtpmdurm5IrTfpAOA8dJWiWGQY/m2V9U1VwRdQKzpoJiXhJOQalbqGXEjtkaATE3IOrLY22NvK3A/UXdgKKbzPd5Tcp3UZe5Pq/LeM+KBfNpSeY+q0zZz+wp/5nFSIvSHJCMyjwo6lJU0iLKytl8KBpIV5HNiyZ+yqtyFxUzBbG5UnhJ8qm+K+zIluzZ3MnrLKmKz6HaOjqXcvtc+vwqgGkxR1E2lrnF2ykkzKYSnZ3ZbBKMfScRDRp6zyKaqhPXZwFn63EX9MzjqqorEjB9HM7TiPJOfG8KdvXG96pgu0cPPFeXI9Q3l6sSrOLs56x7X6icFOtl0HzBrLW47uXrsOPrXlCP74nWvdUblC9e91YJ1vG6125ZW3417XrOOnhhXRusa1lafjXr7J7TzrzQrg3aqdryV5pIbhXuPUvKa13NcZySl4DIhCW03Rq0YWepiaqNfhq0sEumrHFKAqjeghehiDG98aKqQbZxj32vE40WnGhaPXOiyNIPfXGIJclmGQymCRMUc+37M9s39y1a+4kfMdV7EiVJtNwrjktujrKVyU2+AVJXvoXyrYesMA/wei0qFIi48N9WwIBlvd1SlzLwLZcyjqqVXECiX34lkOxTg6TKKxeQACqDVCMKvC1Iqg5zAamqVJ483DVQbj4cSKZeBunk4a6BzvHxQDLKIJ083DWQBT4cSMgs5+AnD3cNNmh9PJBQGaSThzt1yX4BCYmN1H0Jd6oisBck6tSHQxJovbuOq5QHNUVD7OZ7pYAIxIN83PGGaZe7aCogAhce7miPgDiIY7yTmq1Yg/X+AUO9/nP2jss+2J4eZCNoVc10n6GFnDV9oGMdRr2x/iyek+2YPqZV/zl7xwUPtu+IPs9Qac6aPgi2FH2sPVGhbfpYxvOiD3JOEX0a6Ee0G3+1JsdFbLxeZdnCzN8yUvUlYwCoGnn4Wr9EU01JGTp7XNltIAidvddNw+yZ15vszTl3ryOrynV0Yq9ftqZILyg4ukfA7dXWFOX5nRfvEag+UdTxHgG3ToM68txC5VEDw+LPGlQfKPDv2GNEg9CLI7Zpv9kWbsaidD1eCSPVB3eqS/Ol73msj2FM6NDwhN9Zh0OeftDO0VBDo0PRg7/vhZ+s5W9ZkYl8YO7ujTX6tY7cyq3l19FQNIlmszXphhgtP5h4rhs0G8cjcIlHbdCuTslrKR59J5P3HYXsI1HIMPXy2vAKtsK+q8oZHUalBhriR9hJ2Tgq9Won5dlGpVyb6SIs/cliSYjZIAbe0g/fd4xyj8UoB5h9z40MvYGYmD3ZU/NCurrdjMz9Hl4v0sjU0grXcN3r8h0gKO73yE+m172ArrNFriH2SfTcc+WvSbPm/uZb+62BEtYDv1UZB/TTe65GzRrbGv1mHDja2NIcRxvaii/78X5K9vYLxP7lZ0o1Vvqjqe8ZY2WpXfbTGsIlfI2am8ri6U4ZXhHTO4C3RjYbI8251ZwRO6ApiGtoY1MbDrUBTJHXNXGHrY+AN3khZsv73pVXKBonR7VGlhq7mgPTSWtrw5E2THEejDV3nMI71hw1R+oNqk3e79c6quVYnGffp0O1RlOiEZiOc6inoXjE8GSojjTXSacxYID3FtXZbAb2vJrImljoTVC11btFLaGq8ZdzSLlz8VoOOP4f</diagram></mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

@ -1,11 +1,73 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 001| 北野 | 2022-11-04 | 2022-11-04 | v0.0 | 提议 |
| 001| 北野 | 2022-11-04 | 2022-12-19 | v1.0 | 提议 |
### 概述
## 概述
paopao-ce是一个清新文艺的微社区提供类似Twiter/微博的推文分享服务。paopao-ce的运营形态有点类似WordPress只不过WordPress是使用PHP语言开发的博客平台提供的是博客服务而paopao-ce提供的是类似Twitter的推文分享服务。paopao-ce 让 **个人或小组织** 可以快速、方便的部署一个提供**推文分享服务**的小站点,在有限范围内形成一个友善的社交小圈子微社区。
![](.assets/001-01.png)
TODO
### 更新记录
## 从运维角度思考
| 实例部署 | 站点部署 |
| ----- | ----- |
| ![](.assets/001-02.png)| ![](.assets/001-03.png) |
部署paopao-ce实例 数据存储需要使用 关系数据库、对象存储、搜索引擎、缓存paopao-ce支持多实例部署具体文档请参考[deploy](../deploy/)。
#### 关系数据库
* 本地(Native) - 部署 MySQL/PostgreSQL或者paopao-ce内嵌Sqlite3数据库
MySQL/PostgreSQL 可以采用 一主多从+备、一主+备、多主+备 的模式部署具体部署方式由运维者决定paopao-ce本身不关心 关系数据库 的部署方式,仅仅使用标准的方式连接关系数据库使用其数据存储服务。
* 云关系数据库 - 部署 云关系数据库
阿里云、腾讯云、华为云都提供云关系数据库服务如何开启服务请参考相应文档进行部署。paopao-ce采用标准方式连接其相应的数据库使用数据存储服务。
#### 对象存储
paopao-ce使用对象存储服务存储 图片/视频/附件 等推文资源。
* 本地(Native) - 部署OBS(Object Blob Storage System)
目前开发环境可以使用`localoss`功能提供简单的OBS服务, 也可以自行部署[MinIO](https://github.com/minio/minio)来提供对象存储服务。
* 云对象存储服务
阿里云、腾讯云、华为云都提供云对象存储服务,如何开启服务请参考相应文档进行部署。
#### 搜索引擎
paopao-ce目前支持 使用[Zinc](https://github.com/zinclabs/zinc) /[Meilisearch](https://github.com/meilisearch/meilisearch) 提供推文搜索服务,搜索引擎实例的部署请参考相应官方文档。
#### 缓存
paopao-ce目前支持Redis作为缓存存储引擎提供缓存服务请参考Redis官方文档进行实例部署。
## 从代码实现角度思考
paopao-ce在代码实现上采用 **单体架构模式、分层设计、功能模块化**,架构设计上可能略显保守,但是在使用新技术上却非常积极,比如搜索引擎就采用了近来新星[Zinc](https://github.com/zinclabs/zinc) /[Meilisearch](https://github.com/meilisearch/meilisearch)同时也不排斥各种云端服务包括阿里云、腾讯云、华为云的对象存储服务、关系数据库服务等。paopao-ce始终秉持着 **包容并蓄、能用就上、去繁就简** 的架构思维,努力打造一个能 **稳定运行、代码清晰、功能可扩展** 的开源项目。
![](.assets/006-01.png)
## 从人文角度思考
现在的互联网世界已经非常精彩各种社交媒体平台琳琅满目使用体验也非常友好。每个社交平台都有自己的运营方式都有自己的核心用户群体也有自己的产品灵魂都在不断的进行生态演进。比如Twitter、微博都已经从最初的推文分享服务演进到一个成熟的传媒平台注册用户非常庞大日均访问PV也是一个惊人的数字这就注定了平台的运营思维是多维度考量均衡的结果只能做到让用户群体的大多数人用户体验友好并不能满足所有人的需求。大平台有大平台的运营模式小站点有小站点的维系空间。对于类似Twitter这样的推文分享服务paopao-ce提供一种小站点部署模式采用类似WordPress的运维模式**个人/小组织** 能快速、便捷的拥有一个提供推文分享服务的小站点,以填补那些在大平台下难以享受到的用户体验,享受小圈子内的自由空间。
就像许巍唱的「曾经的你」这首歌中所说:"曾梦想仗剑走天涯~ 看一看世界的繁华~ 年少的心总有些轻狂~ 如今你四海为家~ ......" 曾经的你我也在 疯狂刷朋友圈、狂奔微博空间、畅游Twitter世界但是随着环境的改变、岁月的洗礼、心路的淬炼后你我可能已经不复当年的热情逐渐淡出朋友圈、沦为微博的稀客或许Twitter世界还有点吸引力但是总感觉表达的欲望不复从前了。是什么原因变成这样的呢原因可能很多也各自有自己的不同情形所至于此。但是总归一条那就是 **自由**; 如果有那么一个有限空间内,可以自由的 *谈天说地、品头论足、唠唠叨叨亦或自言自语*你我是否又能燃起表达的激情呢从这个角度来说paopao-ce就很契合这种需求曾经你我想拥有一个自己的博客小站点而使用WordPress那么今天想拥有一个自己的类似Twitter的推文分享服务小站点部署paopao-ce或许也是一个不错的选择。
一个产品应该有一个**属于自己的灵魂**,可以说 paopao-ce的宗旨就是 **打造一个清新文艺的微社区**。
## 疑问
1. paopao-ce主要针对哪些站点运营者
其实paopao-ce的运营形态有点类似WordPress只不过WordPress是使用PHP语言开发的博客平台提供的是博客服务而paopao-ce提供的是类似Twitter的推文分享服务。paopao-ce 让 **个人或小组织** 可以快速、方便的部署一个提供**推文分享服务**的小站点,有限范围内形成一个友善的社交小圈子微社区。
1. paopao-ce是一个清新文艺的微社区微社区的 `微` 是如何界定的?
* 首先从站点用户流量层面paopao-ce的部署一般针对的是小站点注册用户不是很多用户流量(QPS)也不会很高这种情形本身很契合paopao-ce对自身微社区的服务定位
* 从代码实现层面思考在数据存储层面的架构设计中已经假定paopao-ce提供服务的QPS不会很高因此不会考虑类似数据库 **分库分表** 这样的设计优化来应对数据库CRUD的流量冲击对站点推文数据的总容量也假定是单个SQL数据库提供满足查询需求的数据容量极限。
1. paopao-ce在代码实现上为什么采用单体架构模式
一个项目的架构设计是多方面考量均衡的结果,最终的目的是满足项目的需求与长远发展。
* 从架构模式的角度来说单体架构模式可以满足paopao-ce对自身服务定位的需求完全有能力承载预期的用户流量QPS所以采用单体模式架构设计是没有问题的
* 从运营者的角度来说,在能保障服务质量的前提下,最看重的还是运营成本的考量。提供一项保质保量的服务,可持续性是评价一项服务的重要指标。单体架构模式的项目部署简单,成本相对于分布式架构模式的项目也更低,假设门槛也没有那么高。黑猫白猫,能抓老鼠就是好猫, 在什么阶段就用什么技术,根据部署运营场景选择适合的技术来支撑服务,才是运营者明智的选择。
* 现在不管是单体架构模式亦或是云原生的分布式架构模式相应的技术栈生态都已经非常成熟技术本身没有优劣之分需要根据具体环境来适配合适的技术这样才能在你保证服务质量的同时保证服务的可持续性与经济性。说白了就是paopao-ce目前采用单体架构模式的设计满足优质服务的同时性价比最高。
1. 如果一个paopao-ce部署站点运营一段时间后QPS逐渐提高到一定程度目前架构的paopao-ce无法满足进一步的用户流量冲击是否会采用分布式技术栈进行优化
不会。paopao-ce将保守的采用目前的单体架构模式提供极致的QPS用户体验如果确实需要超高QPS需求的实例部署将另起炉灶开发另一款相应的产品或许会采用云原生的分布式技术栈生态进行架构设计这将是另一个paopao产品的故事序章了(前提是paopao能火出圈)。
## 更新记录
#### v0.0(2022-11-04) - 北野
* 初始文档,先占个位置
* 初始文档,先占个位置
#### v0.1(2022-12-17) - 北野
* 添加部署结构示意图
#### v0.2(2022-12-18) - 北野
* 添加部分内容
#### v1.0(2022-12-19) - 北野
* 补充部分内容

@ -39,24 +39,19 @@ Friendship功能提供好友间分享推文信息的机制更好的帮助用
### 疑问
1. 什么是弱关系好友体系?
**弱关系好友** 在Friendship中的表现就是 **你只能通过对方发表的推文去判断这个人的思想三观是否符合你的脾胃进而让你决定是否要与对方建立好友关系;这种好友关系前期是非常薄弱,只能通过相互间的推文产生灵魂共鸣,进而互为兴趣、互为好友。** 有别于弱关系,微信的生态就天然建立在强关系之上,微信好友大部分都是自己熟人、朋友甚至亲人,因此微信的朋友圈就是强关系好友体系下的小圈子社交,有时谨言慎行就非常必要,导致有很多人随着年龄成长到某个阶段,对微信朋友圈非常不感冒,很少甚至没有发朋友圈的欲望了,究其原因有一部分可能是圈内好友太熟了甚至有点“严肃”。需要注意的是,有些人的表达欲望并没有因为微信朋友圈这种 **强关系好友** *圈内社交环境* 而降低,仅仅只是被压抑住了,那么一个**弱关系好友**体系或许可以打开这部分人的表达欲望,使得他们可以在有限可控圈子内尽情表达、享受言论的自由。
2. 如何形成这种好友体系?
形成好友体系分 **建立、维持、解除** 好友关系。Friendship提供 *建立/解除* 好友关系的机制,泡泡广场的推文列表依据这个好友体系为每个用户生成个性化推文列表。而好友关系的**维持**本质上就是用户推文的持久更新、思想的持续演化使得好友对你一直保持兴趣Friendship也为每一条推文的访问权限进行**标记(私密/好友可见)**,这可以传达这样一种信息: **“时刻让好友知道我非常在乎好友、对好友特殊关照,你看这条推文就是只有我的好友(也就是你)才可以看到,够意思吧”!** 顺便一说,每一条推文的访问权限标记(公开/私密/好友可见)是建立Friendship弱关系体系的隐性催化剂可以加速Friendship的形成。
3. 如何开启这个功能?
**弱关系好友** 在Friendship中的表现就是 **你只能通过对方发表的推文去判断这个人的思想三观是否符合你的脾胃进而让你决定是否要与对方建立好友关系;这种好友关系前期是非常薄弱,只能通过相互间的推文产生灵魂共鸣,进而互为兴趣、互为好友。** 有别于弱关系,微信的生态就天然建立在强关系之上,微信好友大部分都是自己熟人、朋友甚至亲人,因此微信的朋友圈就是强关系好友体系下的小圈子社交,有时谨言慎行就非常必要,导致有很多人随着年龄成长到某个阶段,对微信朋友圈非常不感冒,很少甚至没有发朋友圈的欲望了,究其原因有一部分可能是圈内好友太熟了甚至有点“严肃”。需要注意的是,有些人的表达欲望并没有因为微信朋友圈这种 **强关系好友** *圈内社交环境* 而降低,仅仅只是被压抑住了,那么一个**弱关系好友**体系或许可以打开这部分人的表达欲望,使得他们可以在有限可控圈子内尽情表达、享受言论的自由。
2. 如何形成这种好友体系?
形成好友体系分 **建立、维持、解除** 好友关系。Friendship提供 *建立/解除* 好友关系的机制,泡泡广场的推文列表依据这个好友体系为每个用户生成个性化推文列表。而好友关系的**维持**本质上就是用户推文的持久更新、思想的持续演化使得好友对你一直保持兴趣Friendship也为每一条推文的访问权限进行**标记(私密/好友可见)**,这可以传达这样一种信息: **“时刻让好友知道我非常在乎好友、对好友特殊关照,你看这条推文就是只有我的好友(也就是你)才可以看到,够意思吧”!** 顺便一说,每一条推文的访问权限标记(公开/私密/好友可见)是建立Friendship弱关系体系的隐性催化剂可以加速Friendship的形成。
3. 如何开启这个功能?
在配置文件config.yaml中的`Features`中添加`Friendship`功能项开启该功能:
```yaml
...
# features中加上 Friendship
Features:
Default: ["Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex", "MinIO", "Friendship"]
Base: ["Redis", "PhoneBind"]
...
```
```yaml
...
# features中加上 Friendship
Features:
Default: ["Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex", "MinIO", "Friendship"]
Base: ["Redis", "PhoneBind"]
...
```
### 更新记录
#### v0.1(2022-11-04) - 北野

@ -0,0 +1,37 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 005| 北野 | 2022-11-21 | 2022-12-10 | v1.0 | 提议 |
### 引入go-mir优化后端架构设计
引入[github.com/alimy/mir/v3](https://github.com/alimy/mir)优化后端的架构设计,使得后端代码更具扩展型。
![](.assets/06-01.png)
### 需求
* 更方便添加后端功能项的实现;
* 优化代码结构,模块化、清晰化代码布局,使得更具扩展性;
* 兼容RESTful/gRPC 服务代码RESTful API是服务于Web/AdmingRPC API是提供给移动端(iOS/Android)的服务;
### 方案
依赖库:
* [go-mir](https://github.com/alimy/mir)
### 疑问
1. 为什么引入go-mir
* [go-mir](https://github.com/alimy/mir)是一套提供类似gRPC服务开发体验的快速开发RESTful API后端开发脚手架巧妙的借用golang语法作为DSL描述RESTful API通过代码生成的方式自动生成相对应的API接口、HTTP服务器框架初始化代码等提供类似gRPC的开发体验对后端开发者非常友好;
* 引入go-mir的另一个主要目的是加速后端服务的开发更好的保证代码风格的一致性;
* 践行 [006-关于paopao-ce的结构设计](006-关于paopao-ce的结构设计.md);
1. 为什么要兼容RESTful/gRPC服务
* RESTful API是提供给Web端使用的包括paopao-ce web端以及后期的运维端admin gRPC API是提供给移动端(iOS/Android)使用的服务;
* RESTful API天然对web端浏览器友好而gRPC生态对后端、移动端天然友好可以根据google-protocol-buffers DSL定义服务API自动生成服务端、客户端代码非常利于开发特别是移动端开发省去了编写客户端网络数据服务相关的业务逻辑只需要专注于页面逻辑编写后端数据获取的网络数据访问逻辑直接调用自动生成的gRPC API客户端代码即可大大的减轻移动端开发的心智负担;
* 后端引入gRPC主要就是考虑到移动端(iOS/Android)开发的开发效率在减轻移动端开发网络数据获取业务逻辑的心智负担上gRPC生态与RESTful生态相比优势明显因此强力引入;
* 再一个就是[go-mir](https://github.com/alimy/mir) v3为RESTful服务的开发提供类似gRPC服务的开发体验也为后端兼容RESTful/gRPC服务创造了很好的条件只要代码结构组织清晰将会有很好的后端开发体验;
>*目前移动端 iOS/Android APP还在规划中这里后续的后端gRPC API服务也是为此做准备敬请期待*
### 更新记录
#### v0.0(2022-11-21) - 北野
* 初始文档
#### v1.0(2022-12-10) - 北野
* 添加内容

@ -1,17 +1,19 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 006| 北野 | 2022-11-23 | 2022-11-23 | v0.0 | 提议 |
| 006| 北野 | 2022-11-23 | 2022-12-23 | v0.1 | 提议 |
### 关于paopao-ce的结构设计
![](.assets/06-01.png)
![](.assets/006-01.png)
### 疑问
1. 为什么要引入[go-mir](https://github.com/alimy/mir)?
TODO;
1. 为什么要兼容RESTful服务与gRPC服务
TODO
1. 为什么要引入[go-mir](https://github.com/alimy/mir)?
工欲善其事必先利其器。为了RESTFul API的后端开发体验可以媲美gRPC本人特意打造[go-mir](https://github.com/alimy/mir) v3版本来满足需求。[go-mir](https://github.com/alimy/mir)是一套使用golang自身语言生态实现的RESTFul API从接口定义到代码自动生成的脚手架辅助工具集便捷的实现快速后端开发体验颇有“程咬金的三板斧简单抡着就完事”的韵味。而从[go-mir](https://github.com/alimy/mir)的官方文档参考也可以看出其生成的代码也确实就将一个HTTP的请求/响应简单分成 `请求绑定`->`业务逻辑`->`结果渲染`三个步骤去完成生成的代码结构简单清晰与gRPC的生成代码有点类似。
1. 为什么要兼容RESTful服务与gRPC服务
RESTful服务与gRPC服务各自有擅长的场景在合适的场景使用最适合的技术去做相应的适配这是paopao-ce秉持的代码开发原则之一。
### 更新记录
#### v0.0(2022-11-23) - 北野
* 初始文档, 先占个位置
#### v0.0(2022-11-23) - 北野
* 初始文档, 先占个位置
#### v0.1(2022-12-23) - 北野
* 添加部分内容

@ -2,4 +2,5 @@
* [001-关于paopao-ce的设计定位](001-关于paopao-ce的设计定位.md "关于paopao-ce的设计定位")
* [002-关于Friendship功能项的设计](002-关于Friendship功能项的设计.md "关于Friendship功能项的设计")
* [003-关于Followship功能项的设计](003-关于Followship功能项的设计.md "关于Followship功能项的设计")
* [006-关于paopao-ce的结构设计](006-关于paopao-ce的结构设计.md "关于paopao-ce的结构设计")
* [005-引入go-mir优化后端架构设计](005-引入go-mir优化后端架构设计.md "引入go-mir优化后端架构设计")
* [006-关于paopao-ce的结构设计](006-关于paopao-ce的结构设计.md "关于paopao-ce的结构设计")

@ -11,8 +11,8 @@
* `Web` 开启Web服务(目前状态: WIP)
* [ ] 提按文档
* [x] 服务初始化逻辑
* [ ] 接口定义
* [ ] 业务逻辑实现
* [x] 接口定义
* [x] 业务逻辑实现
* `Admin` 开启Admin后台运维服务(目前状态: WIP)
* [ ] 提按文档
* [x] 服务初始化逻辑
@ -33,7 +33,16 @@
* [ ] 服务初始化逻辑
* [ ] 接口定义
* [ ] 业务逻辑实现
* `Deprecated:OldWeb` Deprecated(关闭)旧的Web服务(目前状态: WIP)
* `Docs` 开启NativeOBS服务(目前状态: WIP)
* [ ] 提按文档
* [x] 服务初始化逻辑
* `Frontend:Web` 开启独立前端服务(目前状态: 内测)
* [ ] 提按文档
* [x] 服务初始化逻辑
* `Frontend:EmbedWeb` 开启内嵌于后端Web API服务中的前端服务(目前状态: 内测)
* [ ] 提按文档
* [x] 服务初始化逻辑
* `Deprecated:OldWeb` 开启旧的Web服务(目前状态: 内测)
* [ ] 提按文档
* [x] 服务初始化逻辑

@ -5,7 +5,8 @@ go 1.18
require (
github.com/Masterminds/semver/v3 v3.1.1
github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868
github.com/alimy/cfg v0.1.0
github.com/alimy/cfg v0.3.0
github.com/alimy/mir/v3 v3.0.0-beta.4
github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible
github.com/allegro/bigcache/v3 v3.0.2
github.com/bytedance/sonic v1.5.0
@ -24,13 +25,14 @@ require (
github.com/huaweicloud/huaweicloud-sdk-go-obs v3.21.12+incompatible
github.com/json-iterator/go v1.1.12
github.com/meilisearch/meilisearch-go v0.21.0
github.com/minio/minio-go/v7 v7.0.27
github.com/sirupsen/logrus v1.8.1
github.com/minio/minio-go/v7 v7.0.45
github.com/sirupsen/logrus v1.9.0
github.com/smartwalle/alipay/v3 v3.1.7
github.com/spf13/viper v1.10.1
github.com/spf13/viper v1.14.0
github.com/tencentyun/cos-go-sdk-v5 v0.7.35
github.com/yinheli/mahonia v0.0.0-20131226213531-0eef680515cc
google.golang.org/protobuf v1.28.0
google.golang.org/grpc v1.50.1
google.golang.org/protobuf v1.28.1
gopkg.in/natefinch/lumberjack.v2 v2.0.0
gopkg.in/resty.v1 v1.12.0
gorm.io/driver/mysql v1.3.4
@ -51,7 +53,7 @@ require (
github.com/clbanning/mxj v1.8.4 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/fsnotify/fsnotify v1.5.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect
@ -59,7 +61,6 @@ require (
github.com/go-sql-driver/mysql v1.6.0 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.7 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
@ -77,51 +78,50 @@ require (
github.com/jinzhu/now v1.1.5 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/klauspost/compress v1.15.6 // indirect
github.com/klauspost/cpuid v1.3.1 // indirect
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
github.com/klauspost/compress v1.15.9 // indirect
github.com/klauspost/cpuid/v2 v2.1.0 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/lib/pq v1.10.2 // indirect
github.com/magiconair/properties v1.8.5 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-sqlite3 v1.14.12 // indirect
github.com/minio/md5-simd v1.1.0 // indirect
github.com/minio/sha256-simd v0.1.1 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/minio/md5-simd v1.1.2 // indirect
github.com/minio/sha256-simd v1.0.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mozillazg/go-httpheader v0.3.1 // indirect
github.com/pelletier/go-toml v1.9.4 // indirect
github.com/pelletier/go-toml/v2 v2.0.1 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
github.com/rs/xid v1.2.1 // indirect
github.com/rs/xid v1.4.0 // indirect
github.com/smartwalle/crypto4go v1.0.2 // indirect
github.com/spf13/afero v1.6.0 // indirect
github.com/spf13/cast v1.4.1 // indirect
github.com/spf13/afero v1.9.2 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
github.com/subosito/gotenv v1.4.1 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.7 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.37.1-0.20220607072126-8a320890c08d // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 // indirect
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 // indirect
golang.org/x/mod v0.5.0 // indirect
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect
golang.org/x/tools v0.1.5 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gopkg.in/ini.v1 v1.66.2 // indirect
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b // indirect
golang.org/x/sys v0.0.0-20220908164124-27713097b956 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect
golang.org/x/tools v0.1.12 // indirect
google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/uint128 v1.1.1 // indirect
modernc.org/cc/v3 v3.36.0 // indirect
modernc.org/ccgo/v3 v3.16.6 // indirect

126
go.sum

@ -6,6 +6,7 @@ cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSR
cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
@ -19,6 +20,7 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
@ -51,6 +53,7 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
@ -142,8 +145,10 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk=
github.com/alimy/cfg v0.1.0 h1:J7KDLEoVIjEBMGlQJb2ljad/d49gJ4Tsl2ogZ9XNhaY=
github.com/alimy/cfg v0.1.0/go.mod h1:rOxbasTH2srl6StAjNF5Vyi8bfrdkl3fLGmOYtSw81c=
github.com/alimy/cfg v0.3.0 h1:9xgA0QWVCPSq9fFNRcYahVCAX22IL9ts2wrTQPfAStY=
github.com/alimy/cfg v0.3.0/go.mod h1:rOxbasTH2srl6StAjNF5Vyi8bfrdkl3fLGmOYtSw81c=
github.com/alimy/mir/v3 v3.0.0-beta.4 h1:4++lea7OWmykHRVbF1nCnKOJXCvBifmnhe47e91aV6c=
github.com/alimy/mir/v3 v3.0.0-beta.4/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU=
github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible h1:9gWa46nstkJ9miBReJcN8Gq34cBFbzSpQZVVT9N09TM=
github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
@ -500,10 +505,11 @@ github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoD
github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/form3tech-oss/jwt-go v3.2.5+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/fsouza/fake-gcs-server v1.17.0/go.mod h1:D1rTE4YCyHFNa99oyJJ5HyclvN/0uQR+pM/VdlL83bw=
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
github.com/gabriel-vasile/mimetype v1.3.1/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8=
@ -700,8 +706,7 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0=
github.com/google/go-github/v39 v39.2.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
@ -724,6 +729,7 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
@ -744,6 +750,7 @@ github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
@ -948,14 +955,15 @@ github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.15.6 h1:6D9PcO8QWu0JyaQ2zUMmu16T1T+zjjEpP91guRsvDfY=
github.com/klauspost/compress v1.15.6/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s=
github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.1.0 h1:eyi1Ad2aNJMW95zcSbmGg7Cg6cq3ADwLpMAP96d8rF0=
github.com/klauspost/cpuid/v2 v2.1.0/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg=
github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@ -994,8 +1002,8 @@ github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@ -1050,16 +1058,15 @@ github.com/meilisearch/meilisearch-go v0.21.0 h1:SwYMWJVi6vDdSDJdOmbkJ4T26PavjYc
github.com/meilisearch/meilisearch-go v0.21.0/go.mod h1:3dvPYZGUWu40qHoTK187fmqF2lrarboPa5m2Yu2Seh4=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/minio/md5-simd v1.1.0 h1:QPfiOqlZH+Cj9teu0t9b1nTBfPbyTl16Of5MeuShdK4=
github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw=
github.com/minio/minio-go/v7 v7.0.27 h1:yJCvm78B+2+ll1PqO9eSD1as6Ibw3IYnnD8PyBEB2zo=
github.com/minio/minio-go/v7 v7.0.27/go.mod h1:x81+AX5gHSfCSqw7jxRKHvxUXMlE5uKX0Vb75Xk5yYg=
github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU=
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
github.com/minio/minio-go/v7 v7.0.45 h1:g4IeM9M9pW/Lo8AGGNOjBZYlvmtlE1N5TQEYWXRWzIs=
github.com/minio/minio-go/v7 v7.0.45/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASMg2/nvmbarw=
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
@ -1183,10 +1190,10 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml/v2 v2.0.1 h1:8e3L2cCQzLFi2CR4g7vGFuFxX7Jl1kKX8gW+iV0GUKU=
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg=
github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
@ -1204,6 +1211,7 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@ -1256,8 +1264,9 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY=
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@ -1289,8 +1298,9 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartwalle/alipay/v3 v3.1.7 h1:J4U5slABafKVD/b9gPCZe/3HAPB8Pa2NOYOPcugEJBo=
github.com/smartwalle/alipay/v3 v3.1.7/go.mod h1:cZUMCCnsux9YAxA0/f3PWUR+7wckWtE1BqxbVRtGij0=
github.com/smartwalle/crypto4go v1.0.2 h1:9DUEOOsPhmp00438L4oBdcL8EZG1zumecft5bWj5phI=
@ -1305,11 +1315,12 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw=
github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
@ -1325,8 +1336,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk=
github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU=
github.com/spf13/viper v1.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU=
github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As=
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
@ -1344,10 +1355,11 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
@ -1466,8 +1478,9 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
@ -1511,14 +1524,16 @@ golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWP
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU=
golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -1568,8 +1583,9 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.0 h1:UG21uOlmZabA4fW5i7ZX6bjw1xELEGg/ZLgZq9auk/Q=
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -1641,8 +1657,9 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b h1:tvrvnPFcdzp294diPnrdZZZ8XUt2Tyj7svb7X52iDuU=
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -1762,6 +1779,7 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -1800,8 +1818,11 @@ golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf h1:Fm4IcnUL803i92qDlmB0obyHmosDrxZWxJL3gIeNqOw=
golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956 h1:XeJjHH1KiLpKGb6lvMiksZ9l0fVUh+AmGcm0nOMEBOY=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@ -1815,8 +1836,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -1826,8 +1848,9 @@ golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 h1:M73Iuj3xbbb9Uk1DYhzydthsj6oOd6l9bpuFcNoUvTs=
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U=
golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -1902,19 +1925,20 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
@ -2010,7 +2034,9 @@ google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
@ -2038,8 +2064,9 @@ google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ6
google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106 h1:ErU+UA6wxadoU8nWrsy5MZUVBs75K17zUCsUCIfrXCE=
google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e h1:S9GbmC1iCgvbLyAokVCwiO6tVIrU9Y7c5oMx1V/ki/Y=
google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s=
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
@ -2072,8 +2099,9 @@ google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9K
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
@ -2088,8 +2116,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@ -2108,8 +2136,8 @@ gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWd
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI=
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=

@ -1,3 +1,7 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package conf
import (
@ -19,7 +23,15 @@ var (
MysqlSetting *MySQLSettingS
PostgresSetting *PostgresSettingS
Sqlite3Setting *Sqlite3SettingS
ServerSetting *ServerSettingS
ServerSetting *HttpServerSettingS
WebServerSetting *HttpServerSettingS
AdminServerSetting *HttpServerSettingS
SpaceXServerSetting *HttpServerSettingS
BotServerSetting *HttpServerSettingS
LocalossServerSetting *HttpServerSettingS
FrontendWebSetting *HttpServerSettingS
DocsServerSetting *HttpServerSettingS
MobileServerSetting *GRPCServerSettingS
AppSetting *AppSettingS
CacheIndexSetting *CacheIndexSettingS
SimpleCacheIndexSetting *SimpleCacheIndexSettingS
@ -54,41 +66,47 @@ func setupSetting(suite []string, noDefault bool) error {
}
objects := map[string]any{
"App": &AppSetting,
"Server": &ServerSetting,
"CacheIndex": &CacheIndexSetting,
"SimpleCacheIndex": &SimpleCacheIndexSetting,
"BigCacheIndex": &BigCacheIndexSetting,
"Alipay": &AlipaySetting,
"SmsJuhe": &SmsJuheSetting,
"Logger": &loggerSetting,
"LoggerFile": &loggerFileSetting,
"LoggerZinc": &loggerZincSetting,
"LoggerMeili": &loggerMeiliSetting,
"Database": &DatabaseSetting,
"MySQL": &MysqlSetting,
"Postgres": &PostgresSetting,
"Sqlite3": &Sqlite3Setting,
"TweetSearch": &TweetSearchSetting,
"Zinc": &ZincSetting,
"Meili": &MeiliSetting,
"Redis": &redisSetting,
"JWT": &JWTSetting,
"ObjectStorage": &ObjectStorage,
"AliOSS": &AliOSSSetting,
"COS": &COSSetting,
"HuaweiOBS": &HuaweiOBSSetting,
"MinIO": &MinIOSetting,
"LocalOSS": &LocalOSSSetting,
"S3": &S3Setting,
"App": &AppSetting,
"Server": &ServerSetting,
"WebServer": &WebServerSetting,
"AdminServer": &AdminServerSetting,
"SpaceXServer": &SpaceXServerSetting,
"BotServer": &BotServerSetting,
"LocalossServer": &LocalossServerSetting,
"FrontendWebServer": &FrontendWebSetting,
"DocsServer": &DocsServerSetting,
"MobileServer": &MobileServerSetting,
"CacheIndex": &CacheIndexSetting,
"SimpleCacheIndex": &SimpleCacheIndexSetting,
"BigCacheIndex": &BigCacheIndexSetting,
"Alipay": &AlipaySetting,
"SmsJuhe": &SmsJuheSetting,
"Logger": &loggerSetting,
"LoggerFile": &loggerFileSetting,
"LoggerZinc": &loggerZincSetting,
"LoggerMeili": &loggerMeiliSetting,
"Database": &DatabaseSetting,
"MySQL": &MysqlSetting,
"Postgres": &PostgresSetting,
"Sqlite3": &Sqlite3Setting,
"TweetSearch": &TweetSearchSetting,
"Zinc": &ZincSetting,
"Meili": &MeiliSetting,
"Redis": &redisSetting,
"JWT": &JWTSetting,
"ObjectStorage": &ObjectStorage,
"AliOSS": &AliOSSSetting,
"COS": &COSSetting,
"HuaweiOBS": &HuaweiOBSSetting,
"MinIO": &MinIOSetting,
"LocalOSS": &LocalOSSSetting,
"S3": &S3Setting,
}
if err = setting.Unmarshal(objects); err != nil {
return err
}
JWTSetting.Expire *= time.Second
ServerSetting.ReadTimeout *= time.Second
ServerSetting.WriteTimeout *= time.Second
SimpleCacheIndexSetting.CheckTickDuration *= time.Second
SimpleCacheIndexSetting.ExpireTickDuration *= time.Second
BigCacheIndexSetting.ExpireInSecond *= time.Second
@ -134,3 +152,10 @@ func GetOssDomain() string {
}
return uri + AliOSSSetting.Domain + "/"
}
func RunMode() string {
if !cfg.If("Deprecated:OldWeb") {
return ServerSetting.RunMode
}
return AppSetting.RunMode
}

@ -0,0 +1,178 @@
App: # APP基础设置项
RunMode: debug
AttachmentIncomeRate: 0.8
MaxCommentCount: 10
DefaultContextTimeout: 60
DefaultPageSize: 10
MaxPageSize: 100
Server: # 服务设置
RunMode: debug
HttpIp: 0.0.0.0
HttpPort: 8008
ReadTimeout: 60
WriteTimeout: 60
Features:
Default: []
WebServer: # Web服务
HttpIp: 0.0.0.0
HttpPort: 8010
ReadTimeout: 60
WriteTimeout: 60
AdminServer: # Admin后台运维服务
HttpIp: 0.0.0.0
HttpPort: 8014
ReadTimeout: 60
WriteTimeout: 60
SpaceXServer: # SpaceX服务
HttpIp: 0.0.0.0
HttpPort: 8012
ReadTimeout: 60
WriteTimeout: 60
BotServer: # Bot服务
HttpIp: 0.0.0.0
HttpPort: 8016
ReadTimeout: 60
WriteTimeout: 60
LocalossServer: # Localoss服务
HttpIp: 0.0.0.0
HttpPort: 8018
ReadTimeout: 60
WriteTimeout: 60
FrontendWebServer: # Web前端静态资源服务
HttpIp: 0.0.0.0
HttpPort: 8006
ReadTimeout: 60
WriteTimeout: 60
DocsServer: # 开发文档服务
HttpIp: 0.0.0.0
HttpPort: 8011
ReadTimeout: 60
WriteTimeout: 60
MobileServer: # 移动端grpc api服务
Host: 0.0.0.0
Port: 8020
SmsJuhe:
Gateway: https://v.juhe.cn/sms/send
Key:
TplID:
TplVal: "#code#=%s&#m#=%d"
Alipay:
AppID:
InProduction: True
RootCertFile: "custom/alipay/RootCert.crt"
PublicCertFile: "custom/alipay/CertPublicKey_RSA2.crt"
AppPublicCertFile: "custom/alipay/AppCertPublicKey.crt"
CacheIndex:
MaxUpdateQPS: 100 # 最大添加/删除/更新Post的QPS, 设置范围[10, 10000], 默认100
SimpleCacheIndex: # 缓存泡泡广场消息流
MaxIndexSize: 200 # 最大缓存条数
CheckTickDuration: 60 # 循环自检查每多少秒一次
ExpireTickDuration: 300 # 每多少秒后强制过期缓存, 设置为0禁止强制使缓存过期
BigCacheIndex: # 使用BigCache缓存泡泡广场消息流
MaxIndexPage: 1024 # 最大缓存页数必须是2^n, 代表最大同时缓存多少页数据
Verbose: False # 是否打印cache操作的log
ExpireInSecond: 300 # 多少秒(>0)后强制过期缓存
Logger: # 日志通用配置
Level: debug # 日志级别 panic|fatal|error|warn|info|debug|trace
LoggerFile: # 使用File写日志
SavePath: data/paopao-ce/logs
FileName: app
FileExt: .log
LoggerZinc: # 使用Zinc写日志
Host: zinc:4080
Index: paopao-log
User: admin
Password: admin
Secure: False
LoggerMeili: # 使用Meili写日志
Host: meili:7700
Index: paopao-log
ApiKey: paopao-meilisearch
Secure: False
MinWorker: 5 # 最小后台工作者, 设置范围[5, 100], 默认5
MaxLogBuffer: 100 # 最大log缓存条数, 设置范围[10, 10000], 默认100
JWT: # 鉴权加密
Secret: 18a6413dc4fe394c66345ebe501b2f26
Issuer: paopao-api
Expire: 86400
TweetSearch: # 推文关键字搜索相关配置
MaxUpdateQPS: 100 # 最大添加/删除/更新Post的QPS设置范围[10, 10000], 默认100
MinWorker: 10 # 最小后台更新工作者, 设置范围[5, 1000], 默认10
Zinc: # Zinc搜索配置
Host: zinc:4080
Index: paopao-data
User: admin
Password: admin
Secure: False
Meili: # Meili搜索配置
Host: meili:7700
Index: paopao-data
ApiKey: paopao-meilisearch
Secure: False
ObjectStorage: # 对象存储通用配置
RetainInDays: 2 # 临时对象过期时间多少天
TempDir: tmp # 临时对象存放目录名
AliOSS: # 阿里云OSS存储配置
Endpoint:
AccessKeyID:
AccessKeySecret:
Bucket:
Domain:
COS: # 腾讯云COS存储配置
SecretID:
SecretKey:
Region: ap-shanghai
Bucket: demo-1888888888
Domain:
HuaweiOBS: # 华为云OBS存储配置
AccessKey:
SecretKey:
Endpoint:
Bucket: paopao
Domain:
MinIO: # MinIO 存储配置
AccessKey: Q3AM3UQ867SPQQA43P2F
SecretKey: zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG
Secure: False
Endpoint: minio:9000
Bucket: paopao
Domain: 127.0.0.1:9000
S3: # Amazon S3 存储配置
AccessKey: "YOUR-ACCESSKEYID"
SecretKey: "YOUR-SECRETACCESSKEY"
Secure: True
Endpoint: s3.amazonaws.com
Bucket: paopao
Domain:
LocalOSS: # 本地文件OSS存储配置
SavePath: data/paopao-ce/oss
Secure: False
Bucket: paopao
Domain: 127.0.0.1:8008
Database: # Database通用配置
LogLevel: error # 日志级别 silent|error|warn|info
TablePrefix: p_ # 表名前缀
MySQL: # MySQL数据库
Username: paopao
Password: paopao
Host: db:3306
DBName: paopao
Charset: utf8mb4
ParseTime: True
MaxIdleConns: 10
MaxOpenConns: 30
Postgres: # PostgreSQL数据库
User: paopao
Password: paopao
DBName: paopao
Host: localhost
Port: 5432
SSLMode: disable
TimeZone: Asia/Shanghai
Sqlite3: # Sqlite3数据库
Path: data/sqlite3/paopao-ce.db
Redis:
Host: redis:6379
Password:
DB:

@ -1,3 +1,7 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package conf
import (

@ -1,3 +1,7 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
//go:build cgo
// +build cgo

@ -1,3 +1,7 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
//go:build !cgo
// +build !cgo

@ -1,3 +1,7 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package conf
import (

@ -1,3 +1,7 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package conf
import (

@ -1,3 +1,7 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package conf
import (

@ -1,6 +1,11 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package conf
import (
"embed"
"fmt"
"strings"
"time"
@ -10,6 +15,9 @@ import (
"gorm.io/gorm/logger"
)
//go:embed config.yaml
var files embed.FS
type Setting struct {
vp *viper.Viper
}
@ -41,7 +49,7 @@ type LoggerMeiliSettingS struct {
MinWorker int
}
type ServerSettingS struct {
type HttpServerSettingS struct {
RunMode string
HttpIp string
HttpPort string
@ -49,7 +57,13 @@ type ServerSettingS struct {
WriteTimeout time.Duration
}
type GRPCServerSettingS struct {
Host string
Port string
}
type AppSettingS struct {
RunMode string
MaxCommentCount int64
AttachmentIncomeRate float64
DefaultContextTimeout time.Duration
@ -199,13 +213,21 @@ type JWTSettingS struct {
}
func NewSetting() (*Setting, error) {
cfgFile, err := files.Open("config.yaml")
if err != nil {
return nil, err
}
defer cfgFile.Close()
vp := viper.New()
vp.SetConfigName("config")
vp.AddConfigPath(".")
vp.AddConfigPath("custom/")
vp.SetConfigType("yaml")
err := vp.ReadInConfig()
if err != nil {
if err = vp.ReadConfig(cfgFile); err != nil {
return nil, err
}
if err = vp.MergeInConfig(); err != nil {
return nil, err
}
@ -217,7 +239,6 @@ func (s *Setting) ReadSection(k string, v any) error {
if err != nil {
return err
}
return nil
}
@ -249,6 +270,14 @@ func (s *Setting) featuresInfoFrom(k string) (map[string][]string, map[string]st
return suites, kv
}
func (s *HttpServerSettingS) GetReadTimeout() time.Duration {
return s.ReadTimeout * time.Second
}
func (s *HttpServerSettingS) GetWriteTimeout() time.Duration {
return s.WriteTimeout * time.Second
}
func (s *MySQLSettingS) Dsn() string {
return fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=%s&parseTime=%t&loc=Local",
s.UserName,

@ -1,7 +1,10 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package core
import (
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/pkg/types"
)
@ -33,23 +36,17 @@ const (
ActCreateActivationCode
)
type act uint8
type FriendFilter map[int64]types.Empty
type FriendSet map[string]types.Empty
type (
act uint8
type Action struct {
Act act
UserId int64
}
FriendFilter map[int64]types.Empty
FriendSet map[string]types.Empty
// AuthorizationManageService 授权管理服务
type AuthorizationManageService interface {
IsAllow(user *model.User, action *Action) bool
BeFriendFilter(userId int64) FriendFilter
BeFriendIds(userId int64) ([]int64, error)
MyFriendSet(userId int64) FriendSet
}
Action struct {
Act act
UserId int64
}
)
func (f FriendFilter) IsFriend(userId int64) bool {
_, yeah := f[userId]
@ -57,7 +54,7 @@ func (f FriendFilter) IsFriend(userId int64) bool {
}
// IsAllow default true if user is admin
func (a act) IsAllow(user *model.User, userId int64, isFriend bool, isActivation bool) bool {
func (a act) IsAllow(user *User, userId int64, isFriend bool, isActivation bool) bool {
if user.IsAdmin {
return true
}
@ -116,3 +113,11 @@ func (a act) IsAllow(user *model.User, userId int64, isFriend bool, isActivation
return false
}
// AuthorizationManageService 授权管理服务
type AuthorizationManageService interface {
IsAllow(user *User, action *Action) bool
BeFriendFilter(userId int64) FriendFilter
BeFriendIds(userId int64) ([]int64, error)
MyFriendSet(userId int64) FriendSet
}

@ -1,6 +1,12 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package core
import "github.com/rocboss/paopao-ce/internal/model"
import (
"github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
)
const (
IdxActNop IdxAct = iota + 1
@ -15,7 +21,7 @@ type IdxAct uint8
type IndexAction struct {
Act IdxAct
Post *model.Post
Post *dbr.Post
}
func (a IdxAct) String() string {
@ -37,7 +43,7 @@ func (a IdxAct) String() string {
}
}
func NewIndexAction(act IdxAct, post *model.Post) *IndexAction {
func NewIndexAction(act IdxAct, post *dbr.Post) *IndexAction {
return &IndexAction{
Act: act,
Post: post,
@ -48,5 +54,5 @@ func NewIndexAction(act IdxAct, post *model.Post) *IndexAction {
type CacheIndexService interface {
IndexPostsService
SendAction(act IdxAct, post *model.Post)
SendAction(act IdxAct, post *dbr.Post)
}

@ -1,24 +1,36 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package core
import (
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
)
type (
Comment = dbr.Comment
CommentFormated = dbr.CommentFormated
CommentReply = dbr.CommentReply
CommentContent = dbr.CommentContent
CommentReplyFormated = dbr.CommentReplyFormated
)
// CommentService 评论检索服务
type CommentService interface {
GetComments(conditions *model.ConditionsT, offset, limit int) ([]*model.Comment, error)
GetCommentByID(id int64) (*model.Comment, error)
GetCommentCount(conditions *model.ConditionsT) (int64, error)
GetCommentReplyByID(id int64) (*model.CommentReply, error)
GetCommentContentsByIDs(ids []int64) ([]*model.CommentContent, error)
GetCommentRepliesByID(ids []int64) ([]*model.CommentReplyFormated, error)
GetComments(conditions *ConditionsT, offset, limit int) ([]*Comment, error)
GetCommentByID(id int64) (*Comment, error)
GetCommentCount(conditions *ConditionsT) (int64, error)
GetCommentReplyByID(id int64) (*CommentReply, error)
GetCommentContentsByIDs(ids []int64) ([]*CommentContent, error)
GetCommentRepliesByID(ids []int64) ([]*CommentReplyFormated, error)
}
// CommentManageService 评论管理服务
type CommentManageService interface {
DeleteComment(comment *model.Comment) error
CreateComment(comment *model.Comment) (*model.Comment, error)
CreateCommentReply(reply *model.CommentReply) (*model.CommentReply, error)
DeleteCommentReply(reply *model.CommentReply) error
CreateCommentContent(content *model.CommentContent) (*model.CommentContent, error)
DeleteComment(comment *Comment) error
CreateComment(comment *Comment) (*Comment, error)
CreateCommentReply(reply *CommentReply) (*CommentReply, error)
DeleteCommentReply(reply *CommentReply) error
CreateCommentContent(content *CommentContent) (*CommentContent, error)
}

@ -1,3 +1,7 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package core
// DataService 数据服务集成

@ -1,15 +1,36 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package core
import (
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
)
const (
MsgTypePost = dbr.MsgTypePost
MsgtypeComment = dbr.MsgtypeComment
MsgTypeReply = dbr.MsgTypeReply
MsgTypeWhisper = dbr.MsgTypeWhisper
MsgTypeRequestingFriend = dbr.MsgTypeRequestingFriend
MsgTypeSystem = dbr.MsgTypeSystem
MsgStatusUnread = dbr.MsgStatusUnread
MsgStatusReaded = dbr.MsgStatusReaded
)
type (
Message = dbr.Message
MessageFormated = dbr.MessageFormated
)
// MessageService 消息服务
type MessageService interface {
CreateMessage(msg *model.Message) (*model.Message, error)
CreateMessage(msg *Message) (*Message, error)
GetUnreadCount(userID int64) (int64, error)
GetMessageByID(id int64) (*model.Message, error)
ReadMessage(message *model.Message) error
GetMessages(conditions *model.ConditionsT, offset, limit int) ([]*model.MessageFormated, error)
GetMessageCount(conditions *model.ConditionsT) (int64, error)
GetMessageByID(id int64) (*Message, error)
ReadMessage(message *Message) error
GetMessages(conditions *ConditionsT, offset, limit int) ([]*MessageFormated, error)
GetMessageCount(conditions *ConditionsT) (int64, error)
}

@ -1,7 +1,11 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package core
import (
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
)
const (
@ -9,28 +13,39 @@ const (
SearchTypeTag SearchType = "tag"
)
type SearchType string
const (
PostVisitPublic = dbr.PostVisitPublic
PostVisitPrivate = dbr.PostVisitPrivate
PostVisitFriend = dbr.PostVisitFriend
PostVisitInvalid = dbr.PostVisitInvalid
)
type QueryReq struct {
Query string
Visibility []model.PostVisibleT
Type SearchType
}
type (
PostVisibleT = dbr.PostVisibleT
type QueryResp struct {
Items []*model.PostFormated
Total int64
}
SearchType string
type TsDocItem struct {
Post *model.Post
Content string
}
QueryReq struct {
Query string
Visibility []PostVisibleT
Type SearchType
}
QueryResp struct {
Items []*PostFormated
Total int64
}
TsDocItem struct {
Post *Post
Content string
}
)
// TweetSearchService tweet search service interface
type TweetSearchService interface {
IndexName() string
AddDocuments(data []TsDocItem, primaryKey ...string) (bool, error)
DeleteDocuments(identifiers []string) error
Search(user *model.User, q *QueryReq, offset, limit int) (*QueryResp, error)
Search(user *User, q *QueryReq, offset, limit int) (*QueryResp, error)
}

@ -1,17 +1,32 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package core
import (
"github.com/rocboss/paopao-ce/internal/model"
"time"
"github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
)
type (
Captcha = dbr.Captcha
)
// SecurityService 安全相关服务
type SecurityService interface {
GetLatestPhoneCaptcha(phone string) (*model.Captcha, error)
UsePhoneCaptcha(captcha *model.Captcha) error
GetLatestPhoneCaptcha(phone string) (*Captcha, error)
UsePhoneCaptcha(captcha *Captcha) error
SendPhoneCaptcha(phone string) error
}
// 附件检测服务
// AttachmentCheckService 附件检测服务
type AttachmentCheckService interface {
CheckAttachment(uri string) error
}
// PhoneVerifyService 手机验证服务
type PhoneVerifyService interface {
SendPhoneCaptcha(phone string, captcha string, expire time.Duration) error
}

@ -1,3 +1,7 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package core
import (

@ -1,13 +1,22 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package core
import (
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
)
type (
Tag = dbr.Tag
TagFormated = dbr.TagFormated
)
// TopicService 话题服务
type TopicService interface {
CreateTag(tag *model.Tag) (*model.Tag, error)
DeleteTag(tag *model.Tag) error
GetTags(conditions *model.ConditionsT, offset, limit int) ([]*model.Tag, error)
GetTagsByKeyword(keyword string) ([]*model.Tag, error)
CreateTag(tag *Tag) (*Tag, error)
DeleteTag(tag *Tag) error
GetTags(conditions *ConditionsT, offset, limit int) ([]*Tag, error)
GetTagsByKeyword(keyword string) ([]*Tag, error)
}

@ -1,49 +1,83 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package core
import (
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/internal/model/rest"
"github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
)
const (
AttachmentTypeImage = dbr.AttachmentTypeImage
AttachmentTypeVideo = dbr.AttachmentTypeVideo
AttachmentTypeOther = dbr.AttachmentTypeOther
// 类型1标题2文字段落3图片地址4视频地址5语音地址6链接地址7附件资源
ContentTypeTitle = dbr.ContentTypeTitle
ContentTypeText = dbr.ContentTypeText
ContentTypeImage = dbr.ContentTypeImage
ContentTypeVideo = dbr.ContentTypeVideo
ContentTypeAudio = dbr.ContentTypeAudio
ContentTypeLink = dbr.ContentTypeLink
ContentTypeAttachment = dbr.ContentTypeAttachment
ContentTypeChargeAttachment = dbr.ContentTypeChargeAttachment
)
type (
PostStar = dbr.PostStar
PostCollection = dbr.PostCollection
PostAttachmentBill = dbr.PostAttachmentBill
PostContent = dbr.PostContent
Attachment = dbr.Attachment
AttachmentType = dbr.AttachmentType
PostContentT = dbr.PostContentT
IndexTweetList struct {
Tweets []*PostFormated
Total int64
}
)
// TweetService 推文检索服务
type TweetService interface {
GetPostByID(id int64) (*model.Post, error)
GetPosts(conditions *model.ConditionsT, offset, limit int) ([]*model.Post, error)
GetPostCount(conditions *model.ConditionsT) (int64, error)
GetUserPostStar(postID, userID int64) (*model.PostStar, error)
GetUserPostStars(userID int64, offset, limit int) ([]*model.PostStar, error)
GetPostByID(id int64) (*Post, error)
GetPosts(conditions *ConditionsT, offset, limit int) ([]*Post, error)
GetPostCount(conditions *ConditionsT) (int64, error)
GetUserPostStar(postID, userID int64) (*PostStar, error)
GetUserPostStars(userID int64, offset, limit int) ([]*PostStar, error)
GetUserPostStarCount(userID int64) (int64, error)
GetUserPostCollection(postID, userID int64) (*model.PostCollection, error)
GetUserPostCollections(userID int64, offset, limit int) ([]*model.PostCollection, error)
GetUserPostCollection(postID, userID int64) (*PostCollection, error)
GetUserPostCollections(userID int64, offset, limit int) ([]*PostCollection, error)
GetUserPostCollectionCount(userID int64) (int64, error)
GetPostAttatchmentBill(postID, userID int64) (*model.PostAttachmentBill, error)
GetPostContentsByIDs(ids []int64) ([]*model.PostContent, error)
GetPostContentByID(id int64) (*model.PostContent, error)
GetPostAttatchmentBill(postID, userID int64) (*PostAttachmentBill, error)
GetPostContentsByIDs(ids []int64) ([]*PostContent, error)
GetPostContentByID(id int64) (*PostContent, error)
}
// TweetManageService 推文管理服务,包括创建/删除/更新推文
type TweetManageService interface {
CreateAttachment(attachment *model.Attachment) (*model.Attachment, error)
CreatePost(post *model.Post) (*model.Post, error)
DeletePost(post *model.Post) ([]string, error)
LockPost(post *model.Post) error
StickPost(post *model.Post) error
VisiblePost(post *model.Post, visibility model.PostVisibleT) error
UpdatePost(post *model.Post) error
CreatePostStar(postID, userID int64) (*model.PostStar, error)
DeletePostStar(p *model.PostStar) error
CreatePostCollection(postID, userID int64) (*model.PostCollection, error)
DeletePostCollection(p *model.PostCollection) error
CreatePostContent(content *model.PostContent) (*model.PostContent, error)
CreateAttachment(attachment *Attachment) (*Attachment, error)
CreatePost(post *Post) (*Post, error)
DeletePost(post *Post) ([]string, error)
LockPost(post *Post) error
StickPost(post *Post) error
VisiblePost(post *Post, visibility PostVisibleT) error
UpdatePost(post *Post) error
CreatePostStar(postID, userID int64) (*PostStar, error)
DeletePostStar(p *PostStar) error
CreatePostCollection(postID, userID int64) (*PostCollection, error)
DeletePostCollection(p *PostCollection) error
CreatePostContent(content *PostContent) (*PostContent, error)
}
// TweetHelpService 推文辅助服务
type TweetHelpService interface {
RevampPosts(posts []*model.PostFormated) ([]*model.PostFormated, error)
MergePosts(posts []*model.Post) ([]*model.PostFormated, error)
RevampPosts(posts []*PostFormated) ([]*PostFormated, error)
MergePosts(posts []*Post) ([]*PostFormated, error)
}
// IndexPostsService 广场首页推文列表服务
type IndexPostsService interface {
IndexPosts(user *model.User, offset int, limit int) (*rest.IndexTweetsResp, error)
IndexPosts(user *User, offset int, limit int) (*IndexTweetList, error)
}

@ -0,0 +1,24 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package core
import (
"github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
)
const (
UserStatusNormal = dbr.UserStatusNormal
UserStatusClosed = dbr.UserStatusClosed
)
type (
User = dbr.User
Post = dbr.Post
ConditionsT = dbr.ConditionsT
PostFormated = dbr.PostFormated
UserFormated = dbr.UserFormated
PostContentFormated = dbr.PostContentFormated
Model = dbr.Model
)

@ -1,19 +1,33 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package core
import (
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/internal/model/rest"
type (
ContactItem struct {
UserId int64 `json:"user_id"`
UserName string `json:"username"`
Nickname string `json:"nickname"`
Avatar string `json:"avatar"`
Phone string `json:"phone"`
}
ContactList struct {
Contacts []ContactItem `json:"contacts"`
Total int64 `json:"total"`
}
)
// UserManageService 用户管理服务
type UserManageService interface {
GetUserByID(id int64) (*model.User, error)
GetUserByUsername(username string) (*model.User, error)
GetUserByPhone(phone string) (*model.User, error)
GetUsersByIDs(ids []int64) ([]*model.User, error)
GetUsersByKeyword(keyword string) ([]*model.User, error)
CreateUser(user *model.User) (*model.User, error)
UpdateUser(user *model.User) error
GetUserByID(id int64) (*User, error)
GetUserByUsername(username string) (*User, error)
GetUserByPhone(phone string) (*User, error)
GetUsersByIDs(ids []int64) ([]*User, error)
GetUsersByKeyword(keyword string) ([]*User, error)
CreateUser(user *User) (*User, error)
UpdateUser(user *User) error
}
// ContactManageService 联系人管理服务
@ -22,6 +36,6 @@ type ContactManageService interface {
AddFriend(userId int64, friendId int64) error
RejectFriend(userId int64, friendId int64) error
DeleteFriend(userId int64, friendId int64) error
GetContacts(userId int64, offset int, limit int) (*rest.ContactsResp, error)
GetContacts(userId int64, offset int, limit int) (*ContactList, error)
IsFriend(userID int64, friendID int64) bool
}

@ -1,3 +1,7 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package core
import (

@ -1,15 +1,24 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package core
import (
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
)
type (
WalletStatement = dbr.WalletStatement
WalletRecharge = dbr.WalletRecharge
)
// WalletService wallet service interface
type WalletService interface {
GetUserWalletBills(userID int64, offset, limit int) ([]*model.WalletStatement, error)
GetUserWalletBills(userID int64, offset, limit int) ([]*WalletStatement, error)
GetUserWalletBillCount(userID int64) (int64, error)
GetRechargeByID(id int64) (*model.WalletRecharge, error)
CreateRecharge(userId, amount int64) (*model.WalletRecharge, error)
HandleRechargeSuccess(recharge *model.WalletRecharge, tradeNo string) error
HandlePostAttachmentBought(post *model.Post, user *model.User) error
GetRechargeByID(id int64) (*WalletRecharge, error)
CreateRecharge(userId, amount int64) (*WalletRecharge, error)
HandleRechargeSuccess(recharge *WalletRecharge, tradeNo string) error
HandlePostAttachmentBought(post *Post, user *User) error
}

@ -1,3 +1,7 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package cache
import (
@ -11,8 +15,6 @@ import (
"github.com/Masterminds/semver/v3"
"github.com/allegro/bigcache/v3"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/internal/model/rest"
"github.com/rocboss/paopao-ce/pkg/types"
"github.com/sirupsen/logrus"
)
@ -24,7 +26,7 @@ var (
type postsEntry struct {
key string
tweets *rest.IndexTweetsResp
tweets *core.IndexTweetList
}
type bigCacheIndexServant struct {
@ -38,7 +40,7 @@ type bigCacheIndexServant struct {
preventDuration time.Duration
}
func (s *bigCacheIndexServant) IndexPosts(user *model.User, offset int, limit int) (*rest.IndexTweetsResp, error) {
func (s *bigCacheIndexServant) IndexPosts(user *core.User, offset int, limit int) (*core.IndexTweetList, error) {
key := s.keyFrom(user, offset, limit)
posts, err := s.getPosts(key)
if err == nil {
@ -54,7 +56,7 @@ func (s *bigCacheIndexServant) IndexPosts(user *model.User, offset int, limit in
return posts, nil
}
func (s *bigCacheIndexServant) getPosts(key string) (*rest.IndexTweetsResp, error) {
func (s *bigCacheIndexServant) getPosts(key string) (*core.IndexTweetList, error) {
data, err := s.cache.Get(key)
if err != nil {
logrus.Debugf("bigCacheIndexServant.getPosts get posts by key: %s from cache err: %v", key, err)
@ -62,7 +64,7 @@ func (s *bigCacheIndexServant) getPosts(key string) (*rest.IndexTweetsResp, erro
}
buf := bytes.NewBuffer(data)
dec := gob.NewDecoder(buf)
var resp rest.IndexTweetsResp
var resp core.IndexTweetList
if err := dec.Decode(&resp); err != nil {
logrus.Debugf("bigCacheIndexServant.getPosts get posts from cache in decode err: %v", err)
return nil, err
@ -70,7 +72,7 @@ func (s *bigCacheIndexServant) getPosts(key string) (*rest.IndexTweetsResp, erro
return &resp, nil
}
func (s *bigCacheIndexServant) cachePosts(key string, tweets *rest.IndexTweetsResp) {
func (s *bigCacheIndexServant) cachePosts(key string, tweets *core.IndexTweetList) {
entry := &postsEntry{key: key, tweets: tweets}
select {
case s.cachePostsCh <- entry:
@ -96,7 +98,7 @@ func (s *bigCacheIndexServant) setPosts(entry *postsEntry) {
logrus.Debugf("bigCacheIndexServant.setPosts setPosts set cache by key: %s", entry.key)
}
func (s *bigCacheIndexServant) keyFrom(user *model.User, offset int, limit int) string {
func (s *bigCacheIndexServant) keyFrom(user *core.User, offset int, limit int) string {
var userId int64 = -1
if user != nil {
userId = user.ID
@ -104,7 +106,7 @@ func (s *bigCacheIndexServant) keyFrom(user *model.User, offset int, limit int)
return fmt.Sprintf("index:%d:%d:%d", userId, offset, limit)
}
func (s *bigCacheIndexServant) SendAction(act core.IdxAct, post *model.Post) {
func (s *bigCacheIndexServant) SendAction(act core.IdxAct, post *core.Post) {
action := core.NewIndexAction(act, post)
select {
case s.indexActionCh <- action:
@ -134,7 +136,7 @@ func (s *bigCacheIndexServant) handleIndexAction(action *core.IndexAction) {
// 创建/删除 私密推文特殊处理
switch act {
case core.IdxActCreatePost, core.IdxActDeletePost:
if post.Visibility == model.PostVisitPrivate {
if post.Visibility == core.PostVisitPrivate {
s.deleteCacheByUserId(post.UserID, true)
return
}

@ -1,3 +1,7 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package cache
import (

@ -1,10 +1,12 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package cache
import (
"github.com/Masterminds/semver/v3"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/internal/model/rest"
)
var (
@ -16,11 +18,11 @@ type noneCacheIndexServant struct {
ips core.IndexPostsService
}
func (s *noneCacheIndexServant) IndexPosts(user *model.User, offset int, limit int) (*rest.IndexTweetsResp, error) {
func (s *noneCacheIndexServant) IndexPosts(user *core.User, offset int, limit int) (*core.IndexTweetList, error) {
return s.ips.IndexPosts(user, offset, limit)
}
func (s *noneCacheIndexServant) SendAction(_act core.IdxAct, _post *model.Post) {
func (s *noneCacheIndexServant) SendAction(_act core.IdxAct, _post *core.Post) {
// empty
}

@ -1,3 +1,7 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package cache
import (
@ -6,8 +10,6 @@ import (
"github.com/Masterminds/semver/v3"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/internal/model/rest"
"github.com/sirupsen/logrus"
)
@ -20,21 +22,21 @@ type simpleCacheIndexServant struct {
ips core.IndexPostsService
indexActionCh chan core.IdxAct
indexPosts *rest.IndexTweetsResp
indexPosts *core.IndexTweetList
atomicIndex atomic.Value
maxIndexSize int
checkTick *time.Ticker
expireIndexTick *time.Ticker
}
func (s *simpleCacheIndexServant) IndexPosts(user *model.User, offset int, limit int) (*rest.IndexTweetsResp, error) {
cacheResp := s.atomicIndex.Load().(*rest.IndexTweetsResp)
func (s *simpleCacheIndexServant) IndexPosts(user *core.User, offset int, limit int) (*core.IndexTweetList, error) {
cacheResp := s.atomicIndex.Load().(*core.IndexTweetList)
end := offset + limit
if cacheResp != nil {
size := len(cacheResp.Tweets)
logrus.Debugf("simpleCacheIndexServant.IndexPosts get index posts from cache posts: %d offset:%d limit:%d start:%d, end:%d", size, offset, limit, offset, end)
if size >= end {
return &rest.IndexTweetsResp{
return &core.IndexTweetList{
Tweets: cacheResp.Tweets[offset:end],
Total: cacheResp.Total,
}, nil
@ -45,7 +47,7 @@ func (s *simpleCacheIndexServant) IndexPosts(user *model.User, offset int, limit
return s.ips.IndexPosts(user, offset, limit)
}
func (s *simpleCacheIndexServant) SendAction(act core.IdxAct, _post *model.Post) {
func (s *simpleCacheIndexServant) SendAction(act core.IdxAct, _post *core.Post) {
select {
case s.indexActionCh <- act:
logrus.Debugf("simpleCacheIndexServant.SendAction send indexAction by chan: %s", act)

@ -1,3 +1,7 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package dao
import (

@ -1,8 +1,12 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package jinzhu
import (
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
"github.com/rocboss/paopao-ce/pkg/types"
"gorm.io/gorm"
)
@ -21,7 +25,7 @@ func newAuthorizationManageService(db *gorm.DB) core.AuthorizationManageService
}
}
func (s *authorizationManageServant) IsAllow(user *model.User, action *core.Action) bool {
func (s *authorizationManageServant) IsAllow(user *core.User, action *core.Action) bool {
// user is activation if had bind phone
isActivation := (len(user.Phone) != 0)
isFriend := s.isFriend(user.ID, action.UserId)
@ -30,7 +34,7 @@ func (s *authorizationManageServant) IsAllow(user *model.User, action *core.Acti
}
func (s *authorizationManageServant) MyFriendSet(userId int64) core.FriendSet {
ids, err := (&model.Contact{UserId: userId}).MyFriendIds(s.db)
ids, err := (&dbr.Contact{UserId: userId}).MyFriendIds(s.db)
if err != nil {
return core.FriendSet{}
}
@ -43,7 +47,7 @@ func (s *authorizationManageServant) MyFriendSet(userId int64) core.FriendSet {
}
func (s *authorizationManageServant) BeFriendFilter(userId int64) core.FriendFilter {
ids, err := (&model.Contact{FriendId: userId}).BeFriendIds(s.db)
ids, err := (&dbr.Contact{FriendId: userId}).BeFriendIds(s.db)
if err != nil {
return core.FriendFilter{}
}
@ -56,12 +60,12 @@ func (s *authorizationManageServant) BeFriendFilter(userId int64) core.FriendFil
}
func (s *authorizationManageServant) BeFriendIds(userId int64) ([]int64, error) {
return (&model.Contact{FriendId: userId}).BeFriendIds(s.db)
return (&dbr.Contact{FriendId: userId}).BeFriendIds(s.db)
}
func (s *authorizationManageServant) isFriend(userId int64, friendId int64) bool {
contact, err := (&model.Contact{UserId: friendId, FriendId: userId}).GetByUserFriend(s.db)
if err == nil || contact.Status == model.ContactStatusAgree {
contact, err := (&dbr.Contact{UserId: friendId, FriendId: userId}).GetByUserFriend(s.db)
if err == nil || contact.Status == dbr.ContactStatusAgree {
return true
}
return false

@ -1,8 +1,12 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package jinzhu
import (
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
"gorm.io/gorm"
)
@ -31,42 +35,42 @@ func newCommentManageService(db *gorm.DB) core.CommentManageService {
}
}
func (s *commentServant) GetComments(conditions *model.ConditionsT, offset, limit int) ([]*model.Comment, error) {
return (&model.Comment{}).List(s.db, conditions, offset, limit)
func (s *commentServant) GetComments(conditions *core.ConditionsT, offset, limit int) ([]*core.Comment, error) {
return (&dbr.Comment{}).List(s.db, conditions, offset, limit)
}
func (s *commentServant) GetCommentByID(id int64) (*model.Comment, error) {
comment := &model.Comment{
Model: &model.Model{
func (s *commentServant) GetCommentByID(id int64) (*core.Comment, error) {
comment := &dbr.Comment{
Model: &dbr.Model{
ID: id,
},
}
return comment.Get(s.db)
}
func (s *commentServant) GetCommentReplyByID(id int64) (*model.CommentReply, error) {
reply := &model.CommentReply{
Model: &model.Model{
func (s *commentServant) GetCommentReplyByID(id int64) (*core.CommentReply, error) {
reply := &dbr.CommentReply{
Model: &dbr.Model{
ID: id,
},
}
return reply.Get(s.db)
}
func (s *commentServant) GetCommentCount(conditions *model.ConditionsT) (int64, error) {
return (&model.Comment{}).Count(s.db, conditions)
func (s *commentServant) GetCommentCount(conditions *core.ConditionsT) (int64, error) {
return (&dbr.Comment{}).Count(s.db, conditions)
}
func (s *commentServant) GetCommentContentsByIDs(ids []int64) ([]*model.CommentContent, error) {
commentContent := &model.CommentContent{}
return commentContent.List(s.db, &model.ConditionsT{
func (s *commentServant) GetCommentContentsByIDs(ids []int64) ([]*core.CommentContent, error) {
commentContent := &dbr.CommentContent{}
return commentContent.List(s.db, &dbr.ConditionsT{
"comment_id IN ?": ids,
}, 0, 0)
}
func (s *commentServant) GetCommentRepliesByID(ids []int64) ([]*model.CommentReplyFormated, error) {
CommentReply := &model.CommentReply{}
replies, err := CommentReply.List(s.db, &model.ConditionsT{
func (s *commentServant) GetCommentRepliesByID(ids []int64) ([]*core.CommentReplyFormated, error) {
CommentReply := &dbr.CommentReply{}
replies, err := CommentReply.List(s.db, &dbr.ConditionsT{
"comment_id IN ?": ids,
}, 0, 0)
@ -83,7 +87,7 @@ func (s *commentServant) GetCommentRepliesByID(ids []int64) ([]*model.CommentRep
if err != nil {
return nil, err
}
repliesFormated := []*model.CommentReplyFormated{}
repliesFormated := []*core.CommentReplyFormated{}
for _, reply := range replies {
replyFormated := reply.Format()
for _, user := range users {
@ -101,22 +105,22 @@ func (s *commentServant) GetCommentRepliesByID(ids []int64) ([]*model.CommentRep
return repliesFormated, nil
}
func (s *commentManageServant) DeleteComment(comment *model.Comment) error {
func (s *commentManageServant) DeleteComment(comment *core.Comment) error {
return comment.Delete(s.db)
}
func (s *commentManageServant) CreateComment(comment *model.Comment) (*model.Comment, error) {
func (s *commentManageServant) CreateComment(comment *core.Comment) (*core.Comment, error) {
return comment.Create(s.db)
}
func (s *commentManageServant) CreateCommentReply(reply *model.CommentReply) (*model.CommentReply, error) {
func (s *commentManageServant) CreateCommentReply(reply *core.CommentReply) (*core.CommentReply, error) {
return reply.Create(s.db)
}
func (s *commentManageServant) DeleteCommentReply(reply *model.CommentReply) error {
func (s *commentManageServant) DeleteCommentReply(reply *core.CommentReply) error {
return reply.Delete(s.db)
}
func (s *commentManageServant) CreateCommentContent(content *model.CommentContent) (*model.CommentContent, error) {
func (s *commentManageServant) CreateCommentContent(content *core.CommentContent) (*core.CommentContent, error) {
return content.Create(s.db)
}

@ -1,11 +1,14 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package jinzhu
import (
"time"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/internal/model/rest"
"github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
"github.com/sirupsen/logrus"
"gorm.io/gorm"
)
@ -24,14 +27,14 @@ func newContactManageService(db *gorm.DB) core.ContactManageService {
}
}
func (s *contactManageServant) fetchOrNewContact(db *gorm.DB, userId int64, friendId int64, status int8) (*model.Contact, error) {
contact := &model.Contact{
func (s *contactManageServant) fetchOrNewContact(db *gorm.DB, userId int64, friendId int64, status int8) (*dbr.Contact, error) {
contact := &dbr.Contact{
UserId: userId,
FriendId: friendId,
}
contact, err := contact.FetchUser(db)
if err != nil {
contact = &model.Contact{
contact = &dbr.Contact{
UserId: userId,
FriendId: friendId,
Status: status,
@ -54,17 +57,17 @@ func (s *contactManageServant) RequestingFriend(userId int64, friendId int64, gr
}
}()
contact, e := s.fetchOrNewContact(db, userId, friendId, model.ContactStatusRequesting)
contact, e := s.fetchOrNewContact(db, userId, friendId, dbr.ContactStatusRequesting)
if e != nil {
err = e
return
}
// 如果已经好友,啥也不干
if contact.Status == model.ContactStatusAgree {
if contact.Status == dbr.ContactStatusAgree {
return nil
} else if contact.Status == model.ContactStatusReject || contact.Status == model.ContactStatusDeleted {
contact.Status = model.ContactStatusRequesting
} else if contact.Status == dbr.ContactStatusReject || contact.Status == dbr.ContactStatusDeleted {
contact.Status = dbr.ContactStatusRequesting
contact.IsDel = 0 // remove deleted flag if needed
if err = contact.UpdateInUnscoped(db); err != nil {
logrus.Errorf("contactManageServant.RequestingFriend update exsit contact err:%s", err)
@ -72,13 +75,13 @@ func (s *contactManageServant) RequestingFriend(userId int64, friendId int64, gr
}
}
msg := &model.Message{
msg := &dbr.Message{
SenderUserID: userId,
ReceiverUserID: friendId,
Type: model.MsgTypeRequestingFriend,
Type: dbr.MsgTypeRequestingFriend,
Brief: "请求添加好友,并附言:",
Content: greetings,
ReplyID: int64(model.ContactStatusRequesting),
ReplyID: int64(dbr.ContactStatusRequesting),
}
if _, err = msg.Create(db); err != nil {
logrus.Errorf("contactManageServant.RequestingFriend create message err:%s", err)
@ -97,7 +100,7 @@ func (s *contactManageServant) AddFriend(userId int64, friendId int64) (err erro
}
}()
contact := &model.Contact{
contact := &dbr.Contact{
UserId: friendId,
FriendId: userId,
}
@ -105,23 +108,23 @@ func (s *contactManageServant) AddFriend(userId int64, friendId int64) (err erro
return
}
// 如果还不是请求好友,啥也不干
if contact.Status != model.ContactStatusRequesting {
if contact.Status != dbr.ContactStatusRequesting {
logrus.Debugf("contactManageServant.AddFriend not reuesting status now so skip")
return nil
}
contact.Status = model.ContactStatusAgree
contact.Status = dbr.ContactStatusAgree
if err = contact.Update(db); err != nil {
return err
}
contact, err = s.fetchOrNewContact(db, userId, friendId, model.ContactStatusAgree)
contact, err = s.fetchOrNewContact(db, userId, friendId, dbr.ContactStatusAgree)
if err != nil {
return
}
// 如果已经好友,啥也不干
if contact.Status != model.ContactStatusAgree {
contact.Status = model.ContactStatusAgree
if contact.Status != dbr.ContactStatusAgree {
contact.Status = dbr.ContactStatusAgree
contact.IsDel = 0 // remove deleted flag
if err = contact.UpdateInUnscoped(db); err != nil {
logrus.Errorf("contactManageServant.AddFriend update contact err:%s", err)
@ -129,8 +132,8 @@ func (s *contactManageServant) AddFriend(userId int64, friendId int64) (err erro
}
}
args := []any{userId, friendId, friendId, userId, model.MsgTypeRequestingFriend, model.ContactStatusRequesting}
msgs, e := (&model.Message{}).FetchBy(db, model.Predicates{
args := []any{userId, friendId, friendId, userId, dbr.MsgTypeRequestingFriend, dbr.ContactStatusRequesting}
msgs, e := (&dbr.Message{}).FetchBy(db, dbr.Predicates{
"((sender_user_id = ? AND receiver_user_id = ?) OR (sender_user_id = ? AND receiver_user_id = ?)) AND type = ? AND reply_id = ?": args,
})
if e != nil {
@ -138,7 +141,7 @@ func (s *contactManageServant) AddFriend(userId int64, friendId int64) (err erro
return
}
for _, msg := range msgs {
msg.ReplyID = int64(model.ContactStatusAgree)
msg.ReplyID = int64(dbr.ContactStatusAgree)
if err = msg.Update(db); err != nil {
return
}
@ -156,7 +159,7 @@ func (s *contactManageServant) RejectFriend(userId int64, friendId int64) (err e
}
}()
contact := &model.Contact{
contact := &dbr.Contact{
UserId: friendId,
FriendId: userId,
}
@ -164,16 +167,16 @@ func (s *contactManageServant) RejectFriend(userId int64, friendId int64) (err e
return
}
// 如果还不是请求好友,啥也不干
if contact.Status != model.ContactStatusRequesting {
if contact.Status != dbr.ContactStatusRequesting {
return nil
}
contact.Status = model.ContactStatusReject
contact.Status = dbr.ContactStatusReject
if err = contact.Update(db); err != nil {
return err
}
args := []any{friendId, userId, model.MsgTypeRequestingFriend, model.ContactStatusRequesting}
msgs, e := (&model.Message{}).FetchBy(db, model.Predicates{
args := []any{friendId, userId, dbr.MsgTypeRequestingFriend, dbr.ContactStatusRequesting}
msgs, e := (&dbr.Message{}).FetchBy(db, dbr.Predicates{
"sender_user_id = ? AND receiver_user_id = ? AND type = ? AND reply_id = ?": args,
})
if e != nil {
@ -181,7 +184,7 @@ func (s *contactManageServant) RejectFriend(userId int64, friendId int64) (err e
return
}
for _, msg := range msgs {
msg.ReplyID = int64(model.ContactStatusReject)
msg.ReplyID = int64(dbr.ContactStatusReject)
if err = msg.Update(db); err != nil {
return
}
@ -199,7 +202,7 @@ func (s *contactManageServant) DeleteFriend(userId int64, friendId int64) (err e
}
}()
contact := &model.Contact{
contact := &dbr.Contact{
UserId: userId,
FriendId: friendId,
}
@ -210,10 +213,10 @@ func (s *contactManageServant) DeleteFriend(userId int64, friendId int64) (err e
for _, contact := range contacts {
// 如果还不是好友,啥也不干
if contact.Status != model.ContactStatusAgree {
if contact.Status != dbr.ContactStatusAgree {
continue
}
contact.Status = model.ContactStatusDeleted
contact.Status = dbr.ContactStatusDeleted
contact.DeletedOn = time.Now().Unix()
contact.IsDel = 1
if err = contact.Update(db); err != nil {
@ -223,11 +226,11 @@ func (s *contactManageServant) DeleteFriend(userId int64, friendId int64) (err e
return nil
}
func (s *contactManageServant) GetContacts(userId int64, offset int, limit int) (*rest.ContactsResp, error) {
contact := &model.Contact{}
condition := model.ConditionsT{
func (s *contactManageServant) GetContacts(userId int64, offset int, limit int) (*core.ContactList, error) {
contact := &dbr.Contact{}
condition := dbr.ConditionsT{
"user_id": userId,
"status": model.ContactStatusAgree,
"status": dbr.ContactStatusAgree,
}
contacts, err := contact.List(s.db, condition, offset, limit)
if err != nil {
@ -237,13 +240,13 @@ func (s *contactManageServant) GetContacts(userId int64, offset int, limit int)
if err != nil {
return nil, err
}
resp := &rest.ContactsResp{
Contacts: make([]rest.ContactItem, 0, len(contacts)),
resp := &core.ContactList{
Contacts: make([]core.ContactItem, 0, len(contacts)),
Total: total,
}
for _, c := range contacts {
if c.User != nil {
resp.Contacts = append(resp.Contacts, rest.ContactItem{
resp.Contacts = append(resp.Contacts, core.ContactItem{
UserId: c.FriendId,
UserName: c.User.Username,
Nickname: c.User.Nickname,
@ -256,12 +259,12 @@ func (s *contactManageServant) GetContacts(userId int64, offset int, limit int)
}
func (s *contactManageServant) IsFriend(userId int64, friendId int64) bool {
contact := &model.Contact{
contact := &dbr.Contact{
UserId: friendId,
FriendId: userId,
}
contact, err := contact.GetByUserFriend(s.db)
if err == nil && contact.Status == model.ContactStatusAgree {
if err == nil && contact.Status == dbr.ContactStatusAgree {
return true
}
return false

@ -1,13 +1,17 @@
package model
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package dbr
import "gorm.io/gorm"
type AttachmentType int
const (
ATTACHMENT_TYPE_IMAGE AttachmentType = iota + 1
ATTACHMENT_TYPE_VIDEO
ATTACHMENT_TYPE_OTHER
AttachmentTypeImage AttachmentType = iota + 1
AttachmentTypeVideo
AttachmentTypeOther
)
type Attachment struct {

@ -1,4 +1,8 @@
package model
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package dbr
import "gorm.io/gorm"

@ -1,4 +1,8 @@
package model
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package dbr
import (
"time"

@ -1,4 +1,8 @@
package model
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package dbr
import (
"time"
@ -47,7 +51,7 @@ func (c *CommentContent) Create(db *gorm.DB) (*CommentContent, error) {
}
func (c *CommentContent) MediaContentsByCommentId(db *gorm.DB, commentIds []int64) (contents []string, err error) {
err = db.Model(c).Where("comment_id IN ? AND type = ?", commentIds, CONTENT_TYPE_IMAGE).Select("content").Find(&contents).Error
err = db.Model(c).Where("comment_id IN ? AND type = ?", commentIds, ContentTypeImage).Select("content").Find(&contents).Error
return
}

@ -1,4 +1,8 @@
package model
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package dbr
import (
"time"

@ -1,4 +1,8 @@
package model
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package dbr
import (
"github.com/sirupsen/logrus"

@ -1,4 +1,8 @@
package model
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package dbr
import "gorm.io/gorm"

@ -0,0 +1,40 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package dbr
import (
"time"
"gorm.io/gorm"
"gorm.io/plugin/soft_delete"
)
// Model 公共Model
type Model struct {
ID int64 `gorm:"primary_key" json:"id"`
CreatedOn int64 `json:"created_on"`
ModifiedOn int64 `json:"modified_on"`
DeletedOn int64 `json:"deleted_on"`
IsDel soft_delete.DeletedAt `gorm:"softDelete:flag" json:"is_del"`
}
type ConditionsT map[string]any
type Predicates map[string][]any
func (m *Model) BeforeCreate(tx *gorm.DB) (err error) {
nowTime := time.Now().Unix()
tx.Statement.SetColumn("created_on", nowTime)
tx.Statement.SetColumn("modified_on", nowTime)
return
}
func (m *Model) BeforeUpdate(tx *gorm.DB) (err error) {
if !tx.Statement.Changed("modified_on") {
tx.Statement.SetColumn("modified_on", time.Now().Unix())
}
return
}

@ -1,4 +1,8 @@
package model
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package dbr
import (
"strings"

@ -1,4 +1,8 @@
package model
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package dbr
import "gorm.io/gorm"

@ -1,4 +1,8 @@
package model
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package dbr
import (
"time"

@ -1,4 +1,8 @@
package model
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package dbr
import (
"time"
@ -7,27 +11,26 @@ import (
)
// 类型1标题2文字段落3图片地址4视频地址5语音地址6链接地址7附件资源
type PostContentT int
const (
CONTENT_TYPE_TITLE PostContentT = iota + 1
CONTENT_TYPE_TEXT
CONTENT_TYPE_IMAGE
CONTENT_TYPE_VIDEO
CONTENT_TYPE_AUDIO
CONTENT_TYPE_LINK
CONTENT_TYPE_ATTACHMENT
CONTENT_TYPE_CHARGE_ATTACHMENT
ContentTypeTitle PostContentT = iota + 1
ContentTypeText
ContentTypeImage
ContentTypeVideo
ContentTypeAudio
ContentTypeLink
ContentTypeAttachment
ContentTypeChargeAttachment
)
var (
mediaContentType = []PostContentT{
CONTENT_TYPE_IMAGE,
CONTENT_TYPE_VIDEO,
CONTENT_TYPE_AUDIO,
CONTENT_TYPE_ATTACHMENT,
CONTENT_TYPE_CHARGE_ATTACHMENT,
ContentTypeImage,
ContentTypeVideo,
ContentTypeAudio,
ContentTypeAttachment,
ContentTypeChargeAttachment,
}
)

@ -1,4 +1,8 @@
package model
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package dbr
import (
"time"

@ -1,4 +1,8 @@
package model
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package dbr
import (
"time"

@ -1,4 +1,8 @@
package model
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package dbr
import "gorm.io/gorm"

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

Loading…
Cancel
Save