mir: add friendship api implement for new web service

pull/196/head
Michael Li 2 years ago
parent 6b2f320cd8
commit 53383b9916
No known key found for this signature in database

@ -15,22 +15,25 @@ type Followship interface {
Chain() gin.HandlersChain Chain() gin.HandlersChain
ListFollowers(*web.ListFollowersReq) (*web.ListFollowersResp, mir.Error) ListFollowers(*web.ListFollowersReq) (*web.ListFollowersResp, mir.Error)
ListFollowings() mir.Error ListFollowings(*web.ListFollowingsReq) (*web.ListFollowingsResp, mir.Error)
DeleteFollowing() mir.Error DeleteFollowing(*web.DeleteFollowingReq) mir.Error
AddFollowing() mir.Error AddFollowing(*web.AddFollowingReq) mir.Error
mustEmbedUnimplementedFollowshipServant() mustEmbedUnimplementedFollowshipServant()
} }
type FollowshipBinding interface { type FollowshipBinding interface {
BindListFollowers(*gin.Context) (*web.ListFollowersReq, mir.Error) 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() mustEmbedUnimplementedFollowshipBinding()
} }
type FollowshipRender interface { type FollowshipRender interface {
RenderListFollowers(*gin.Context, *web.ListFollowersResp, mir.Error) RenderListFollowers(*gin.Context, *web.ListFollowersResp, mir.Error)
RenderListFollowings(*gin.Context, mir.Error) RenderListFollowings(*gin.Context, *web.ListFollowingsResp, mir.Error)
RenderDeleteFollowing(*gin.Context, mir.Error) RenderDeleteFollowing(*gin.Context, mir.Error)
RenderAddFollowing(*gin.Context, mir.Error) RenderAddFollowing(*gin.Context, mir.Error)
@ -68,7 +71,13 @@ func RegisterFollowshipServant(e *gin.Engine, s Followship, b FollowshipBinding,
default: default:
} }
r.RenderListFollowings(c, s.ListFollowings()) 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) { router.Handle("POST", "/following/delete", func(c *gin.Context) {
@ -78,7 +87,12 @@ func RegisterFollowshipServant(e *gin.Engine, s Followship, b FollowshipBinding,
default: default:
} }
r.RenderDeleteFollowing(c, s.DeleteFollowing()) 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) { router.Handle("POST", "/following/add", func(c *gin.Context) {
@ -88,7 +102,12 @@ func RegisterFollowshipServant(e *gin.Engine, s Followship, b FollowshipBinding,
default: default:
} }
r.RenderAddFollowing(c, s.AddFollowing()) req, err := b.BindAddFollowing(c)
if err != nil {
r.RenderAddFollowing(c, err)
return
}
r.RenderAddFollowing(c, s.AddFollowing(req))
}) })
} }
@ -105,15 +124,15 @@ func (UnimplementedFollowshipServant) ListFollowers(req *web.ListFollowersReq) (
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
} }
func (UnimplementedFollowshipServant) ListFollowings() mir.Error { func (UnimplementedFollowshipServant) ListFollowings(req *web.ListFollowingsReq) (*web.ListFollowingsResp, mir.Error) {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
} }
func (UnimplementedFollowshipServant) DeleteFollowing() mir.Error { func (UnimplementedFollowshipServant) DeleteFollowing(req *web.DeleteFollowingReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
} }
func (UnimplementedFollowshipServant) AddFollowing() mir.Error { func (UnimplementedFollowshipServant) AddFollowing(req *web.AddFollowingReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
} }
@ -128,8 +147,8 @@ func (r *UnimplementedFollowshipRender) RenderListFollowers(c *gin.Context, data
r.RenderAny(c, data, err) r.RenderAny(c, data, err)
} }
func (r *UnimplementedFollowshipRender) RenderListFollowings(c *gin.Context, err mir.Error) { func (r *UnimplementedFollowshipRender) RenderListFollowings(c *gin.Context, data *web.ListFollowingsResp, err mir.Error) {
r.RenderAny(c, nil, err) r.RenderAny(c, data, err)
} }
func (r *UnimplementedFollowshipRender) RenderDeleteFollowing(c *gin.Context, err mir.Error) { func (r *UnimplementedFollowshipRender) RenderDeleteFollowing(c *gin.Context, err mir.Error) {
@ -153,4 +172,22 @@ func (b *UnimplementedFollowshipBinding) BindListFollowers(c *gin.Context) (*web
return obj, err 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() {} func (b *UnimplementedFollowshipBinding) mustEmbedUnimplementedFollowshipBinding() {}

@ -15,16 +15,20 @@ type Friendship interface {
Chain() gin.HandlersChain Chain() gin.HandlersChain
GetContacts(*web.GetContactsReq) (*web.GetContactsResp, mir.Error) GetContacts(*web.GetContactsReq) (*web.GetContactsResp, mir.Error)
DeleteFriend() mir.Error DeleteFriend(*web.DeleteFriendReq) mir.Error
RejectFriend() mir.Error RejectFriend(*web.RejectFriendReq) mir.Error
AddFriend() mir.Error AddFriend(*web.AddFriendReq) mir.Error
RequestingFriend() mir.Error RequestingFriend(*web.RequestingFriendReq) mir.Error
mustEmbedUnimplementedFriendshipServant() mustEmbedUnimplementedFriendshipServant()
} }
type FriendshipBinding interface { type FriendshipBinding interface {
BindGetContacts(*gin.Context) (*web.GetContactsReq, mir.Error) 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() mustEmbedUnimplementedFriendshipBinding()
} }
@ -70,7 +74,12 @@ func RegisterFriendshipServant(e *gin.Engine, s Friendship, b FriendshipBinding,
default: default:
} }
r.RenderDeleteFriend(c, s.DeleteFriend()) 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) { router.Handle("POST", "/friend/reject", func(c *gin.Context) {
@ -80,7 +89,12 @@ func RegisterFriendshipServant(e *gin.Engine, s Friendship, b FriendshipBinding,
default: default:
} }
r.RenderRejectFriend(c, s.RejectFriend()) 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) { router.Handle("POST", "/friend/add", func(c *gin.Context) {
@ -90,7 +104,12 @@ func RegisterFriendshipServant(e *gin.Engine, s Friendship, b FriendshipBinding,
default: default:
} }
r.RenderAddFriend(c, s.AddFriend()) 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) { router.Handle("POST", "/friend/requesting", func(c *gin.Context) {
@ -100,7 +119,12 @@ func RegisterFriendshipServant(e *gin.Engine, s Friendship, b FriendshipBinding,
default: default:
} }
r.RenderRequestingFriend(c, s.RequestingFriend()) req, err := b.BindRequestingFriend(c)
if err != nil {
r.RenderRequestingFriend(c, err)
return
}
r.RenderRequestingFriend(c, s.RequestingFriend(req))
}) })
} }
@ -117,19 +141,19 @@ func (UnimplementedFriendshipServant) GetContacts(req *web.GetContactsReq) (*web
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
} }
func (UnimplementedFriendshipServant) DeleteFriend() mir.Error { func (UnimplementedFriendshipServant) DeleteFriend(req *web.DeleteFriendReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
} }
func (UnimplementedFriendshipServant) RejectFriend() mir.Error { func (UnimplementedFriendshipServant) RejectFriend(req *web.RejectFriendReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
} }
func (UnimplementedFriendshipServant) AddFriend() mir.Error { func (UnimplementedFriendshipServant) AddFriend(req *web.AddFriendReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
} }
func (UnimplementedFriendshipServant) RequestingFriend() mir.Error { func (UnimplementedFriendshipServant) RequestingFriend(req *web.RequestingFriendReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
} }
@ -173,4 +197,28 @@ func (b *UnimplementedFriendshipBinding) BindGetContacts(c *gin.Context) (*web.G
return obj, err 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() {} func (b *UnimplementedFriendshipBinding) mustEmbedUnimplementedFriendshipBinding() {}

@ -4,10 +4,24 @@
package web package web
type ListFollowersReq struct { import "github.com/rocboss/paopao-ce/internal/servants/base"
*BaseInfo `json:"-"`
type AddFollowingReq struct {
BaseInfo `json:"-" binding:"-"`
} }
type ListFollowersResp struct { type DeleteFollowingReq struct {
// TODO BaseInfo `json:"-" binding:"-"`
} }
type ListFollowingsReq struct {
BaseInfo `json:"-" binding:"-"`
}
type ListFollowingsResp base.PageResp
type ListFollowersReq struct {
BaseInfo `form:"-" binding:"-"`
}
type ListFollowersResp base.PageResp

@ -4,10 +4,37 @@
package web package web
import "github.com/rocboss/paopao-ce/internal/servants/base"
type RequestingFriendReq struct {
BaseInfo `json:"-" binding:"-"`
UserId int64 `json:"user_id" binding:"required"`
Greetings string `json:"greetings" binding:"required"`
}
type AddFriendReq struct {
BaseInfo `json:"-" binding:"-"`
UserId int64 `json:"user_id" binding:"required"`
}
type RejectFriendReq struct {
BaseInfo `json:"-" binding:"-"`
UserId int64 `json:"user_id" binding:"required"`
}
type DeleteFriendReq struct {
BaseInfo `json:"-" binding:"-"`
UserId int64 `json:"user_id"`
}
type GetContactsReq struct { type GetContactsReq struct {
*BaseInfo `json:"-"` BaseInfo `form:"-" binding:"-"`
Page int `form:"-" binding:"-"`
PageSize int `form:"-" binding:"-"`
} }
type GetContactsResp struct { type GetContactsResp base.PageResp
// TODO
func (r *GetContactsReq) SetPageInfo(page int, pageSize int) {
r.Page, r.PageSize = page, pageSize
} }

@ -129,7 +129,7 @@ type UploadAttachmentResp struct {
} }
type DownloadAttachmentPrecheckReq struct { type DownloadAttachmentPrecheckReq struct {
BaseInfo `json:"-" binding:"-"` BaseInfo `form:"-" binding:"-"`
ContentID int64 `form:"id"` ContentID int64 `form:"id"`
} }
@ -138,7 +138,7 @@ type DownloadAttachmentPrecheckResp struct {
} }
type DownloadAttachmentReq struct { type DownloadAttachmentReq struct {
BaseInfo `json:"-" binding:"-"` BaseInfo `form:"-" binding:"-"`
ContentID int64 `form:"id"` ContentID int64 `form:"id"`
} }

