feature/post #1

Open
daniel.w wants to merge 7 commits from feature/post into main
8 changed files with 193 additions and 16 deletions
Showing only changes of commit 132f1ba951 - Show all commits

View File

@ -15,12 +15,17 @@ message Pager {
int64 index=3; // int64 index=3; //
} }
message Media{
string type =1;
string url =2;
}
// //
message NewPostReq { message NewPostReq {
int64 user_id = 1; // ID string uid = 1; // ID
string content = 2; // string content = 2; //
repeated string tags = 3; // repeated string tags = 3; //
repeated string media_url = 4; // Media URL repeated Media media = 4; // Media URL
bool is_ad = 5; // bool is_ad = 5; //
} }
@ -38,7 +43,7 @@ message DeletePostsReq {
message UpdatePostReq { message UpdatePostReq {
string post_id = 1; // ID string post_id = 1; // ID
repeated string tags = 2; // repeated string tags = 2; //
repeated string media_url = 3; // Media URL repeated Media media = 3; // Media URL
optional string content = 4; // optional string content = 4; //
optional int64 like_count = 5; // optional int64 like_count = 5; //
optional int64 dislike_count = 6; // optional int64 dislike_count = 6; //
@ -60,7 +65,7 @@ message PostDetailItem {
int64 user_id = 2; // ID int64 user_id = 2; // ID
string content = 3; // string content = 3; //
repeated string tags = 4; // repeated string tags = 4; //
repeated string media_url = 5; // URL repeated Media media = 5; // URL
bool is_ad = 6; // bool is_ad = 6; //
int64 created_at = 7; // int64 created_at = 7; //
int64 update_at = 8; // int64 update_at = 8; //

17
go.mod
View File

@ -3,7 +3,10 @@ module app-cloudep-tweeting-service
go 1.22.3 go 1.22.3
require ( require (
code.30cm.net/digimon/library-go/errs v1.2.4
code.30cm.net/digimon/library-go/validator v1.0.0
github.com/zeromicro/go-zero v1.7.0 github.com/zeromicro/go-zero v1.7.0
go.mongodb.org/mongo-driver v1.16.1
google.golang.org/grpc v1.66.0 google.golang.org/grpc v1.66.0
google.golang.org/protobuf v1.34.2 google.golang.org/protobuf v1.34.2
) )
@ -18,14 +21,19 @@ require (
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/fatih/color v1.17.0 // indirect github.com/fatih/color v1.17.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.4 // indirect github.com/go-openapi/swag v0.22.4 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.22.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/mock v1.6.0 // indirect github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.4 // indirect github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/gnostic-models v0.6.8 // indirect github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect github.com/google/gofuzz v1.2.0 // indirect
@ -33,11 +41,14 @@ require (
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
github.com/josharian/intern v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.8 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/montanaflynn/stats v0.7.1 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.3 // indirect github.com/openzipkin/zipkin-go v0.4.3 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect
@ -47,6 +58,10 @@ require (
github.com/prometheus/procfs v0.12.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect
github.com/redis/go-redis/v9 v9.6.1 // indirect github.com/redis/go-redis/v9 v9.6.1 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect
go.etcd.io/etcd/api/v3 v3.5.15 // indirect go.etcd.io/etcd/api/v3 v3.5.15 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.15 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.15 // indirect
go.etcd.io/etcd/client/v3 v3.5.15 // indirect go.etcd.io/etcd/client/v3 v3.5.15 // indirect
@ -65,8 +80,10 @@ require (
go.uber.org/automaxprocs v1.5.3 // indirect go.uber.org/automaxprocs v1.5.3 // indirect
go.uber.org/multierr v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect
go.uber.org/zap v1.24.0 // indirect go.uber.org/zap v1.24.0 // indirect
golang.org/x/crypto v0.25.0 // indirect
golang.org/x/net v0.27.0 // indirect golang.org/x/net v0.27.0 // indirect
golang.org/x/oauth2 v0.21.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.22.0 // indirect golang.org/x/sys v0.22.0 // indirect
golang.org/x/term v0.22.0 // indirect golang.org/x/term v0.22.0 // indirect
golang.org/x/text v0.16.0 // indirect golang.org/x/text v0.16.0 // indirect

View File

@ -1,7 +1,22 @@
package config package config
import "github.com/zeromicro/go-zero/zrpc" import (
"github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/zrpc"
)
type Config struct { type Config struct {
zrpc.RpcServerConf zrpc.RpcServerConf
Mongo struct {
Schema string
User string
Password string
Host string
Port string
Database string
Collection string
}
// 快取
Cache cache.CacheConf
} }

38
internal/domain/errors.go Normal file
View File

@ -0,0 +1,38 @@
package domain
import (
"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
func (e ErrorCode) ToUint32() uint32 {
return uint32(e)
}
const (
_ = iota
PostMongoErrorCode ErrorCode = iota
)
// PostMongoError ...
func PostMongoError(s ...string) *errs.LibError {
return errs.NewError(code.CloudEPTweeting, code.DBError,
PostMongoErrorCode.ToUint32(),
fmt.Sprintf("%s", strings.Join(s, " ")))
}
// PostMongoErrorL logs error message and returns Err
func PostMongoErrorL(l logx.Logger, filed []logx.LogField, s ...string) *errs.LibError {
e := PostMongoError(s...)
if filed != nil || len(filed) >= 0 {
l.WithCallerSkip(1).WithFields(filed...).Error(e.Error())
}
l.WithCallerSkip(1).Error(e.Error())
return e
}

12
internal/domain/status.go Normal file
View File

@ -0,0 +1,12 @@
package domain
type TweetingStatus int8
func (t TweetingStatus) ToInt8() int8 {
return int8(t)
}
const (
TweetingStatusNotReviewedYet TweetingStatus = iota + 1
TweetingStatusPass
)

View File

@ -1,10 +1,12 @@
package postservicelogic package postservicelogic
import ( import (
"context"
"app-cloudep-tweeting-service/gen_result/pb/tweeting" "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" "app-cloudep-tweeting-service/internal/svc"
ers "code.30cm.net/digimon/library-go/errs"
"context"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
) )
@ -23,9 +25,64 @@ func NewNewPostLogic(ctx context.Context, svcCtx *svc.ServiceContext) *NewPostLo
} }
} }
type newTweetingReq struct {
UID string `json:"uid" validate:"required"`
Content string `json:"content" validate:"required,gte=500"` // 貼文限制 500 字內
Tags []string `json:"tags"`
MediaUrl []string `json:"media_url"`
IsAd bool `json:"is_ad"` // default false
}
// NewPost 新增貼文 // NewPost 新增貼文
func (l *NewPostLogic) NewPost(in *tweeting.NewPostReq) (*tweeting.PostResp, error) { func (l *NewPostLogic) NewPost(in *tweeting.NewPostReq) (*tweeting.PostResp, error) {
// todo: add your logic here and delete this line // 驗證資料
if err := l.svcCtx.Validate.ValidateAll(&newTweetingReq{
UID: in.GetUid(),
Content: in.GetContent(),
}); err != nil {
return nil, ers.InvalidFormat(err.Error())
}
// ============ prepare ============
// 新增資料
tweet := &model.Post{
UID: in.GetUid(),
Content: in.GetContent(),
Status: domain.TweetingStatusNotReviewedYet.ToInt8(),
IsAd: in.IsAd,
}
if len(in.GetTags()) > 0 {
// 存在貼文內的不提供搜尋純顯示用只不過在原始的tag 發生變動的時候,並不會一起改變
// 搜尋會貼文與Tag 的表會再另外一邊做關聯
// 暫時業務邏輯上tag 只提供新增,不提供修改以及刪除,故目前版本可行
tweet.Tags = in.GetTags()
}
return &tweeting.PostResp{}, nil if len(in.Media) > 0 {
// 將 Media 存入
var media []model.Media
for _, item := range in.GetMedia() {
media = append(media, model.Media{
Links: item.Url,
Type: item.Type,
})
}
tweet.Media = media
}
// ============ insert ============
err := l.svcCtx.PostModel.Insert(l.ctx, tweet)
if err != nil {
e := domain.PostMongoErrorL(
logx.WithContext(l.ctx),
[]logx.LogField{
{Key: "req", Value: in},
{Key: "func", Value: "PostModel.Insert"},
{Key: "err", Value: err},
},
"failed to add new post").Wrap(err)
return nil, e
}
return &tweeting.PostResp{
PostId: tweet.ID.Hex(),
}, nil
} }

View File

@ -6,9 +6,24 @@ import (
"go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson/primitive"
) )
// TODO Tag 這裡在效能與正確性之間做取捨
// 存在貼文內的不提供搜尋純顯示用只不過在原始的tag 發生變動的時候,並不會一起改變
// 搜尋會貼文與Tag 的表會再另外一邊做關聯
// 暫時業務邏輯上tag 只提供新增,不提供修改以及刪除,故目前版本可行
type Post struct { type Post struct {
ID primitive.ObjectID `bson:"_id,omitempty" json:"id,omitempty"` ID primitive.ObjectID `bson:"_id,omitempty" json:"id,omitempty"`
// TODO: Fill your own fields UID string `bson:"uid" json:"uid"`
Content string `bson:"content" json:"content"`
Status int8 `bson:"status" json:"status"` // 1. 等待審核中 , 2 審核通過,預設為 1
IsAd bool `bson:"is_ad" json:"is_ad"` // 此則貼文是否為廣告貼文
Tags []string `bson:"tags" json:"tags"` // 本則貼文的標籤,不提供搜尋,僅提供顯示(存名字ID 建立之後就不提供修改與刪除)
Media []Media `bson:"media_url" json:"media_url"` // 網址
UpdateAt time.Time `bson:"updateAt,omitempty" json:"updateAt,omitempty"` UpdateAt time.Time `bson:"updateAt,omitempty" json:"updateAt,omitempty"`
CreateAt time.Time `bson:"createAt,omitempty" json:"createAt,omitempty"` CreateAt time.Time `bson:"createAt,omitempty" json:"createAt,omitempty"`
} }
type Media struct {
Type string // media type jpeg, m3u8 之類的
Links string // 連結的網址
}

View File

@ -1,13 +1,31 @@
package svc package svc
import "app-cloudep-tweeting-service/internal/config" import (
"app-cloudep-tweeting-service/internal/config"
model "app-cloudep-tweeting-service/internal/model/mongo"
vi "code.30cm.net/digimon/library-go/validator"
"fmt"
)
type ServiceContext struct { type ServiceContext struct {
Config config.Config Config config.Config
Validate vi.Validate
PostModel model.PostModel
} }
func NewServiceContext(c config.Config) *ServiceContext { func NewServiceContext(c config.Config) *ServiceContext {
baseMongo := MustMongoConnectUrl(c)
return &ServiceContext{ return &ServiceContext{
Config: c, Config: c,
Validate: vi.MustValidator(),
PostModel: model.NewPostModel(baseMongo, c.Mongo.Database, "post", c.Cache),
} }
} }
func MustMongoConnectUrl(c config.Config) string {
return fmt.Sprintf(
"%s://%s:%s", c.Mongo.Schema,
c.Mongo.Host, c.Mongo.Port)
}