feature/post_v2 #2

Merged
daniel.w merged 5 commits from feature/post_v2 into main 2024-08-30 07:08:46 +00:00
17 changed files with 652 additions and 75 deletions
Showing only changes of commit 68b3ab95b9 - Show all commits

View File

@ -9,90 +9,101 @@ message OKResp {}
message NoneReq {} message NoneReq {}
// //
message Pager { message Pager
int64 total = 1; // {
int64 size = 2; // int64 total = 1; //
int64 index = 3; // int64 size = 2; //
int64 index = 3; //
} }
// ========== =========== // ========== ===========
// ------ NewPost -------- // ------ NewPost --------
message NewPostReq { message NewPostReq
string uid = 1; // ID {
string content = 2; // string uid = 1; // ID
repeated string tags = 3; // string content = 2; //
repeated Media media = 4; // Media URL repeated string tags = 3; //
bool is_ad = 5; // repeated Media media = 4; // Media URL
bool is_ad = 5; //
} }
message Media { message Media
{
string type = 1; string type = 1;
string url = 2; string url = 2;
} }
// //
message PostResp { message PostResp
string post_id = 1; // ID {
string post_id = 1; // ID
} }
// ------ DeletePost ------ // ------ DeletePost ------
// //
message DeletePostsReq { message DeletePostsReq
repeated string post_id = 1; // ID {
repeated string post_id = 1; // ID
} }
// ------ UpdatePost ------ // ------ UpdatePost ------
// //
message UpdatePostReq { message UpdatePostReq
string post_id = 1; // ID {
repeated string tags = 2; // string post_id = 1; // ID
repeated Media media = 3; // Media URL repeated string tags = 2; //
optional string content = 4; // repeated Media media = 3; // Media URL
optional int64 like_count = 5; // optional string content = 4; //
optional int64 dislike_count = 6; // optional int64 like_count = 5; //
optional int64 dislike_count = 6; //
} }
// ------ListPosts ------ // ------ListPosts ------
// //
message QueryPostsReq { message QueryPostsReq
repeated string uid = 1; // ID篩選貼文 {
repeated string post_id = 2; // ID篩選貼文 repeated string uid = 1; // ID篩選貼文
optional int32 only_ads = 3; // 0 1 2 repeated string post_id = 2; // ID篩選貼文
int32 page_index = 4; // optional int32 only_ads = 3; // 0 1 2
int32 page_size = 5; // int32 page_index = 4; //
int32 page_size = 5; //
} }
// //
message PostDetailItem { message PostDetailItem
string post_id = 1; // ID {
string uid = 2; // ID string post_id = 1; // ID
string content = 3; // string uid = 2; // ID
repeated string tags = 4; // string content = 3; //
repeated Media media = 5; // URL repeated string tags = 4; //
bool is_ad = 6; // repeated Media media = 5; // URL
int64 created_at = 7; // bool is_ad = 6; //
int64 update_at = 8; // int64 created_at = 7; //
int64 like_count = 9; // int64 update_at = 8; //
int64 dislike_count = 10; // int64 like_count = 9; //
int64 dislike_count = 10; //
} }
// //
message ListPostsResp { message ListPostsResp
repeated PostDetailItem posts = 1; // {
repeated PostDetailItem posts = 1; //
Pager page = 2; Pager page = 2;
} }
message ModifyLikeDislikeCountReq { message ModifyLikeDislikeCountReq
string post_id = 1; // ID {
int64 reaction_type = 2; // string post_id = 1; // ID
bool is_increment = 3; // true false int64 reaction_type = 2; //
int64 count = 4; // bool is_increment = 3; // true false
int64 count = 4; //
} }
// ========== () ========== // ========== () ==========
service PostService { service PostService
{
// CreatePost // CreatePost
rpc CreatePost(NewPostReq) returns (PostResp); rpc CreatePost(NewPostReq) returns (PostResp);
// DeletePost // DeletePost
@ -102,3 +113,72 @@ service PostService {
// ListPosts // ListPosts
rpc ListPosts(QueryPostsReq) returns (ListPostsResp); rpc ListPosts(QueryPostsReq) returns (ListPostsResp);
} }
// =================================================================================================
// ------------ ------------
message CommentPostReq
{
string post_id = 1; // ID
string uid = 2; // ID
string content = 3; //
}
message CommentPostResp
{
string comment_id = 1; // ID
}
// ------------ ------------
message GetCommentsReq
{
string post_id = 1; // ID
int32 page_index = 2; //
int32 page_size = 3; //
}
//
message CommentDetail
{
string comment_id = 1; // ID
string uid = 2; // ID
string content = 3; //
int64 created_at = 4; //
int64 like_count = 5; //
int64 dislike_count = 6; //
}
//
message GetCommentsResp
{
repeated CommentDetail comments = 1; //
Pager page = 2;
}
// ------------ ------------
message DeleteCommentReq
{
repeated string comment_id = 1; // ID
}
//
message UpdateCommentReq
{
string comment_id = 1; // ID
string content = 2; //
optional int64 like_count = 3; //
optional int64 dislike_count = 4; //
}
//
service CommentService
{
// NewComment
rpc NewComment(CommentPostReq) returns (CommentPostResp);
// GetComments
rpc GetComments(GetCommentsReq) returns (GetCommentsResp);
// DeleteComment
rpc DeleteComment(DeleteCommentReq) returns (OKResp);
// UpdateComment
rpc UpdateComment(UpdateCommentReq) returns (OKResp);
}

View File

@ -1,5 +1,13 @@
package domain package domain
import (
ers "code.30cm.net/digimon/library-go/errs"
"code.30cm.net/digimon/library-go/errs/code"
"fmt"
"github.com/zeromicro/go-zero/core/logx"
"strings"
)
type ErrorCode uint32 type ErrorCode uint32
func (e ErrorCode) ToUint32() uint32 { func (e ErrorCode) ToUint32() uint32 {
@ -15,3 +23,25 @@ const (
UpdatePostError UpdatePostError
ListPostError ListPostError
) )
const (
CommentFoundErrorCode ErrorCode = iota + 10
CommentInsertErrorCode
CommentDeleteErrorCode
CommentUpdateErrorCode
CommentListErrorCode
)
func CommentError(ec ErrorCode, s ...string) *ers.LibError {
return ers.NewError(code.CloudEPTweeting, code.DBError,
ec.ToUint32(),
fmt.Sprintf("%s", strings.Join(s, " ")))
}
func CommentErrorL(ec ErrorCode,
l logx.Logger, filed []logx.LogField, s ...string) *ers.LibError {
e := CommentError(ec, s...)
l.WithCallerSkip(1).WithFields(filed...).Error(e.Error())
return e
}

View File

@ -0,0 +1,44 @@
package commentservicelogic
import (
"app-cloudep-tweeting-service/internal/domain"
"context"
"app-cloudep-tweeting-service/gen_result/pb/tweeting"
"app-cloudep-tweeting-service/internal/svc"
"github.com/zeromicro/go-zero/core/logx"
)
type DeleteCommentLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewDeleteCommentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteCommentLogic {
return &DeleteCommentLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
// DeleteComment 刪除評論
func (l *DeleteCommentLogic) DeleteComment(in *tweeting.DeleteCommentReq) (*tweeting.OKResp, error) {
_, err := l.svcCtx.CommentModel.DeleteMany(l.ctx, in.GetCommentId()...)
if err != nil {
e := domain.CommentErrorL(
domain.CommentDeleteErrorCode,
logx.WithContext(l.ctx),
[]logx.LogField{
{Key: "req", Value: in},
{Key: "func", Value: "CommentModel.DeleteMany"},
{Key: "err", Value: err},
},
"failed to del comment").Wrap(err)
return nil, e
}
return &tweeting.OKResp{}, nil
}

View File

@ -0,0 +1,102 @@
package commentservicelogic
import (
"app-cloudep-tweeting-service/internal/domain"
model "app-cloudep-tweeting-service/internal/model/mongo"
ers "code.30cm.net/digimon/library-go/errs"
"context"
"app-cloudep-tweeting-service/gen_result/pb/tweeting"
"app-cloudep-tweeting-service/internal/svc"
"github.com/zeromicro/go-zero/core/logx"
)
type GetCommentsLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewGetCommentsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetCommentsLogic {
return &GetCommentsLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
// 只列出要驗證的資料
type listReq struct {
PostID string `json:"post_id" validate:"required"`
PageSize int64 `json:"page_size" validate:"required"`
PageIndex int64 `json:"page_index" validate:"required"`
}
// 將單個 Post 轉換為 PostDetailItem
func convertToCommentDetailItem(item *model.Comment) *tweeting.CommentDetail {
return &tweeting.CommentDetail{
CommentId: item.ID.Hex(),
Uid: item.UID,
Content: item.Content,
CreatedAt: item.CreateAt,
LikeCount: int64(item.LikeCount),
DislikeCount: int64(item.DisLikeCount),
}
}
// GetComments 查詢評論
// 目前應該是沒有需求是要看 uid 在哪裡留過言,如果未來業務邏輯有再新增
func (l *GetCommentsLogic) GetComments(in *tweeting.GetCommentsReq) (*tweeting.GetCommentsResp, error) {
// 將 PageSize 和 PageIndex 提前轉換為 int64
pageSize := int64(in.GetPageSize())
pageIndex := int64(in.GetPageIndex())
// 驗證資料
if err := l.svcCtx.Validate.ValidateAll(&listReq{
PageSize: pageSize,
PageIndex: pageIndex,
PostID: in.GetPostId(),
}); err != nil {
// 錯誤代碼 05-011-00
return nil, ers.InvalidFormat(err.Error())
}
// 構建查詢條件
query := &model.QueryCommentModelReq{
PostID: in.GetPostId(),
PageSize: pageSize,
PageIndex: pageIndex,
}
// 執行查詢
find, count, err := l.svcCtx.CommentModel.Find(l.ctx, query)
if err != nil {
e := domain.CommentErrorL(
domain.CommentListErrorCode,
logx.WithContext(l.ctx),
[]logx.LogField{
{Key: "query", Value: query},
{Key: "func", Value: "CommentModel.Find"},
{Key: "err", Value: err},
},
"failed to find comment").Wrap(err)
return nil, e
}
// 將查詢結果轉換為 API 回應格式
result := make([]*tweeting.CommentDetail, 0, count)
for _, item := range find {
result = append(result, convertToCommentDetailItem(item))
}
// 返回結果
return &tweeting.GetCommentsResp{
Comments: result,
Page: &tweeting.Pager{
Total: count,
Index: pageIndex,
Size: pageSize,
},
}, nil
}

View File

@ -0,0 +1,95 @@
package commentservicelogic
import (
"app-cloudep-tweeting-service/gen_result/pb/tweeting"
"app-cloudep-tweeting-service/internal/domain"
model "app-cloudep-tweeting-service/internal/model/mongo"
"app-cloudep-tweeting-service/internal/svc"
ers "code.30cm.net/digimon/library-go/errs"
"context"
"errors"
"github.com/zeromicro/go-zero/core/logx"
)
type NewCommentLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewNewCommentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *NewCommentLogic {
return &NewCommentLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
// 輸入的定義 -> 檢查用
type newCommentReq struct {
UID string `json:"uid" validate:"required"`
Content string `json:"content" validate:"required,lte=500"` // 貼文限制 500 字內
PostID string `json:"post_id" validate:"required"`
}
// NewComment 發表評論
func (l *NewCommentLogic) NewComment(in *tweeting.CommentPostReq) (*tweeting.CommentPostResp, error) {
// 驗證資料
if err := l.svcCtx.Validate.ValidateAll(&newCommentReq{
UID: in.GetUid(),
Content: in.GetContent(),
PostID: in.GetPostId(),
}); err != nil {
// 錯誤代碼 05-011-00
return nil, ers.InvalidFormat(err.Error())
}
// 檢查是否有這個文章
_, err := l.svcCtx.PostModel.FindOne(l.ctx, in.GetPostId())
if err != nil {
if errors.Is(model.ErrNotFound, err) {
// 錯誤代碼 05-031-00
return nil, ers.ResourceNotFound("failed to find post: ", in.GetPostId())
}
// 錯誤代碼 05-021-10
e := domain.CommentErrorL(
domain.CommentFoundErrorCode,
logx.WithContext(l.ctx),
[]logx.LogField{
{Key: "req", Value: in},
{Key: "func", Value: "PostModel.FindOne"},
{Key: "err", Value: err},
},
"failed to find post:", in.GetPostId()).Wrap(err)
return nil, e
}
data := &model.Comment{
PostID: in.GetPostId(),
UID: in.GetUid(),
Content: in.GetContent(),
LikeCount: 0,
DisLikeCount: 0,
}
err = l.svcCtx.CommentModel.Insert(l.ctx, data)
if err != nil {
// 錯誤代碼 05-021-11
e := domain.CommentErrorL(
domain.CommentInsertErrorCode,
logx.WithContext(l.ctx),
[]logx.LogField{
{Key: "req", Value: in},
{Key: "func", Value: "CommentModel.Insert"},
{Key: "err", Value: err},
},
"failed to insert comment:", in.GetPostId()).Wrap(err)
return nil, e
}
return &tweeting.CommentPostResp{
CommentId: data.ID.Hex(),
}, nil
}

View File

@ -0,0 +1 @@
package commentservicelogic

View File

@ -0,0 +1,81 @@
package commentservicelogic
import (
"app-cloudep-tweeting-service/gen_result/pb/tweeting"
"app-cloudep-tweeting-service/internal/domain"
model "app-cloudep-tweeting-service/internal/model/mongo"
"app-cloudep-tweeting-service/internal/svc"
ers "code.30cm.net/digimon/library-go/errs"
"context"
"go.mongodb.org/mongo-driver/bson/primitive"
"github.com/zeromicro/go-zero/core/logx"
)
type UpdateCommentLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewUpdateCommentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateCommentLogic {
return &UpdateCommentLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
type checkCommentId struct {
CommentId string `validate:"required"`
Content string `json:"content,omitempty" validate:"lte=500"`
}
// UpdateComment 更新評論
func (l *UpdateCommentLogic) UpdateComment(in *tweeting.UpdateCommentReq) (*tweeting.OKResp, error) {
// 驗證資料
if err := l.svcCtx.Validate.ValidateAll(&checkCommentId{
CommentId: in.GetCommentId(),
Content: in.GetContent(),
}); err != nil {
// 錯誤代碼 05-011-00
return nil, ers.InvalidFormat(err.Error())
}
// 沒有就沒有,有就走全覆蓋
update := model.Comment{}
oid, err := primitive.ObjectIDFromHex(in.GetCommentId())
if err != nil {
// 錯誤代碼 05-011-00
return nil, ers.InvalidFormat("failed to get correct comment id")
}
update.ID = oid
update.Content = in.GetContent()
// 因為 0 也有意義,所以如果是真的沒帶進來,用 -1 帶進去表示不作動
if in.LikeCount == nil {
update.LikeCount = -1
} else {
update.LikeCount = in.GetLikeCount()
}
if in.DislikeCount == nil {
update.DisLikeCount = -1
} else {
update.DisLikeCount = in.GetDislikeCount()
}
_, err = l.svcCtx.CommentModel.UpdateOptional(l.ctx, &update)
if err != nil {
// 錯誤代碼 05-021-13
e := domain.CommentErrorL(
domain.CommentUpdateErrorCode,
logx.WithContext(l.ctx),
[]logx.LogField{
{Key: "req", Value: in},
{Key: "func", Value: "CommentModel.UpdateOptional"},
{Key: "err", Value: err},
},
"failed to update comment:", in.CommentId).Wrap(err)
return nil, e
}
return &tweeting.OKResp{}, nil
}

View File

@ -80,8 +80,19 @@ func (l *UpdatePostLogic) UpdatePost(in *tweeting.UpdatePostReq) (*tweeting.OKRe
} }
update.MediaURL = media update.MediaURL = media
update.Content = in.GetContent() update.Content = in.GetContent()
update.Like = uint64(in.GetLikeCount())
update.DisLike = uint64(in.GetDislikeCount()) // 因為 0 也有意義,所以如果是真的沒帶進來,用 -1 帶進去表示不作動
if in.LikeCount == nil {
update.Like = -1
} else {
update.Like = in.GetLikeCount()
}
if in.DislikeCount == nil {
update.DisLike = -1
} else {
update.DisLike = in.GetDislikeCount()
}
_, err = l.svcCtx.PostModel.UpdateOptional(l.ctx, &update) _, err = l.svcCtx.PostModel.UpdateOptional(l.ctx, &update)
if err != nil { if err != nil {

View File

@ -1,6 +1,14 @@
package model package model
import "github.com/zeromicro/go-zero/core/stores/mon" import (
"context"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/mon"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"time"
)
var _ CommentModel = (*customCommentModel)(nil) var _ CommentModel = (*customCommentModel)(nil)
@ -9,13 +17,27 @@ type (
// and implement the added methods in customCommentModel. // and implement the added methods in customCommentModel.
CommentModel interface { CommentModel interface {
commentModel commentModel
DeleteMany(ctx context.Context, id ...string) (int64, error)
UpdateOptional(ctx context.Context, data *Comment) (*mongo.UpdateResult, error)
Find(ctx context.Context, param *QueryCommentModelReq) ([]*Comment, int64, error)
} }
customCommentModel struct { customCommentModel struct {
*defaultCommentModel *defaultCommentModel
} }
QueryCommentModelReq struct {
PostID string
PageSize int64
PageIndex int64
}
) )
func (xw customCommentModel) Find(ctx context.Context, param *QueryCommentModelReq) ([]*Comment, int64, error) {
// TODO implement me
panic("implement me")
}
// NewCommentModel returns a model for the mongo. // NewCommentModel returns a model for the mongo.
func NewCommentModel(url, db, collection string) CommentModel { func NewCommentModel(url, db, collection string) CommentModel {
conn := mon.MustNewModel(url, db, collection) conn := mon.MustNewModel(url, db, collection)
@ -23,3 +45,56 @@ func NewCommentModel(url, db, collection string) CommentModel {
defaultCommentModel: newDefaultCommentModel(conn), defaultCommentModel: newDefaultCommentModel(conn),
} }
} }
func (m *defaultCommentModel) DeleteMany(ctx context.Context, id ...string) (int64, error) {
objectIDs := make([]primitive.ObjectID, 0, len(id))
// prepare
for _, item := range id {
oid, err := primitive.ObjectIDFromHex(item)
if err != nil {
logx.WithCallerSkip(1).WithFields(
logx.Field("func", "defaultPostModel.DeleteMany"),
logx.Field("id", item),
).Error(err.Error())
continue
}
objectIDs = append(objectIDs, oid)
}
// 檢查是否有有效的 ObjectIDs
if len(objectIDs) == 0 {
return 0, ErrNotFound
}
// 刪除文檔
res, err := m.conn.DeleteMany(ctx, bson.M{"_id": bson.M{"$in": objectIDs}})
if err != nil {
return 0, err
}
return res, err
}
func (m *defaultCommentModel) UpdateOptional(ctx context.Context, data *Comment) (*mongo.UpdateResult, error) {
update := bson.M{"$set": bson.M{}}
if data.Content != "" {
update["$set"].(bson.M)["content"] = data.Content
}
if data.LikeCount != -1 {
update["$set"].(bson.M)["like_count"] = data.LikeCount
}
if data.DisLikeCount != -1 {
update["$set"].(bson.M)["dis_like_count"] = data.DisLikeCount
}
// UpdateAt 是每次都需要更新的,不用檢查
update["$set"].(bson.M)["updateAt"] = time.Now().UTC().UnixNano()
res, err := m.conn.UpdateOne(ctx, bson.M{"_id": data.ID}, update)
return res, err
}

View File

@ -29,8 +29,8 @@ func newDefaultCommentModel(conn *mon.Model) *defaultCommentModel {
func (m *defaultCommentModel) Insert(ctx context.Context, data *Comment) error { func (m *defaultCommentModel) Insert(ctx context.Context, data *Comment) error {
if data.ID.IsZero() { if data.ID.IsZero() {
data.ID = primitive.NewObjectID() data.ID = primitive.NewObjectID()
data.CreateAt = time.Now() data.CreateAt = time.Now().UTC().UnixNano()
data.UpdateAt = time.Now() data.UpdateAt = time.Now().UTC().UnixNano()
} }
_, err := m.conn.InsertOne(ctx, data) _, err := m.conn.InsertOne(ctx, data)
@ -57,7 +57,7 @@ func (m *defaultCommentModel) FindOne(ctx context.Context, id string) (*Comment,
} }
func (m *defaultCommentModel) Update(ctx context.Context, data *Comment) (*mongo.UpdateResult, error) { func (m *defaultCommentModel) Update(ctx context.Context, data *Comment) (*mongo.UpdateResult, error) {
data.UpdateAt = time.Now() data.UpdateAt = time.Now().UTC().UnixNano()
res, err := m.conn.UpdateOne(ctx, bson.M{"_id": data.ID}, bson.M{"$set": data}) res, err := m.conn.UpdateOne(ctx, bson.M{"_id": data.ID}, bson.M{"$set": data})
return res, err return res, err

View File

@ -1,14 +1,23 @@
package model package model
import ( import (
"time"
"go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson/primitive"
) )
type Comment struct { type Comment struct {
ID primitive.ObjectID `bson:"_id,omitempty" json:"id,omitempty"` ID primitive.ObjectID `bson:"_id,omitempty" json:"id,omitempty"`
// TODO: Fill your own fields PostID string `bson:"post_id" json:"post_id"`
UpdateAt time.Time `bson:"updateAt,omitempty" json:"updateAt,omitempty"` UID string `bson:"uid" json:"uid"` // 留下留言的人
CreateAt time.Time `bson:"createAt,omitempty" json:"createAt,omitempty"` Content string `bson:"content" json:"content"` // 留言內容
LikeCount int64 `bson:"like_count" json:"like_count"` // 喜歡這則留言的人
DisLikeCount int64 `bson:"dis_like_count" json:"dis_like_count"` // 不喜歡這則留言的人
UpdateAt int64 `bson:"updateAt,omitempty" json:"updateAt,omitempty"`
CreateAt int64 `bson:"createAt,omitempty" json:"createAt,omitempty"`
} }
func (c Comment) CollectionName() string {
return "comment"
}
// 照邏輯,應該需要建立的索引有
// 複合索引:(PostID + CreateAt)

View File

@ -106,11 +106,11 @@ func (m *defaultPostModel) UpdateOptional(ctx context.Context, data *Post) (*mon
update["$set"].(bson.M)["media_url"] = data.MediaURL update["$set"].(bson.M)["media_url"] = data.MediaURL
} }
if data.Like != 0 { if data.Like != -1 {
update["$set"].(bson.M)["like"] = data.Like update["$set"].(bson.M)["like"] = data.Like
} }
if data.DisLike != 0 { if data.DisLike != -1 {
update["$set"].(bson.M)["dislike"] = data.DisLike update["$set"].(bson.M)["dislike"] = data.DisLike
} }

View File

@ -12,8 +12,8 @@ type Post struct {
IsAd bool `bson:"is_ad" json:"is_ad"` // 此則貼文是否為廣告貼文 -> 過濾條件 IsAd bool `bson:"is_ad" json:"is_ad"` // 此則貼文是否為廣告貼文 -> 過濾條件
Tags []string `bson:"tags" json:"tags"` // 本則貼文的標籤,不提供搜尋,僅提供顯示(存名字ID 建立之後就不提供修改與刪除) Tags []string `bson:"tags" json:"tags"` // 本則貼文的標籤,不提供搜尋,僅提供顯示(存名字ID 建立之後就不提供修改與刪除)
MediaURL []Media `bson:"media_url" json:"media_url"` // 網址 MediaURL []Media `bson:"media_url" json:"media_url"` // 網址
Like uint64 `bson:"like" json:"like"` // 讚數量 Like int64 `bson:"like" json:"like"` // 讚數量
DisLike uint64 `bson:"dislike" json:"dislike"` // 不讚數量 DisLike int64 `bson:"dislike" json:"dislike"` // 不讚數量
UpdateAt int64 `bson:"updateAt,omitempty" json:"updateAt,omitempty"` UpdateAt int64 `bson:"updateAt,omitempty" json:"updateAt,omitempty"`
CreateAt int64 `bson:"createAt,omitempty" json:"createAt,omitempty"` // -> 排序條件 CreateAt int64 `bson:"createAt,omitempty" json:"createAt,omitempty"` // -> 排序條件
} }

View File

@ -0,0 +1,47 @@
// Code generated by goctl. DO NOT EDIT.
// Source: tweeting.proto
package server
import (
"context"
"app-cloudep-tweeting-service/gen_result/pb/tweeting"
"app-cloudep-tweeting-service/internal/logic/commentservice"
"app-cloudep-tweeting-service/internal/svc"
)
type CommentServiceServer struct {
svcCtx *svc.ServiceContext
tweeting.UnimplementedCommentServiceServer
}
func NewCommentServiceServer(svcCtx *svc.ServiceContext) *CommentServiceServer {
return &CommentServiceServer{
svcCtx: svcCtx,
}
}
// NewComment 發表評論
func (s *CommentServiceServer) NewComment(ctx context.Context, in *tweeting.CommentPostReq) (*tweeting.CommentPostResp, error) {
l := commentservicelogic.NewNewCommentLogic(ctx, s.svcCtx)
return l.NewComment(in)
}
// GetComments 查詢評論
func (s *CommentServiceServer) GetComments(ctx context.Context, in *tweeting.GetCommentsReq) (*tweeting.GetCommentsResp, error) {
l := commentservicelogic.NewGetCommentsLogic(ctx, s.svcCtx)
return l.GetComments(in)
}
// DeleteComment 刪除評論
func (s *CommentServiceServer) DeleteComment(ctx context.Context, in *tweeting.DeleteCommentReq) (*tweeting.OKResp, error) {
l := commentservicelogic.NewDeleteCommentLogic(ctx, s.svcCtx)
return l.DeleteComment(in)
}
// UpdateComment 更新評論
func (s *CommentServiceServer) UpdateComment(ctx context.Context, in *tweeting.UpdateCommentReq) (*tweeting.OKResp, error) {
l := commentservicelogic.NewUpdateCommentLogic(ctx, s.svcCtx)
return l.UpdateComment(in)
}

View File

@ -7,7 +7,7 @@ import (
"context" "context"
"app-cloudep-tweeting-service/gen_result/pb/tweeting" "app-cloudep-tweeting-service/gen_result/pb/tweeting"
postservicelogic "app-cloudep-tweeting-service/internal/logic/postservice" "app-cloudep-tweeting-service/internal/logic/postservice"
"app-cloudep-tweeting-service/internal/svc" "app-cloudep-tweeting-service/internal/svc"
) )
@ -45,9 +45,3 @@ func (s *PostServiceServer) ListPosts(ctx context.Context, in *tweeting.QueryPos
l := postservicelogic.NewListPostsLogic(ctx, s.svcCtx) l := postservicelogic.NewListPostsLogic(ctx, s.svcCtx)
return l.ListPosts(in) return l.ListPosts(in)
} }
// ModifyLikeDislikeCount 調整讚或不讚數量
func (s *PostServiceServer) ModifyLikeDislikeCount(ctx context.Context, in *tweeting.ModifyLikeDislikeCountReq) (*tweeting.OKResp, error) {
l := postservicelogic.NewModifyLikeDislikeCountLogic(ctx, s.svcCtx)
return l.ModifyLikeDislikeCount(in)
}

View File

@ -14,7 +14,14 @@ func mustMongoConnectUrl(c config.Config) string {
) )
} }
// TODO 思考快取做在那邊
func MustPostModel(c config.Config) model.PostModel { func MustPostModel(c config.Config) model.PostModel {
postCollection := model.Post{} postCollection := model.Post{}
return model.NewPostModel(mustMongoConnectUrl(c), c.Mongo.Database, postCollection.CollectionName()) return model.NewPostModel(mustMongoConnectUrl(c), c.Mongo.Database, postCollection.CollectionName())
} }
func MustCommentModel(c config.Config) model.CommentModel {
m := model.Comment{}
return model.NewCommentModel(mustMongoConnectUrl(c), c.Mongo.Database, m.CollectionName())
}

View File

@ -11,14 +11,15 @@ type ServiceContext struct {
Config config.Config Config config.Config
Validate vi.Validate Validate vi.Validate
PostModel model.PostModel PostModel model.PostModel
CommentModel model.CommentModel
} }
func NewServiceContext(c config.Config) *ServiceContext { func NewServiceContext(c config.Config) *ServiceContext {
return &ServiceContext{ return &ServiceContext{
Config: c, Config: c,
Validate: vi.MustValidator(), Validate: vi.MustValidator(),
PostModel: MustPostModel(c),
PostModel: MustPostModel(c), CommentModel: MustCommentModel(c),
} }
} }