@ -18,17 +18,15 @@ var (
) )
type followshipSrv struct { type followshipSrv struct {
base.BaseServant
api.UnimplementedFollowshipServant api.UnimplementedFollowshipServant
*base.DaoServant
} }
type followshipBinding struct { type followshipBinding struct {
base.BaseBinding
*api.UnimplementedFollowshipBinding *api.UnimplementedFollowshipBinding
} }
type followshipRender struct { type followshipRender struct {
base.BaseRender
*api.UnimplementedFollowshipRender *api.UnimplementedFollowshipRender
} }
@ -36,7 +34,7 @@ func (s *followshipSrv) Chain() gin.HandlersChain {
return gin.HandlersChain{chain.JWT()} return gin.HandlersChain{chain.JWT()}
} }
func newFollowshipSrv() api.Followship { func newFollowshipSrv(s *base.DaoServant) api.Followship {
return &followshipSrv{} return &followshipSrv{}
} }

@ -5,10 +5,14 @@
package web package web
import ( import (
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
api "github.com/rocboss/paopao-ce/auto/api/v1" api "github.com/rocboss/paopao-ce/auto/api/v1"
"github.com/rocboss/paopao-ce/internal/model/web"
"github.com/rocboss/paopao-ce/internal/servants/base" "github.com/rocboss/paopao-ce/internal/servants/base"
"github.com/rocboss/paopao-ce/internal/servants/chain" "github.com/rocboss/paopao-ce/internal/servants/chain"
"github.com/rocboss/paopao-ce/pkg/xerror"
"github.com/sirupsen/logrus"
) )
var ( var (
@ -18,17 +22,15 @@ var (
) )
type friendshipSrv struct { type friendshipSrv struct {
base.BaseServant
api.UnimplementedFriendshipServant api.UnimplementedFriendshipServant
*base.DaoServant
} }
type friendshipBinding struct { type friendshipBinding struct {
base.BaseBinding
*api.UnimplementedFriendshipBinding *api.UnimplementedFriendshipBinding
} }
type friendshipRender struct { type friendshipRender struct {
base.BaseRender
*api.UnimplementedFriendshipRender *api.UnimplementedFriendshipRender
} }
@ -36,8 +38,91 @@ func (s *friendshipSrv) Chain() gin.HandlersChain {
return gin.HandlersChain{chain.JWT()} return gin.HandlersChain{chain.JWT()}
} }
func newFriendshipSrv() api.Friendship { func (s *friendshipSrv) GetContacts(req *web.GetContactsReq) (*web.GetContactsResp, mir.Error) {
return &friendshipSrv{} if req.User == nil {
return nil, xerror.ServerError
}
res, err := s.Ds.GetContacts(req.User.ID, (req.Page-1)*req.PageSize, req.PageSize)
if err != nil {
logrus.Errorf("service.GetContacts err: %s", err)
return nil, _errGetContactsFailed
}
resp := base.PageRespFrom(res.Contacts, req.Page, req.PageSize, res.Total)
return (*web.GetContactsResp)(resp), nil
}
func (s *friendshipSrv) DeleteFriend(req *web.DeleteFriendReq) mir.Error {
if req.User == nil {
return xerror.ServerError
}
if req.User != nil && req.User.ID == req.UserId {
return _errNoActionToSelf
}
if _, err := s.Ds.GetUserByID(req.UserId); err != nil {
return _errNotExistFriendId
}
if err := s.Ds.DeleteFriend(req.User.ID, req.UserId); err != nil {
logrus.Errorf("Ds.DeleteFriend err: %s", err)
return _errDeleteFriendFailed
}
return nil
}
func (s *friendshipSrv) RejectFriend(req *web.RejectFriendReq) mir.Error {
if req.User == nil {
return xerror.ServerError
}
if req.User.ID == req.UserId {
return _errNoActionToSelf
}
if _, err := s.Ds.GetUserByID(req.UserId); err != nil {
return _errNotExistFriendId
}
if err := s.Ds.RejectFriend(req.User.ID, req.UserId); err != nil {
logrus.Errorf("Ds.RejectFriend err: %s", err)
return _errRejectFriendFailed
}
return nil
}
func (s *friendshipSrv) AddFriend(req *web.AddFriendReq) mir.Error {
if req.User == nil {
return xerror.ServerError
}
if req.User.ID == req.UserId {
return _errNoActionToSelf
}
if _, err := s.Ds.GetUserByID(req.UserId); err != nil {
return _errNotExistFriendId
}
if err := s.Ds.AddFriend(req.User.ID, req.UserId); err != nil {
logrus.Errorf("Ds.AddFriend err: %s", err)
return _errAddFriendFailed
}
return nil
}
func (s *friendshipSrv) RequestingFriend(req *web.RequestingFriendReq) mir.Error {
if req.User == nil {
return xerror.ServerError
}
if req.User.ID == req.UserId {
return _errNoRequestingFriendToSelf
}
if _, err := s.Ds.GetUserByID(req.UserId); err != nil {
return _errNotExistFriendId
}
if err := s.Ds.RequestingFriend(req.User.ID, req.UserId, req.Greetings); err != nil {
logrus.Errorf("Ds.RequestingFriend err: %s", err)
return _errSendRequestingFriendFailed
}
return nil
}
func newFriendshipSrv(s *base.DaoServant) api.Friendship {
return &friendshipSrv{
DaoServant: s,
}
} }
func newFriendshipBinding() api.FriendshipBinding { func newFriendshipBinding() api.FriendshipBinding {

@ -37,10 +37,10 @@ func RouteWeb(e *gin.Engine) {
api.RegisterAlipayPrivServant(e, newAlipayPrivSrv(ds, client), newAlipayPrivBinding(), newAlipayPrivRender()) api.RegisterAlipayPrivServant(e, newAlipayPrivSrv(ds, client), newAlipayPrivBinding(), newAlipayPrivRender())
}, },
"Followship": func() { "Followship": func() {
api.RegisterFollowshipServant(e, newFollowshipSrv(), newFollowshipBinding(), newFollowshipRender()) api.RegisterFollowshipServant(e, newFollowshipSrv(ds), newFollowshipBinding(), newFollowshipRender())
}, },
"Friendship": func() { "Friendship": func() {
api.RegisterFriendshipServant(e, newFriendshipSrv(), newFriendshipBinding(), newFriendshipRender()) api.RegisterFriendshipServant(e, newFriendshipSrv(ds), newFriendshipBinding(), newFriendshipRender())
}, },
}) })
} }

@ -16,13 +16,13 @@ type Followship struct {
Group Group `mir:"v1"` Group Group `mir:"v1"`
// AddFollowing 添加关注 // AddFollowing 添加关注
AddFollowing func(Post) `mir:"/following/add"` AddFollowing func(Post, web.AddFollowingReq) `mir:"/following/add"`
// DeleteFollowing 取消关注 // DeleteFollowing 取消关注
DeleteFollowing func(Post) `mir:"/following/delete"` DeleteFollowing func(Post, web.DeleteFollowingReq) `mir:"/following/delete"`
// ListFollowings 获取用户的关注列表 // ListFollowings 获取用户的关注列表
ListFollowings func(Get) `mir:"/following/list"` ListFollowings func(Get, web.ListFollowingsReq) web.ListFollowingsResp `mir:"/following/list"`
// ListFollowers 获取用户的追随者列表 // ListFollowers 获取用户的追随者列表
ListFollowers func(Get, web.ListFollowersReq) web.ListFollowersResp `mir:"/follower/list"` ListFollowers func(Get, web.ListFollowersReq) web.ListFollowersResp `mir:"/follower/list"`

@ -16,16 +16,16 @@ type Friendship struct {
Group Group `mir:"v1"` Group Group `mir:"v1"`
// RequestingFriend 请求添加朋友 // RequestingFriend 请求添加朋友
RequestingFriend func(Post) `mir:"/friend/requesting"` RequestingFriend func(Post, web.RequestingFriendReq) `mir:"/friend/requesting"`
// AddFriend 同意添加好友 // AddFriend 同意添加好友
AddFriend func(Post) `mir:"/friend/add"` AddFriend func(Post, web.AddFriendReq) `mir:"/friend/add"`
// RejectFriend 拒绝添加好友 // RejectFriend 拒绝添加好友
RejectFriend func(Post) `mir:"/friend/reject"` RejectFriend func(Post, web.RejectFriendReq) `mir:"/friend/reject"`
// DeleteFriend 删除好友 // DeleteFriend 删除好友
DeleteFriend func(Post) `mir:"/friend/delete"` DeleteFriend func(Post, web.DeleteFriendReq) `mir:"/friend/delete"`
// GetContacts 获取好友列表 // GetContacts 获取好友列表
GetContacts func(Get, web.GetContactsReq) web.GetContactsResp `mir:"/user/contacts"` GetContacts func(Get, web.GetContactsReq) web.GetContactsResp `mir:"/user/contacts"`

Loading…
Cancel
Save