mirror of https://github.com/rocboss/paopao-ce
Merge pull request #148 from alimy/pr-optimize-core-service-logic
optimize core service implement logicpull/149/head
commit
65f8bd626e
@ -0,0 +1,11 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"github.com/Masterminds/semver/v3"
|
||||
)
|
||||
|
||||
// VersionInfo 版本信息
|
||||
type VersionInfo interface {
|
||||
Name() string
|
||||
Version() *semver.Version
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/rocboss/paopao-ce/internal/model"
|
||||
)
|
||||
|
||||
func (d *dataServant) CreateAttachment(attachment *model.Attachment) (*model.Attachment, error) {
|
||||
return attachment.Create(d.engine)
|
||||
}
|
||||
|
||||
func (s *attachmentCheckServant) CheckAttachment(uri string) error {
|
||||
if strings.Index(uri, s.domain) != 0 {
|
||||
return fmt.Errorf("附件非本站资源")
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"github.com/rocboss/paopao-ce/internal/conf"
|
||||
"github.com/rocboss/paopao-ce/internal/core"
|
||||
"github.com/rocboss/paopao-ce/internal/model"
|
||||
)
|
||||
|
||||
func newSimpleAuthorizationManageService() *simpleAuthorizationManageService {
|
||||
return &simpleAuthorizationManageService{
|
||||
db: conf.DBEngine,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *simpleAuthorizationManageService) IsAllow(user *model.User, action *core.Action) bool {
|
||||
// user is activation if had bind phone
|
||||
isActivation := (len(user.Phone) != 0)
|
||||
isFriend := s.isFriend(action.UserId)
|
||||
// TODO: just use defaut act authorization chek rule now
|
||||
return action.Act.IsAllow(user, action.UserId, isFriend, isActivation)
|
||||
}
|
||||
|
||||
// GetFriendFilter _userId保留未来使用
|
||||
func (s *simpleAuthorizationManageService) GetFriendFilter(_userId int64) core.FriendFilter {
|
||||
// TODO: just return an empty friend fileter now
|
||||
return core.FriendFilter{}
|
||||
}
|
||||
|
||||
func (s *simpleAuthorizationManageService) GetFriendIds(_userId int64) []int64 {
|
||||
// TODO: just retrun empty now
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *simpleAuthorizationManageService) isFriend(_userId int64) bool {
|
||||
// friend with all world now
|
||||
return true
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/allegro/bigcache/v3"
|
||||
"github.com/rocboss/paopao-ce/internal/conf"
|
||||
"github.com/rocboss/paopao-ce/internal/core"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func NewBigCacheIndexService(indexPosts core.IndexPostsService) (core.CacheIndexService, core.VersionInfo) {
|
||||
s := conf.BigCacheIndexSetting
|
||||
|
||||
config := bigcache.DefaultConfig(s.ExpireInSecond)
|
||||
config.Shards = s.MaxIndexPage
|
||||
config.Verbose = s.Verbose
|
||||
config.MaxEntrySize = 10000
|
||||
config.Logger = logrus.StandardLogger()
|
||||
cache, err := bigcache.NewBigCache(config)
|
||||
if err != nil {
|
||||
logrus.Fatalf("initial bigCahceIndex failure by err: %v", err)
|
||||
}
|
||||
|
||||
cacheIndex := &bigCacheIndexServant{
|
||||
ips: indexPosts,
|
||||
cache: cache,
|
||||
}
|
||||
|
||||
// indexActionCh capacity custom configure by conf.yaml need in [10, 10000]
|
||||
// or re-compile source to adjust min/max capacity
|
||||
capacity := conf.CacheIndexSetting.MaxUpdateQPS
|
||||
if capacity < 10 {
|
||||
capacity = 10
|
||||
} else if capacity > 10000 {
|
||||
capacity = 10000
|
||||
}
|
||||
cacheIndex.indexActionCh = make(chan core.IndexActionT, capacity)
|
||||
cacheIndex.cachePostsCh = make(chan *postsEntry, capacity)
|
||||
|
||||
// 启动索引更新器
|
||||
go cacheIndex.startIndexPosts()
|
||||
|
||||
return cacheIndex, cacheIndex
|
||||
}
|
||||
|
||||
func NewSimpleCacheIndexService(indexPosts core.IndexPostsService) (core.CacheIndexService, core.VersionInfo) {
|
||||
s := conf.SimpleCacheIndexSetting
|
||||
cacheIndex := &simpleCacheIndexServant{
|
||||
ips: indexPosts,
|
||||
maxIndexSize: s.MaxIndexSize,
|
||||
indexPosts: nil,
|
||||
checkTick: time.NewTicker(s.CheckTickDuration), // check whether need update index every 1 minute
|
||||
expireIndexTick: time.NewTicker(time.Second),
|
||||
}
|
||||
|
||||
// force expire index every ExpireTickDuration second
|
||||
if s.ExpireTickDuration != 0 {
|
||||
cacheIndex.expireIndexTick.Reset(s.CheckTickDuration)
|
||||
} else {
|
||||
cacheIndex.expireIndexTick.Stop()
|
||||
}
|
||||
|
||||
// indexActionCh capacity custom configure by conf.yaml need in [10, 10000]
|
||||
// or re-compile source to adjust min/max capacity
|
||||
capacity := conf.CacheIndexSetting.MaxUpdateQPS
|
||||
if capacity < 10 {
|
||||
capacity = 10
|
||||
} else if capacity > 10000 {
|
||||
capacity = 10000
|
||||
}
|
||||
cacheIndex.indexActionCh = make(chan core.IndexActionT, capacity)
|
||||
|
||||
// start index posts
|
||||
cacheIndex.atomicIndex.Store(cacheIndex.indexPosts)
|
||||
go cacheIndex.startIndexPosts()
|
||||
|
||||
return cacheIndex, cacheIndex
|
||||
}
|
||||
|
||||
func NewNoneCacheIndexService(indexPosts core.IndexPostsService) (core.CacheIndexService, core.VersionInfo) {
|
||||
obj := &noneCacheIndexServant{
|
||||
ips: indexPosts,
|
||||
}
|
||||
return obj, obj
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
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 (
|
||||
_ core.CacheIndexService = (*noneCacheIndexServant)(nil)
|
||||
_ core.VersionInfo = (*noneCacheIndexServant)(nil)
|
||||
)
|
||||
|
||||
type noneCacheIndexServant struct {
|
||||
ips core.IndexPostsService
|
||||
}
|
||||
|
||||
func (s *noneCacheIndexServant) IndexPosts(user *model.User, offset int, limit int) (*rest.IndexTweetsResp, error) {
|
||||
return s.ips.IndexPosts(user, offset, limit)
|
||||
}
|
||||
|
||||
func (s *noneCacheIndexServant) SendAction(act core.IndexActionT) {
|
||||
// empty
|
||||
}
|
||||
|
||||
func (s *noneCacheIndexServant) Name() string {
|
||||
return "NoneCacheIndex"
|
||||
}
|
||||
|
||||
func (s *noneCacheIndexServant) Version() *semver.Version {
|
||||
return semver.MustParse("v0.1.0")
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
var (
|
||||
_ core.CacheIndexService = (*simpleCacheIndexServant)(nil)
|
||||
_ core.VersionInfo = (*simpleCacheIndexServant)(nil)
|
||||
)
|
||||
|
||||
type simpleCacheIndexServant struct {
|
||||
ips core.IndexPostsService
|
||||
|
||||
indexActionCh chan core.IndexActionT
|
||||
indexPosts *rest.IndexTweetsResp
|
||||
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)
|
||||
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{
|
||||
Tweets: cacheResp.Tweets[offset:end],
|
||||
Total: cacheResp.Total,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
logrus.Debugln("simpleCacheIndexServant.IndexPosts get index posts from database")
|
||||
return s.ips.IndexPosts(user, offset, limit)
|
||||
}
|
||||
|
||||
func (s *simpleCacheIndexServant) SendAction(act core.IndexActionT) {
|
||||
select {
|
||||
case s.indexActionCh <- act:
|
||||
logrus.Debugf("simpleCacheIndexServant.SendAction send indexAction by chan: %s", act)
|
||||
default:
|
||||
go func(ch chan<- core.IndexActionT, act core.IndexActionT) {
|
||||
logrus.Debugf("simpleCacheIndexServant.SendAction send indexAction by goroutine: %s", act)
|
||||
ch <- act
|
||||
}(s.indexActionCh, act)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *simpleCacheIndexServant) startIndexPosts() {
|
||||
var err error
|
||||
for {
|
||||
select {
|
||||
case <-s.checkTick.C:
|
||||
if s.indexPosts == nil {
|
||||
logrus.Debugf("index posts by checkTick")
|
||||
if s.indexPosts, err = s.ips.IndexPosts(nil, 0, s.maxIndexSize); err == nil {
|
||||
s.atomicIndex.Store(s.indexPosts)
|
||||
} else {
|
||||
logrus.Errorf("get index posts err: %v", err)
|
||||
}
|
||||
}
|
||||
case <-s.expireIndexTick.C:
|
||||
logrus.Debugf("expire index posts by expireIndexTick")
|
||||
if s.indexPosts != nil {
|
||||
s.indexPosts = nil
|
||||
s.atomicIndex.Store(s.indexPosts)
|
||||
}
|
||||
case action := <-s.indexActionCh:
|
||||
switch action {
|
||||
// TODO: 这里列出来是因为后续可能会精细化处理每种情况
|
||||
case core.IdxActCreatePost,
|
||||
core.IdxActUpdatePost,
|
||||
core.IdxActDeletePost,
|
||||
core.IdxActStickPost,
|
||||
core.IdxActVisiblePost:
|
||||
// prevent many update post in least time
|
||||
if s.indexPosts != nil {
|
||||
logrus.Debugf("remove index posts by action %s", action)
|
||||
s.indexPosts = nil
|
||||
s.atomicIndex.Store(s.indexPosts)
|
||||
}
|
||||
default:
|
||||
// nop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *simpleCacheIndexServant) Name() string {
|
||||
return "SimpleCacheIndex"
|
||||
}
|
||||
|
||||
func (s *simpleCacheIndexServant) Version() *semver.Version {
|
||||
return semver.MustParse("v0.1.0")
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/allegro/bigcache/v3"
|
||||
"github.com/rocboss/paopao-ce/internal/core"
|
||||
"github.com/rocboss/paopao-ce/internal/model"
|
||||
)
|
||||
|
||||
var (
|
||||
_ core.CacheIndexService = (*simpleCacheIndexServant)(nil)
|
||||
_ core.CacheIndexService = (*bigCacheIndexServant)(nil)
|
||||
_ core.CacheIndexService = (*noneCacheIndexServant)(nil)
|
||||
)
|
||||
|
||||
type postsEntry struct {
|
||||
key string
|
||||
posts []*model.PostFormated
|
||||
}
|
||||
|
||||
type indexPostsFunc func(*model.User, int, int) ([]*model.PostFormated, error)
|
||||
|
||||
type bigCacheIndexServant struct {
|
||||
getIndexPosts indexPostsFunc
|
||||
indexActionCh chan core.IndexActionT
|
||||
cachePostsCh chan *postsEntry
|
||||
cache *bigcache.BigCache
|
||||
lastCacheResetTime time.Time
|
||||
}
|
||||
|
||||
type simpleCacheIndexServant struct {
|
||||
getIndexPosts indexPostsFunc
|
||||
indexActionCh chan core.IndexActionT
|
||||
indexPosts []*model.PostFormated
|
||||
atomicIndex atomic.Value
|
||||
maxIndexSize int
|
||||
checkTick *time.Ticker
|
||||
expireIndexTick *time.Ticker
|
||||
}
|
||||
|
||||
type noneCacheIndexServant struct {
|
||||
getIndexPosts indexPostsFunc
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"github.com/Masterminds/semver/v3"
|
||||
"github.com/rocboss/paopao-ce/internal/core"
|
||||
"github.com/rocboss/paopao-ce/internal/model"
|
||||
)
|
||||
|
||||
func newNoneCacheIndexServant(getIndexPosts indexPostsFunc) (*noneCacheIndexServant, versionInfo) {
|
||||
obj := &noneCacheIndexServant{
|
||||
getIndexPosts: getIndexPosts,
|
||||
}
|
||||
return obj, obj
|
||||
}
|
||||
|
||||
func (s *noneCacheIndexServant) IndexPosts(user *model.User, offset int, limit int) ([]*model.PostFormated, error) {
|
||||
return s.getIndexPosts(user, offset, limit)
|
||||
}
|
||||
|
||||
func (s *noneCacheIndexServant) SendAction(act core.IndexActionT) {
|
||||
// empty
|
||||
}
|
||||
|
||||
func (s *noneCacheIndexServant) name() string {
|
||||
return "NoneCacheIndex"
|
||||
}
|
||||
|
||||
func (s *noneCacheIndexServant) version() *semver.Version {
|
||||
return semver.MustParse("v0.1.0")
|
||||
}
|
@ -1,118 +0,0 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/Masterminds/semver/v3"
|
||||
"github.com/rocboss/paopao-ce/internal/conf"
|
||||
"github.com/rocboss/paopao-ce/internal/core"
|
||||
"github.com/rocboss/paopao-ce/internal/model"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func newSimpleCacheIndexServant(getIndexPosts indexPostsFunc) (*simpleCacheIndexServant, versionInfo) {
|
||||
s := conf.SimpleCacheIndexSetting
|
||||
cacheIndex := &simpleCacheIndexServant{
|
||||
getIndexPosts: getIndexPosts,
|
||||
maxIndexSize: s.MaxIndexSize,
|
||||
indexPosts: make([]*model.PostFormated, 0),
|
||||
checkTick: time.NewTicker(s.CheckTickDuration), // check whether need update index every 1 minute
|
||||
expireIndexTick: time.NewTicker(time.Second),
|
||||
}
|
||||
|
||||
// force expire index every ExpireTickDuration second
|
||||
if s.ExpireTickDuration != 0 {
|
||||
cacheIndex.expireIndexTick.Reset(s.CheckTickDuration)
|
||||
} else {
|
||||
cacheIndex.expireIndexTick.Stop()
|
||||
}
|
||||
|
||||
// indexActionCh capacity custom configure by conf.yaml need in [10, 10000]
|
||||
// or re-compile source to adjust min/max capacity
|
||||
capacity := conf.CacheIndexSetting.MaxUpdateQPS
|
||||
if capacity < 10 {
|
||||
capacity = 10
|
||||
} else if capacity > 10000 {
|
||||
capacity = 10000
|
||||
}
|
||||
cacheIndex.indexActionCh = make(chan core.IndexActionT, capacity)
|
||||
|
||||
// start index posts
|
||||
cacheIndex.atomicIndex.Store(cacheIndex.indexPosts)
|
||||
go cacheIndex.startIndexPosts()
|
||||
|
||||
return cacheIndex, cacheIndex
|
||||
}
|
||||
|
||||
func (s *simpleCacheIndexServant) IndexPosts(user *model.User, offset int, limit int) ([]*model.PostFormated, error) {
|
||||
posts := s.atomicIndex.Load().([]*model.PostFormated)
|
||||
end := offset + limit
|
||||
size := len(posts)
|
||||
logrus.Debugf("get index posts from posts: %d offset:%d limit:%d start:%d, end:%d", size, offset, limit, offset, end)
|
||||
if size >= end {
|
||||
return posts[offset:end], nil
|
||||
}
|
||||
|
||||
logrus.Debugln("simpleCacheIndexServant.IndexPosts get index posts from database")
|
||||
return s.getIndexPosts(user, offset, limit)
|
||||
}
|
||||
|
||||
func (s *simpleCacheIndexServant) SendAction(act core.IndexActionT) {
|
||||
select {
|
||||
case s.indexActionCh <- act:
|
||||
logrus.Debugf("send indexAction by chan: %s", act)
|
||||
default:
|
||||
go func(ch chan<- core.IndexActionT, act core.IndexActionT) {
|
||||
logrus.Debugf("send indexAction by goroutine: %s", act)
|
||||
ch <- act
|
||||
}(s.indexActionCh, act)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *simpleCacheIndexServant) startIndexPosts() {
|
||||
var err error
|
||||
for {
|
||||
select {
|
||||
case <-s.checkTick.C:
|
||||
if len(s.indexPosts) == 0 {
|
||||
logrus.Debugf("index posts by checkTick")
|
||||
if s.indexPosts, err = s.getIndexPosts(nil, 0, s.maxIndexSize); err == nil {
|
||||
s.atomicIndex.Store(s.indexPosts)
|
||||
} else {
|
||||
logrus.Errorf("get index posts err: %v", err)
|
||||
}
|
||||
}
|
||||
case <-s.expireIndexTick.C:
|
||||
logrus.Debugf("expire index posts by expireIndexTick")
|
||||
if len(s.indexPosts) != 0 {
|
||||
s.indexPosts = nil
|
||||
s.atomicIndex.Store(s.indexPosts)
|
||||
}
|
||||
case action := <-s.indexActionCh:
|
||||
switch action {
|
||||
// TODO: 这里列出来是因为后续可能会精细化处理每种情况
|
||||
case core.IdxActCreatePost,
|
||||
core.IdxActUpdatePost,
|
||||
core.IdxActDeletePost,
|
||||
core.IdxActStickPost,
|
||||
core.IdxActVisiblePost:
|
||||
// prevent many update post in least time
|
||||
if len(s.indexPosts) != 0 {
|
||||
logrus.Debugf("remove index posts by action %s", action)
|
||||
s.indexPosts = nil
|
||||
s.atomicIndex.Store(s.indexPosts)
|
||||
}
|
||||
default:
|
||||
// nop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *simpleCacheIndexServant) name() string {
|
||||
return "SimpleCacheIndex"
|
||||
}
|
||||
|
||||
func (s *simpleCacheIndexServant) version() *semver.Version {
|
||||
return semver.MustParse("v0.1.0")
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package dao
|
||||
|
||||
import "github.com/rocboss/paopao-ce/internal/model"
|
||||
|
||||
func (d *dataServant) GetComments(conditions *model.ConditionsT, offset, limit int) ([]*model.Comment, error) {
|
||||
return (&model.Comment{}).List(d.engine, conditions, offset, limit)
|
||||
}
|
||||
|
||||
func (d *dataServant) GetCommentByID(id int64) (*model.Comment, error) {
|
||||
comment := &model.Comment{
|
||||
Model: &model.Model{
|
||||
ID: id,
|
||||
},
|
||||
}
|
||||
return comment.Get(d.engine)
|
||||
}
|
||||
|
||||
func (d *dataServant) DeleteComment(comment *model.Comment) error {
|
||||
return comment.Delete(d.engine)
|
||||
}
|
||||
|
||||
func (d *dataServant) GetCommentCount(conditions *model.ConditionsT) (int64, error) {
|
||||
return (&model.Comment{}).Count(d.engine, conditions)
|
||||
}
|
||||
|
||||
func (d *dataServant) CreateComment(comment *model.Comment) (*model.Comment, error) {
|
||||
return comment.Create(d.engine)
|
||||
}
|
||||
|
||||
func (d *dataServant) CreateCommentReply(reply *model.CommentReply) (*model.CommentReply, error) {
|
||||
return reply.Create(d.engine)
|
||||
}
|
||||
|
||||
func (d *dataServant) GetCommentReplyByID(id int64) (*model.CommentReply, error) {
|
||||
reply := &model.CommentReply{
|
||||
Model: &model.Model{
|
||||
ID: id,
|
||||
},
|
||||
}
|
||||
return reply.Get(d.engine)
|
||||
}
|
||||
|
||||
func (d *dataServant) DeleteCommentReply(reply *model.CommentReply) error {
|
||||
return reply.Delete(d.engine)
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
package dao
|
||||
|
||||
import "github.com/rocboss/paopao-ce/internal/model"
|
||||
|
||||
func (d *dataServant) GetCommentContentsByIDs(ids []int64) ([]*model.CommentContent, error) {
|
||||
commentContent := &model.CommentContent{}
|
||||
return commentContent.List(d.engine, &model.ConditionsT{
|
||||
"comment_id IN ?": ids,
|
||||
}, 0, 0)
|
||||
}
|
||||
func (d *dataServant) GetCommentRepliesByID(ids []int64) ([]*model.CommentReplyFormated, error) {
|
||||
CommentReply := &model.CommentReply{}
|
||||
replies, err := CommentReply.List(d.engine, &model.ConditionsT{
|
||||
"comment_id IN ?": ids,
|
||||
}, 0, 0)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userIds := []int64{}
|
||||
for _, reply := range replies {
|
||||
userIds = append(userIds, reply.UserID, reply.AtUserID)
|
||||
}
|
||||
|
||||
users, err := d.GetUsersByIDs(userIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repliesFormated := []*model.CommentReplyFormated{}
|
||||
for _, reply := range replies {
|
||||
replyFormated := reply.Format()
|
||||
for _, user := range users {
|
||||
if reply.UserID == user.ID {
|
||||
replyFormated.User = user.Format()
|
||||
}
|
||||
if reply.AtUserID == user.ID {
|
||||
replyFormated.AtUser = user.Format()
|
||||
}
|
||||
}
|
||||
|
||||
repliesFormated = append(repliesFormated, replyFormated)
|
||||
}
|
||||
|
||||
return repliesFormated, nil
|
||||
}
|
||||
|
||||
func (d *dataServant) CreateCommentContent(content *model.CommentContent) (*model.CommentContent, error) {
|
||||
return content.Create(d.engine)
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package jinzhu
|
||||
|
||||
import (
|
||||
"github.com/rocboss/paopao-ce/internal/core"
|
||||
"github.com/rocboss/paopao-ce/internal/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
_ core.AuthorizationManageService = (*authorizationManageServant)(nil)
|
||||
)
|
||||
|
||||
type authorizationManageServant struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func (s *authorizationManageServant) IsAllow(user *model.User, action *core.Action) bool {
|
||||
// user is activation if had bind phone
|
||||
isActivation := (len(user.Phone) != 0)
|
||||
isFriend := s.isFriend(user.ID, action.UserId)
|
||||
// TODO: just use defaut act authorization chek rule now
|
||||
return action.Act.IsAllow(user, action.UserId, isFriend, isActivation)
|
||||
}
|
||||
|
||||
func (s *authorizationManageServant) BeFriendFilter(userId int64) core.FriendFilter {
|
||||
// just empty now
|
||||
return core.FriendFilter{}
|
||||
}
|
||||
|
||||
func (s *authorizationManageServant) BeFriendIds(userId int64) ([]int64, error) {
|
||||
// just empty now
|
||||
return []int64{}, nil
|
||||
}
|
||||
|
||||
func (s *authorizationManageServant) isFriend(userId int64, friendId int64) bool {
|
||||
// just true now
|
||||
return true
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
package jinzhu
|
||||
|
||||
import (
|
||||
"github.com/rocboss/paopao-ce/internal/core"
|
||||
"github.com/rocboss/paopao-ce/internal/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
_ core.CommentService = (*commentServant)(nil)
|
||||
_ core.CommentManageService = (*commentManageServant)(nil)
|
||||
)
|
||||
|
||||
type commentServant struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
type commentManageServant struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func newCommentService(db *gorm.DB) core.CommentService {
|
||||
return &commentServant{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
func newCommentManageService(db *gorm.DB) core.CommentManageService {
|
||||
return &commentManageServant{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
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) GetCommentByID(id int64) (*model.Comment, error) {
|
||||
comment := &model.Comment{
|
||||
Model: &model.Model{
|
||||
ID: id,
|
||||
},
|
||||
}
|
||||
return comment.Get(s.db)
|
||||
}
|
||||
|
||||
func (s *commentServant) GetCommentReplyByID(id int64) (*model.CommentReply, error) {
|
||||
reply := &model.CommentReply{
|
||||
Model: &model.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) GetCommentContentsByIDs(ids []int64) ([]*model.CommentContent, error) {
|
||||
commentContent := &model.CommentContent{}
|
||||
return commentContent.List(s.db, &model.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{
|
||||
"comment_id IN ?": ids,
|
||||
}, 0, 0)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userIds := []int64{}
|
||||
for _, reply := range replies {
|
||||
userIds = append(userIds, reply.UserID, reply.AtUserID)
|
||||
}
|
||||
|
||||
users, err := getUsersByIDs(s.db, userIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repliesFormated := []*model.CommentReplyFormated{}
|
||||
for _, reply := range replies {
|
||||
replyFormated := reply.Format()
|
||||
for _, user := range users {
|
||||
if reply.UserID == user.ID {
|
||||
replyFormated.User = user.Format()
|
||||
}
|
||||
if reply.AtUserID == user.ID {
|
||||
replyFormated.AtUser = user.Format()
|
||||
}
|
||||
}
|
||||
|
||||
repliesFormated = append(repliesFormated, replyFormated)
|
||||
}
|
||||
|
||||
return repliesFormated, nil
|
||||
}
|
||||
|
||||
func (s *commentManageServant) DeleteComment(comment *model.Comment) error {
|
||||
return comment.Delete(s.db)
|
||||
}
|
||||
|
||||
func (s *commentManageServant) CreateComment(comment *model.Comment) (*model.Comment, error) {
|
||||
return comment.Create(s.db)
|
||||
}
|
||||
|
||||
func (s *commentManageServant) CreateCommentReply(reply *model.CommentReply) (*model.CommentReply, error) {
|
||||
return reply.Create(s.db)
|
||||
}
|
||||
|
||||
func (s *commentManageServant) DeleteCommentReply(reply *model.CommentReply) error {
|
||||
return reply.Delete(s.db)
|
||||
}
|
||||
|
||||
func (s *commentManageServant) CreateCommentContent(content *model.CommentContent) (*model.CommentContent, error) {
|
||||
return content.Create(s.db)
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
// Core service implement base gorm+mysql/postgresql/sqlite3.
|
||||
// Jinzhu is the primary developer of gorm so use his name as
|
||||
// pakcage name as a saluter.
|
||||
|
||||
package jinzhu
|
||||
|
||||
import (
|
||||
"github.com/Masterminds/semver/v3"
|
||||
"github.com/rocboss/paopao-ce/internal/conf"
|
||||
"github.com/rocboss/paopao-ce/internal/core"
|
||||
"github.com/rocboss/paopao-ce/internal/dao/cache"
|
||||
"github.com/rocboss/paopao-ce/internal/dao/security"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var (
|
||||
_ core.DataService = (*dataServant)(nil)
|
||||
_ core.VersionInfo = (*dataServant)(nil)
|
||||
)
|
||||
|
||||
type dataServant struct {
|
||||
core.IndexPostsService
|
||||
core.WalletService
|
||||
core.MessageService
|
||||
core.TopicService
|
||||
core.TweetService
|
||||
core.TweetManageService
|
||||
core.TweetHelpService
|
||||
core.CommentService
|
||||
core.CommentManageService
|
||||
core.UserManageService
|
||||
core.SecurityService
|
||||
core.AttachmentCheckService
|
||||
}
|
||||
|
||||
func NewDataService() (core.DataService, core.VersionInfo) {
|
||||
// initialize CacheIndex if needed
|
||||
var (
|
||||
c core.CacheIndexService
|
||||
v core.VersionInfo
|
||||
)
|
||||
db := conf.DBEngine
|
||||
|
||||
i := newIndexPostsService(db)
|
||||
if conf.CfgIf("SimpleCacheIndex") {
|
||||
i = newSimpleIndexPostsService(db)
|
||||
c, v = cache.NewSimpleCacheIndexService(i)
|
||||
} else if conf.CfgIf("BigCacheIndex") {
|
||||
c, v = cache.NewBigCacheIndexService(i)
|
||||
} else {
|
||||
c, v = cache.NewNoneCacheIndexService(i)
|
||||
}
|
||||
logrus.Infof("use %s as cache index service by version: %s", v.Name(), v.Version())
|
||||
|
||||
ds := &dataServant{
|
||||
IndexPostsService: c,
|
||||
WalletService: newWalletService(db),
|
||||
MessageService: newMessageService(db),
|
||||
TopicService: newTopicService(db),
|
||||
TweetService: newTweetService(db),
|
||||
TweetManageService: newTweetManageService(db, c),
|
||||
TweetHelpService: newTweetHelpService(db),
|
||||
CommentService: newCommentService(db),
|
||||
CommentManageService: newCommentManageService(db),
|
||||
UserManageService: newUserManageService(db),
|
||||
SecurityService: newSecurityService(db),
|
||||
AttachmentCheckService: security.NewAttachmentCheckService(),
|
||||
}
|
||||
return ds, ds
|
||||
}
|
||||
|
||||
func NewAuthorizationManageService() core.AuthorizationManageService {
|
||||
return &authorizationManageServant{
|
||||
db: conf.DBEngine,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *dataServant) Name() string {
|
||||
return "Gorm"
|
||||
}
|
||||
|
||||
func (s *dataServant) Version() *semver.Version {
|
||||
return semver.MustParse("v0.1.0")
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package jinzhu
|
||||
|
||||
import (
|
||||
"github.com/rocboss/paopao-ce/internal/core"
|
||||
"github.com/rocboss/paopao-ce/internal/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
_ core.MessageService = (*messageServant)(nil)
|
||||
)
|
||||
|
||||
type messageServant struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func newMessageService(db *gorm.DB) core.MessageService {
|
||||
return &messageServant{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *messageServant) CreateMessage(msg *model.Message) (*model.Message, error) {
|
||||
return msg.Create(d.db)
|
||||
}
|
||||
|
||||
func (d *messageServant) GetUnreadCount(userID int64) (int64, error) {
|
||||
return (&model.Message{}).Count(d.db, &model.ConditionsT{
|
||||
"receiver_user_id": userID,
|
||||
"is_read": model.MsgStatusUnread,
|
||||
})
|
||||
}
|
||||
|
||||
func (d *messageServant) GetMessageByID(id int64) (*model.Message, error) {
|
||||
return (&model.Message{
|
||||
Model: &model.Model{
|
||||
ID: id,
|
||||
},
|
||||
}).Get(d.db)
|
||||
}
|
||||
|
||||
func (d *messageServant) ReadMessage(message *model.Message) error {
|
||||
message.IsRead = 1
|
||||
return message.Update(d.db)
|
||||
}
|
||||
|
||||
func (d *messageServant) GetMessages(conditions *model.ConditionsT, offset, limit int) ([]*model.MessageFormated, error) {
|
||||
messages, err := (&model.Message{}).List(d.db, conditions, offset, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mfs := []*model.MessageFormated{}
|
||||
for _, message := range messages {
|
||||
mf := message.Format()
|
||||
mfs = append(mfs, mf)
|
||||
}
|
||||
|
||||
return mfs, nil
|
||||
}
|
||||
|
||||
func (d *messageServant) GetMessageCount(conditions *model.ConditionsT) (int64, error) {
|
||||
return (&model.Message{}).Count(d.db, conditions)
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package jinzhu
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/rocboss/paopao-ce/internal/conf"
|
||||
"github.com/rocboss/paopao-ce/internal/core"
|
||||
"github.com/rocboss/paopao-ce/internal/model"
|
||||
"github.com/rocboss/paopao-ce/pkg/json"
|
||||
"gopkg.in/resty.v1"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
_ core.SecurityService = (*securityServant)(nil)
|
||||
)
|
||||
|
||||
type securityServant struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func newSecurityService(db *gorm.DB) core.SecurityService {
|
||||
return &securityServant{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
type juhePhoneCaptchaRsp struct {
|
||||
ErrorCode int `json:"error_code"`
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
|
||||
// 获取最新短信验证码
|
||||
func (s *securityServant) GetLatestPhoneCaptcha(phone string) (*model.Captcha, error) {
|
||||
return (&model.Captcha{
|
||||
Phone: phone,
|
||||
}).Get(s.db)
|
||||
}
|
||||
|
||||
// 更新短信验证码
|
||||
func (s *securityServant) UsePhoneCaptcha(captcha *model.Captcha) error {
|
||||
captcha.UseTimes++
|
||||
return captcha.Update(s.db)
|
||||
}
|
||||
|
||||
// 发送短信验证码
|
||||
func (s *securityServant) SendPhoneCaptcha(phone string) error {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
captcha := rand.Intn(900000) + 100000
|
||||
m := 5
|
||||
|
||||
client := resty.New()
|
||||
client.DisableWarn = true
|
||||
resp, err := client.R().
|
||||
SetFormData(map[string]string{
|
||||
"mobile": phone,
|
||||
"tpl_id": conf.SmsJuheSetting.TplID,
|
||||
"tpl_value": fmt.Sprintf(conf.SmsJuheSetting.TplVal, captcha, m),
|
||||
"key": conf.SmsJuheSetting.Key,
|
||||
}).Post(conf.SmsJuheSetting.Gateway)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if resp.StatusCode() != http.StatusOK {
|
||||
return errors.New(resp.Status())
|
||||
}
|
||||
|
||||
result := &juhePhoneCaptchaRsp{}
|
||||
err = json.Unmarshal(resp.Body(), result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if result.ErrorCode != 0 {
|
||||
return errors.New(result.Reason)
|
||||
}
|
||||
|
||||
// 写入表
|
||||
captchaModel := &model.Captcha{
|
||||
Phone: phone,
|
||||
Captcha: strconv.Itoa(captcha),
|
||||
ExpiredOn: time.Now().Add(time.Minute * time.Duration(m)).Unix(),
|
||||
}
|
||||
captchaModel.Create(s.db)
|
||||
return nil
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package jinzhu
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/rocboss/paopao-ce/internal/core"
|
||||
"github.com/rocboss/paopao-ce/internal/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
_ core.TopicService = (*topicServant)(nil)
|
||||
)
|
||||
|
||||
type topicServant struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func newTopicService(db *gorm.DB) core.TopicService {
|
||||
return &topicServant{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *topicServant) CreateTag(tag *model.Tag) (*model.Tag, error) {
|
||||
return createTag(s.db, tag)
|
||||
}
|
||||
|
||||
func (s *topicServant) DeleteTag(tag *model.Tag) error {
|
||||
return deleteTag(s.db, tag)
|
||||
}
|
||||
|
||||
func (s *topicServant) GetTags(conditions *model.ConditionsT, offset, limit int) ([]*model.Tag, error) {
|
||||
return (&model.Tag{}).List(s.db, conditions, offset, limit)
|
||||
}
|
||||
|
||||
func (s *topicServant) GetTagsByKeyword(keyword string) ([]*model.Tag, error) {
|
||||
tag := &model.Tag{}
|
||||
|
||||
keyword = "%" + strings.Trim(keyword, " ") + "%"
|
||||
if keyword == "%%" {
|
||||
return tag.List(s.db, &model.ConditionsT{
|
||||
"ORDER": "quote_num DESC",
|
||||
}, 0, 6)
|
||||
} else {
|
||||
return tag.List(s.db, &model.ConditionsT{
|
||||
"tag LIKE ?": keyword,
|
||||
"ORDER": "quote_num DESC",
|
||||
}, 0, 6)
|
||||
}
|
||||
}
|
@ -0,0 +1,361 @@
|
||||
package jinzhu
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/rocboss/paopao-ce/internal/core"
|
||||
"github.com/rocboss/paopao-ce/internal/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
_ core.TweetService = (*tweetServant)(nil)
|
||||
_ core.TweetManageService = (*tweetManageServant)(nil)
|
||||
_ core.TweetHelpService = (*tweetHelpServant)(nil)
|
||||
)
|
||||
|
||||
type tweetServant struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
type tweetManageServant struct {
|
||||
cacheIndex core.CacheIndexService
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
type tweetHelpServant struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func newTweetService(db *gorm.DB) core.TweetService {
|
||||
return &tweetServant{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
func newTweetManageService(db *gorm.DB, cacheIndex core.CacheIndexService) core.TweetManageService {
|
||||
return &tweetManageServant{
|
||||
cacheIndex: cacheIndex,
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
func newTweetHelpService(db *gorm.DB) core.TweetHelpService {
|
||||
return &tweetHelpServant{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
// MergePosts post数据整合
|
||||
func (s *tweetHelpServant) MergePosts(posts []*model.Post) ([]*model.PostFormated, error) {
|
||||
postIds := make([]int64, 0, len(posts))
|
||||
userIds := make([]int64, 0, len(posts))
|
||||
for _, post := range posts {
|
||||
postIds = append(postIds, post.ID)
|
||||
userIds = append(userIds, post.UserID)
|
||||
}
|
||||
|
||||
postContents, err := s.getPostContentsByIDs(postIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
users, err := s.getUsersByIDs(userIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userMap := make(map[int64]*model.UserFormated, len(users))
|
||||
for _, user := range users {
|
||||
userMap[user.ID] = user.Format()
|
||||
}
|
||||
|
||||
contentMap := make(map[int64][]*model.PostContentFormated, len(postContents))
|
||||
for _, content := range postContents {
|
||||
contentMap[content.PostID] = append(contentMap[content.PostID], content.Format())
|
||||
}
|
||||
|
||||
// 数据整合
|
||||
postsFormated := make([]*model.PostFormated, 0, len(posts))
|
||||
for _, post := range posts {
|
||||
postFormated := post.Format()
|
||||
postFormated.User = userMap[post.UserID]
|
||||
postFormated.Contents = contentMap[post.ID]
|
||||
postsFormated = append(postsFormated, postFormated)
|
||||
}
|
||||
return postsFormated, nil
|
||||
}
|
||||
|
||||
// RevampPosts post数据整形修复
|
||||
func (s *tweetHelpServant) RevampPosts(posts []*model.PostFormated) ([]*model.PostFormated, error) {
|
||||
postIds := make([]int64, 0, len(posts))
|
||||
userIds := make([]int64, 0, len(posts))
|
||||
for _, post := range posts {
|
||||
postIds = append(postIds, post.ID)
|
||||
userIds = append(userIds, post.UserID)
|
||||
}
|
||||
|
||||
postContents, err := s.getPostContentsByIDs(postIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
users, err := s.getUsersByIDs(userIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userMap := make(map[int64]*model.UserFormated, len(users))
|
||||
for _, user := range users {
|
||||
userMap[user.ID] = user.Format()
|
||||
}
|
||||
|
||||
contentMap := make(map[int64][]*model.PostContentFormated, len(postContents))
|
||||
for _, content := range postContents {
|
||||
contentMap[content.PostID] = append(contentMap[content.PostID], content.Format())
|
||||
}
|
||||
|
||||
// 数据整合
|
||||
for _, post := range posts {
|
||||
post.User = userMap[post.UserID]
|
||||
post.Contents = contentMap[post.ID]
|
||||
}
|
||||
return posts, nil
|
||||
}
|
||||
|
||||
func (s *tweetHelpServant) getPostContentsByIDs(ids []int64) ([]*model.PostContent, error) {
|
||||
return (&model.PostContent{}).List(s.db, &model.ConditionsT{
|
||||
"post_id IN ?": ids,
|
||||
"ORDER": "sort ASC",
|
||||
}, 0, 0)
|
||||
}
|
||||
|
||||
func (s *tweetHelpServant) getUsersByIDs(ids []int64) ([]*model.User, error) {
|
||||
user := &model.User{}
|
||||
|
||||
return user.List(s.db, &model.ConditionsT{
|
||||
"id IN ?": ids,
|
||||
}, 0, 0)
|
||||
}
|
||||
|
||||
func (s *tweetManageServant) CreatePostCollection(postID, userID int64) (*model.PostCollection, error) {
|
||||
collection := &model.PostCollection{
|
||||
PostID: postID,
|
||||
UserID: userID,
|
||||
}
|
||||
|
||||
return collection.Create(s.db)
|
||||
}
|
||||
|
||||
func (s *tweetManageServant) DeletePostCollection(p *model.PostCollection) error {
|
||||
return p.Delete(s.db)
|
||||
}
|
||||
|
||||
func (s *tweetManageServant) CreatePostContent(content *model.PostContent) (*model.PostContent, error) {
|
||||
return content.Create(s.db)
|
||||
}
|
||||
|
||||
func (s *tweetManageServant) CreateAttachment(attachment *model.Attachment) (*model.Attachment, error) {
|
||||
return attachment.Create(s.db)
|
||||
}
|
||||
|
||||
func (s *tweetManageServant) CreatePost(post *model.Post) (*model.Post, error) {
|
||||
post.LatestRepliedOn = time.Now().Unix()
|
||||
p, err := post.Create(s.db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.cacheIndex.SendAction(core.IdxActCreatePost)
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (s *tweetManageServant) DeletePost(post *model.Post) error {
|
||||
if err := post.Delete(s.db); err != nil {
|
||||
return err
|
||||
}
|
||||
s.cacheIndex.SendAction(core.IdxActDeletePost)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *tweetManageServant) LockPost(post *model.Post) error {
|
||||
post.IsLock = 1 - post.IsLock
|
||||
return post.Update(s.db)
|
||||
}
|
||||
|
||||
func (s *tweetManageServant) StickPost(post *model.Post) error {
|
||||
post.IsTop = 1 - post.IsTop
|
||||
if err := post.Update(s.db); err != nil {
|
||||
return err
|
||||
}
|
||||
s.cacheIndex.SendAction(core.IdxActStickPost)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *tweetManageServant) VisiblePost(post *model.Post, visibility model.PostVisibleT) error {
|
||||
oldVisibility := post.Visibility
|
||||
post.Visibility = visibility
|
||||
// TODO: 这个判断是否可以不要呢
|
||||
if oldVisibility == visibility {
|
||||
return nil
|
||||
}
|
||||
// 私密推文 特殊处理
|
||||
if visibility == model.PostVisitPrivate {
|
||||
// 强制取消置顶
|
||||
// TODO: 置顶推文用户是否有权设置成私密? 后续完善
|
||||
post.IsTop = 0
|
||||
}
|
||||
db := s.db.Begin()
|
||||
err := post.Update(db)
|
||||
if err != nil {
|
||||
db.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
// tag处理
|
||||
tags := strings.Split(post.Tags, ",")
|
||||
for _, t := range tags {
|
||||
tag := &model.Tag{
|
||||
Tag: t,
|
||||
}
|
||||
// TODO: 暂时宽松不处理错误,这里或许可以有优化,后续完善
|
||||
if oldVisibility == model.PostVisitPrivate {
|
||||
// 从私密转为非私密才需要重新创建tag
|
||||
createTag(db, tag)
|
||||
} else if visibility == model.PostVisitPrivate {
|
||||
// 从非私密转为私密才需要删除tag
|
||||
deleteTag(db, tag)
|
||||
}
|
||||
}
|
||||
db.Commit()
|
||||
s.cacheIndex.SendAction(core.IdxActVisiblePost)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *tweetManageServant) UpdatePost(post *model.Post) error {
|
||||
if err := post.Update(s.db); err != nil {
|
||||
return err
|
||||
}
|
||||
s.cacheIndex.SendAction(core.IdxActUpdatePost)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *tweetManageServant) CreatePostStar(postID, userID int64) (*model.PostStar, error) {
|
||||
star := &model.PostStar{
|
||||
PostID: postID,
|
||||
UserID: userID,
|
||||
}
|
||||
return star.Create(s.db)
|
||||
}
|
||||
|
||||
func (s *tweetManageServant) DeletePostStar(p *model.PostStar) error {
|
||||
return p.Delete(s.db)
|
||||
}
|
||||
|
||||
func (s *tweetServant) GetPostByID(id int64) (*model.Post, error) {
|
||||
post := &model.Post{
|
||||
Model: &model.Model{
|
||||
ID: id,
|
||||
},
|
||||
}
|
||||
return post.Get(s.db)
|
||||
}
|
||||
|
||||
func (s *tweetServant) GetPosts(conditions *model.ConditionsT, offset, limit int) ([]*model.Post, error) {
|
||||
return (&model.Post{}).List(s.db, conditions, offset, limit)
|
||||
}
|
||||
|
||||
func (s *tweetServant) GetPostCount(conditions *model.ConditionsT) (int64, error) {
|
||||
return (&model.Post{}).Count(s.db, conditions)
|
||||
}
|
||||
|
||||
func (s *tweetServant) GetUserPostStar(postID, userID int64) (*model.PostStar, error) {
|
||||
star := &model.PostStar{
|
||||
PostID: postID,
|
||||
UserID: userID,
|
||||
}
|
||||
return star.Get(s.db)
|
||||
}
|
||||
|
||||
func (s *tweetServant) GetUserPostStars(userID int64, offset, limit int) ([]*model.PostStar, error) {
|
||||
star := &model.PostStar{
|
||||
UserID: userID,
|
||||
}
|
||||
|
||||
return star.List(s.db, &model.ConditionsT{
|
||||
"ORDER": s.db.NamingStrategy.TableName("PostStar") + ".id DESC",
|
||||
}, offset, limit)
|
||||
}
|
||||
|
||||
func (s *tweetServant) GetUserPostStarCount(userID int64) (int64, error) {
|
||||
star := &model.PostStar{
|
||||
UserID: userID,
|
||||
}
|
||||
return star.Count(s.db, &model.ConditionsT{})
|
||||
}
|
||||
|
||||
func (s *tweetServant) GetUserPostCollection(postID, userID int64) (*model.PostCollection, error) {
|
||||
star := &model.PostCollection{
|
||||
PostID: postID,
|
||||
UserID: userID,
|
||||
}
|
||||
return star.Get(s.db)
|
||||
}
|
||||
|
||||
func (s *tweetServant) GetUserPostCollections(userID int64, offset, limit int) ([]*model.PostCollection, error) {
|
||||
collection := &model.PostCollection{
|
||||
UserID: userID,
|
||||
}
|
||||
|
||||
return collection.List(s.db, &model.ConditionsT{
|
||||
"ORDER": s.db.NamingStrategy.TableName("PostCollection") + ".id DESC",
|
||||
}, offset, limit)
|
||||
}
|
||||
|
||||
func (s *tweetServant) GetUserPostCollectionCount(userID int64) (int64, error) {
|
||||
collection := &model.PostCollection{
|
||||
UserID: userID,
|
||||
}
|
||||
return collection.Count(s.db, &model.ConditionsT{})
|
||||
}
|
||||
|
||||
func (s *tweetServant) GetUserWalletBills(userID int64, offset, limit int) ([]*model.WalletStatement, error) {
|
||||
statement := &model.WalletStatement{
|
||||
UserID: userID,
|
||||
}
|
||||
|
||||
return statement.List(s.db, &model.ConditionsT{
|
||||
"ORDER": "id DESC",
|
||||
}, offset, limit)
|
||||
}
|
||||
|
||||
func (s *tweetServant) GetUserWalletBillCount(userID int64) (int64, error) {
|
||||
statement := &model.WalletStatement{
|
||||
UserID: userID,
|
||||
}
|
||||
return statement.Count(s.db, &model.ConditionsT{})
|
||||
}
|
||||
|
||||
func (s *tweetServant) GetPostAttatchmentBill(postID, userID int64) (*model.PostAttachmentBill, error) {
|
||||
bill := &model.PostAttachmentBill{
|
||||
PostID: postID,
|
||||
UserID: userID,
|
||||
}
|
||||
|
||||
return bill.Get(s.db)
|
||||
}
|
||||
|
||||
func (s *tweetServant) GetPostContentsByIDs(ids []int64) ([]*model.PostContent, error) {
|
||||
return (&model.PostContent{}).List(s.db, &model.ConditionsT{
|
||||
"post_id IN ?": ids,
|
||||
"ORDER": "sort ASC",
|
||||
}, 0, 0)
|
||||
}
|
||||
|
||||
func (s *tweetServant) GetPostContentByID(id int64) (*model.PostContent, error) {
|
||||
return (&model.PostContent{
|
||||
Model: &model.Model{
|
||||
ID: id,
|
||||
},
|
||||
}).Get(s.db)
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
package jinzhu
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/rocboss/paopao-ce/internal/core"
|
||||
"github.com/rocboss/paopao-ce/internal/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
_ core.UserManageService = (*userManageServant)(nil)
|
||||
)
|
||||
|
||||
type userManageServant struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func newUserManageService(db *gorm.DB) core.UserManageService {
|
||||
return &userManageServant{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *userManageServant) GetUserByID(id int64) (*model.User, error) {
|
||||
user := &model.User{
|
||||
Model: &model.Model{
|
||||
ID: id,
|
||||
},
|
||||
}
|
||||
return user.Get(s.db)
|
||||
}
|
||||
|
||||
func (s *userManageServant) GetUserByUsername(username string) (*model.User, error) {
|
||||
user := &model.User{
|
||||
Username: username,
|
||||
}
|
||||
return user.Get(s.db)
|
||||
}
|
||||
|
||||
func (s *userManageServant) GetUserByPhone(phone string) (*model.User, error) {
|
||||
user := &model.User{
|
||||
Phone: phone,
|
||||
}
|
||||
return user.Get(s.db)
|
||||
}
|
||||
|
||||
func (s *userManageServant) GetUsersByIDs(ids []int64) ([]*model.User, error) {
|
||||
user := &model.User{}
|
||||
return user.List(s.db, &model.ConditionsT{
|
||||
"id IN ?": ids,
|
||||
}, 0, 0)
|
||||
}
|
||||
|
||||
func (s *userManageServant) GetUsersByKeyword(keyword string) ([]*model.User, error) {
|
||||
user := &model.User{}
|
||||
keyword = strings.Trim(keyword, " ") + "%"
|
||||
if keyword == "%" {
|
||||
return user.List(s.db, &model.ConditionsT{
|
||||
"ORDER": "id ASC",
|
||||
}, 0, 6)
|
||||
} else {
|
||||
return user.List(s.db, &model.ConditionsT{
|
||||
"username LIKE ?": keyword,
|
||||
}, 0, 6)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *userManageServant) GetTagsByKeyword(keyword string) ([]*model.Tag, error) {
|
||||
tag := &model.Tag{}
|
||||
keyword = "%" + strings.Trim(keyword, " ") + "%"
|
||||
if keyword == "%%" {
|
||||
return tag.List(s.db, &model.ConditionsT{
|
||||
"ORDER": "quote_num DESC",
|
||||
}, 0, 6)
|
||||
} else {
|
||||
return tag.List(s.db, &model.ConditionsT{
|
||||
"tag LIKE ?": keyword,
|
||||
"ORDER": "quote_num DESC",
|
||||
}, 0, 6)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *userManageServant) CreateUser(user *model.User) (*model.User, error) {
|
||||
return user.Create(s.db)
|
||||
}
|
||||
|
||||
func (s *userManageServant) UpdateUser(user *model.User) error {
|
||||
return user.Update(s.db)
|
||||
}
|
||||
|
||||
func (s *userManageServant) IsFriend(userId int64, friendId int64) bool {
|
||||
// just true now
|
||||
return true
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package jinzhu
|
||||
|
||||
import (
|
||||
"github.com/rocboss/paopao-ce/internal/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func createTag(db *gorm.DB, tag *model.Tag) (*model.Tag, error) {
|
||||
t, err := tag.Get(db)
|
||||
if err != nil {
|
||||
tag.QuoteNum = 1
|
||||
return tag.Create(db)
|
||||
}
|
||||
|
||||
// 更新
|
||||
t.QuoteNum++
|
||||
err = t.Update(db)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func deleteTag(db *gorm.DB, tag *model.Tag) error {
|
||||
tag, err := tag.Get(db)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tag.QuoteNum--
|
||||
return tag.Update(db)
|
||||
}
|
||||
|
||||
// 根据IDs获取用户列表
|
||||
func getUsersByIDs(db *gorm.DB, ids []int64) ([]*model.User, error) {
|
||||
user := &model.User{}
|
||||
return user.List(db, &model.ConditionsT{
|
||||
"id IN ?": ids,
|
||||
}, 0, 0)
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
package dao
|
||||
|
||||
import "github.com/rocboss/paopao-ce/internal/model"
|
||||
|
||||
func (d *dataServant) CreateMessage(msg *model.Message) (*model.Message, error) {
|
||||
return msg.Create(d.engine)
|
||||
}
|
||||
|
||||
func (d *dataServant) GetUnreadCount(userID int64) (int64, error) {
|
||||
return (&model.Message{}).Count(d.engine, &model.ConditionsT{
|
||||
"receiver_user_id": userID,
|
||||
"is_read": model.MSG_UNREAD,
|
||||
})
|
||||
}
|
||||
|
||||
func (d *dataServant) GetMessageByID(id int64) (*model.Message, error) {
|
||||
return (&model.Message{
|
||||
Model: &model.Model{
|
||||
ID: id,
|
||||
},
|
||||
}).Get(d.engine)
|
||||
}
|
||||
|
||||
func (d *dataServant) ReadMessage(message *model.Message) error {
|
||||
message.IsRead = 1
|
||||
return message.Update(d.engine)
|
||||
}
|
||||
|
||||
func (d *dataServant) GetMessages(conditions *model.ConditionsT, offset, limit int) ([]*model.MessageFormated, error) {
|
||||
messages, err := (&model.Message{}).List(d.engine, conditions, offset, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mfs := []*model.MessageFormated{}
|
||||
for _, message := range messages {
|
||||
mf := message.Format()
|
||||
mfs = append(mfs, mf)
|
||||
}
|
||||
|
||||
return mfs, nil
|
||||
}
|
||||
|
||||
func (d *dataServant) GetMessageCount(conditions *model.ConditionsT) (int64, error) {
|
||||
return (&model.Message{}).Count(d.engine, conditions)
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"github.com/aliyun/aliyun-oss-go-sdk/oss"
|
||||
"github.com/minio/minio-go/v7"
|
||||
"github.com/rocboss/paopao-ce/internal/conf"
|
||||
"github.com/rocboss/paopao-ce/internal/core"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var (
|
||||
_ core.ObjectStorageService = (*aliossServant)(nil)
|
||||
_ core.ObjectStorageService = (*minioServant)(nil)
|
||||
_ core.ObjectStorageService = (*s3Servant)(nil)
|
||||
_ core.ObjectStorageService = (*localossServant)(nil)
|
||||
)
|
||||
|
||||
type localossServant struct {
|
||||
savePath string
|
||||
domain string
|
||||
}
|
||||
|
||||
type aliossServant struct {
|
||||
bucket *oss.Bucket
|
||||
domain string
|
||||
}
|
||||
|
||||
type minioServant struct {
|
||||
client *minio.Client
|
||||
bucket string
|
||||
domain string
|
||||
}
|
||||
|
||||
type s3Servant = minioServant
|
||||
|
||||
func NewObjectStorageService() (oss core.ObjectStorageService) {
|
||||
var v versionInfo
|
||||
if conf.CfgIf("AliOSS") {
|
||||
oss, v = newAliossServent()
|
||||
} else if conf.CfgIf("MinIO") {
|
||||
oss, v = newMinioServeant()
|
||||
} else if conf.CfgIf("S3") {
|
||||
oss, v = newS3Servent()
|
||||
logrus.Infof("use S3 as object storage by version %s", v.version())
|
||||
return
|
||||
} else if conf.CfgIf("LocalOSS") {
|
||||
oss, v = newLocalossServent()
|
||||
} else {
|
||||
// default use AliOSS as object storage service
|
||||
oss, v = newAliossServent()
|
||||
logrus.Infof("use default AliOSS as object storage by version %s", v.version())
|
||||
return
|
||||
}
|
||||
logrus.Infof("use %s as object storage by version %s", v.name(), v.version())
|
||||
return
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"github.com/minio/minio-go/v7"
|
||||
"github.com/minio/minio-go/v7/pkg/credentials"
|
||||
"github.com/rocboss/paopao-ce/internal/conf"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func newS3Servent() (*s3Servant, versionInfo) {
|
||||
// Initialize s3 client object use minio-go.
|
||||
client, err := minio.New(conf.S3Setting.Endpoint, &minio.Options{
|
||||
Creds: credentials.NewStaticV4(conf.S3Setting.AccessKey, conf.S3Setting.SecretKey, ""),
|
||||
Secure: conf.S3Setting.Secure,
|
||||
})
|
||||
if err != nil {
|
||||
logrus.Fatalf("s3.New err: %v", err)
|
||||
}
|
||||
|
||||
obj := &s3Servant{
|
||||
client: client,
|
||||
bucket: conf.MinIOSetting.Bucket,
|
||||
domain: getOssDomain(),
|
||||
}
|
||||
return obj, obj
|
||||
}
|
@ -1,286 +0,0 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/rocboss/paopao-ce/internal/core"
|
||||
"github.com/rocboss/paopao-ce/internal/model"
|
||||
)
|
||||
|
||||
func (d *dataServant) CreatePost(post *model.Post) (*model.Post, error) {
|
||||
post.LatestRepliedOn = time.Now().Unix()
|
||||
p, err := post.Create(d.engine)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
d.SendAction(core.IdxActCreatePost)
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (d *dataServant) DeletePost(post *model.Post) error {
|
||||
if err := post.Delete(d.engine); err != nil {
|
||||
return err
|
||||
}
|
||||
d.SendAction(core.IdxActDeletePost)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *dataServant) LockPost(post *model.Post) error {
|
||||
post.IsLock = 1 - post.IsLock
|
||||
return post.Update(d.engine)
|
||||
}
|
||||
|
||||
func (d *dataServant) StickPost(post *model.Post) error {
|
||||
post.IsTop = 1 - post.IsTop
|
||||
if err := post.Update(d.engine); err != nil {
|
||||
return err
|
||||
}
|
||||
d.SendAction(core.IdxActStickPost)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *dataServant) VisiblePost(post *model.Post, visibility model.PostVisibleT) error {
|
||||
oldVisibility := post.Visibility
|
||||
post.Visibility = visibility
|
||||
// TODO: 这个判断是否可以不要呢
|
||||
if oldVisibility == visibility {
|
||||
return nil
|
||||
}
|
||||
// 私密推文 特殊处理
|
||||
if visibility == model.PostVisitPrivate {
|
||||
// 强制取消置顶
|
||||
// TODO: 置顶推文用户是否有权设置成私密? 后续完善
|
||||
post.IsTop = 0
|
||||
}
|
||||
db := d.engine.Begin()
|
||||
err := post.Update(db)
|
||||
if err != nil {
|
||||
db.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
// tag处理
|
||||
tags := strings.Split(post.Tags, ",")
|
||||
for _, t := range tags {
|
||||
tag := &model.Tag{
|
||||
Tag: t,
|
||||
}
|
||||
// TODO: 暂时宽松不处理错误,这里或许可以有优化,后续完善
|
||||
if oldVisibility == model.PostVisitPrivate {
|
||||
// 从私密转为非私密才需要重新创建tag
|
||||
d.createTag(db, tag)
|
||||
} else if visibility == model.PostVisitPrivate {
|
||||
// 从非私密转为私密才需要删除tag
|
||||
d.deleteTag(db, tag)
|
||||
}
|
||||
}
|
||||
db.Commit()
|
||||
d.SendAction(core.IdxActVisiblePost)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *dataServant) GetPostByID(id int64) (*model.Post, error) {
|
||||
post := &model.Post{
|
||||
Model: &model.Model{
|
||||
ID: id,
|
||||
},
|
||||
}
|
||||
return post.Get(d.engine)
|
||||
}
|
||||
|
||||
func (d *dataServant) GetPosts(conditions *model.ConditionsT, offset, limit int) ([]*model.Post, error) {
|
||||
return (&model.Post{}).List(d.engine, conditions, offset, limit)
|
||||
}
|
||||
|
||||
func (d *dataServant) GetPostCount(conditions *model.ConditionsT) (int64, error) {
|
||||
return (&model.Post{}).Count(d.engine, conditions)
|
||||
}
|
||||
|
||||
func (d *dataServant) UpdatePost(post *model.Post) error {
|
||||
if err := post.Update(d.engine); err != nil {
|
||||
return err
|
||||
}
|
||||
d.SendAction(core.IdxActUpdatePost)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *dataServant) GetUserPostStar(postID, userID int64) (*model.PostStar, error) {
|
||||
star := &model.PostStar{
|
||||
PostID: postID,
|
||||
UserID: userID,
|
||||
}
|
||||
|
||||
return star.Get(d.engine)
|
||||
}
|
||||
|
||||
func (d *dataServant) GetUserPostStars(userID int64, offset, limit int) ([]*model.PostStar, error) {
|
||||
star := &model.PostStar{
|
||||
UserID: userID,
|
||||
}
|
||||
|
||||
return star.List(d.engine, &model.ConditionsT{
|
||||
"ORDER": d.engine.NamingStrategy.TableName("PostStar") + ".id DESC",
|
||||
}, offset, limit)
|
||||
}
|
||||
|
||||
func (d *dataServant) GetUserPostStarCount(userID int64) (int64, error) {
|
||||
star := &model.PostStar{
|
||||
UserID: userID,
|
||||
}
|
||||
return star.Count(d.engine, &model.ConditionsT{})
|
||||
}
|
||||
|
||||
func (d *dataServant) CreatePostStar(postID, userID int64) (*model.PostStar, error) {
|
||||
star := &model.PostStar{
|
||||
PostID: postID,
|
||||
UserID: userID,
|
||||
}
|
||||
|
||||
return star.Create(d.engine)
|
||||
}
|
||||
|
||||
func (d *dataServant) DeletePostStar(p *model.PostStar) error {
|
||||
return p.Delete(d.engine)
|
||||
}
|
||||
|
||||
func (d *dataServant) GetUserPostCollection(postID, userID int64) (*model.PostCollection, error) {
|
||||
star := &model.PostCollection{
|
||||
PostID: postID,
|
||||
UserID: userID,
|
||||
}
|
||||
|
||||
return star.Get(d.engine)
|
||||
}
|
||||
|
||||
func (d *dataServant) GetUserPostCollections(userID int64, offset, limit int) ([]*model.PostCollection, error) {
|
||||
collection := &model.PostCollection{
|
||||
UserID: userID,
|
||||
}
|
||||
|
||||
return collection.List(d.engine, &model.ConditionsT{
|
||||
"ORDER": d.engine.NamingStrategy.TableName("PostCollection") + ".id DESC",
|
||||
}, offset, limit)
|
||||
}
|
||||
|
||||
func (d *dataServant) GetUserPostCollectionCount(userID int64) (int64, error) {
|
||||
collection := &model.PostCollection{
|
||||
UserID: userID,
|
||||
}
|
||||
return collection.Count(d.engine, &model.ConditionsT{})
|
||||
}
|
||||
func (d *dataServant) GetUserWalletBills(userID int64, offset, limit int) ([]*model.WalletStatement, error) {
|
||||
statement := &model.WalletStatement{
|
||||
UserID: userID,
|
||||
}
|
||||
|
||||
return statement.List(d.engine, &model.ConditionsT{
|
||||
"ORDER": "id DESC",
|
||||
}, offset, limit)
|
||||
}
|
||||
|
||||
func (d *dataServant) GetUserWalletBillCount(userID int64) (int64, error) {
|
||||
statement := &model.WalletStatement{
|
||||
UserID: userID,
|
||||
}
|
||||
return statement.Count(d.engine, &model.ConditionsT{})
|
||||
}
|
||||
|
||||
func (d *dataServant) CreatePostCollection(postID, userID int64) (*model.PostCollection, error) {
|
||||
collection := &model.PostCollection{
|
||||
PostID: postID,
|
||||
UserID: userID,
|
||||
}
|
||||
|
||||
return collection.Create(d.engine)
|
||||
}
|
||||
|
||||
func (d *dataServant) DeletePostCollection(p *model.PostCollection) error {
|
||||
return p.Delete(d.engine)
|
||||
}
|
||||
|
||||
func (d *dataServant) GetPostAttatchmentBill(postID, userID int64) (*model.PostAttachmentBill, error) {
|
||||
bill := &model.PostAttachmentBill{
|
||||
PostID: postID,
|
||||
UserID: userID,
|
||||
}
|
||||
|
||||
return bill.Get(d.engine)
|
||||
}
|
||||
|
||||
// MergePosts post数据整合
|
||||
func (d *dataServant) MergePosts(posts []*model.Post) ([]*model.PostFormated, error) {
|
||||
postIds := make([]int64, 0, len(posts))
|
||||
userIds := make([]int64, 0, len(posts))
|
||||
for _, post := range posts {
|
||||
postIds = append(postIds, post.ID)
|
||||
userIds = append(userIds, post.UserID)
|
||||
}
|
||||
|
||||
postContents, err := d.GetPostContentsByIDs(postIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
users, err := d.GetUsersByIDs(userIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userMap := make(map[int64]*model.UserFormated, len(users))
|
||||
for _, user := range users {
|
||||
userMap[user.ID] = user.Format()
|
||||
}
|
||||
|
||||
contentMap := make(map[int64][]*model.PostContentFormated, len(postContents))
|
||||
for _, content := range postContents {
|
||||
contentMap[content.PostID] = append(contentMap[content.PostID], content.Format())
|
||||
}
|
||||
|
||||
// 数据整合
|
||||
postsFormated := make([]*model.PostFormated, 0, len(posts))
|
||||
for _, post := range posts {
|
||||
postFormated := post.Format()
|
||||
postFormated.User = userMap[post.UserID]
|
||||
postFormated.Contents = contentMap[post.ID]
|
||||
postsFormated = append(postsFormated, postFormated)
|
||||
}
|
||||
return postsFormated, nil
|
||||
}
|
||||
|
||||
// RevampPosts post数据整形修复
|
||||
func (d *dataServant) RevampPosts(posts []*model.PostFormated) ([]*model.PostFormated, error) {
|
||||
postIds := make([]int64, 0, len(posts))
|
||||
userIds := make([]int64, 0, len(posts))
|
||||
for _, post := range posts {
|
||||
postIds = append(postIds, post.ID)
|
||||
userIds = append(userIds, post.UserID)
|
||||
}
|
||||
|
||||
postContents, err := d.GetPostContentsByIDs(postIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
users, err := d.GetUsersByIDs(userIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userMap := make(map[int64]*model.UserFormated, len(users))
|
||||
for _, user := range users {
|
||||
userMap[user.ID] = user.Format()
|
||||
}
|
||||
|
||||
contentMap := make(map[int64][]*model.PostContentFormated, len(postContents))
|
||||
for _, content := range postContents {
|
||||
contentMap[content.PostID] = append(contentMap[content.PostID], content.Format())
|
||||
}
|
||||
|
||||
// 数据整合
|
||||
for _, post := range posts {
|
||||
post.User = userMap[post.UserID]
|
||||
post.Contents = contentMap[post.ID]
|
||||
}
|
||||
return posts, nil
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
package dao
|
||||
|
||||
import "github.com/rocboss/paopao-ce/internal/model"
|
||||
|
||||
func (d *dataServant) CreatePostContent(content *model.PostContent) (*model.PostContent, error) {
|
||||
return content.Create(d.engine)
|
||||
}
|
||||
|
||||
func (d *dataServant) GetPostContentsByIDs(ids []int64) ([]*model.PostContent, error) {
|
||||
return (&model.PostContent{}).List(d.engine, &model.ConditionsT{
|
||||
"post_id IN ?": ids,
|
||||
"ORDER": "sort ASC",
|
||||
}, 0, 0)
|
||||
}
|
||||
|
||||
func (d *dataServant) GetPostContentByID(id int64) (*model.PostContent, error) {
|
||||
return (&model.PostContent{
|
||||
Model: &model.Model{
|
||||
ID: id,
|
||||
},
|
||||
}).Get(d.engine)
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
// Core service implement base sqlx+mysql. All sub-service
|
||||
// will declare here and provide initial function.
|
||||
|
||||
package sakila
|
||||
|
||||
import (
|
||||
"github.com/rocboss/paopao-ce/internal/core"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func NewDataService() (core.DataService, core.VersionInfo) {
|
||||
logrus.Fatal("not support now")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func NewAuthorizationManageService() core.AuthorizationManageService {
|
||||
logrus.Fatal("not support now")
|
||||
return nil
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"github.com/meilisearch/meilisearch-go"
|
||||
"github.com/rocboss/paopao-ce/internal/conf"
|
||||
"github.com/rocboss/paopao-ce/internal/core"
|
||||
"github.com/rocboss/paopao-ce/pkg/zinc"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var (
|
||||
_ core.TweetSearchService = (*zincTweetSearchServant)(nil)
|
||||
_ core.TweetSearchService = (*bridgeTweetSearchServant)(nil)
|
||||
)
|
||||
|
||||
type documents struct {
|
||||
primaryKey []string
|
||||
docItems core.DocItems
|
||||
identifiers []string
|
||||
}
|
||||
|
||||
type bridgeTweetSearchServant struct {
|
||||
ts core.TweetSearchService
|
||||
updateDocsCh chan *documents
|
||||
}
|
||||
|
||||
type tweetSearchFilter struct {
|
||||
ams core.AuthorizationManageService
|
||||
}
|
||||
|
||||
type zincTweetSearchServant struct {
|
||||
tweetSearchFilter
|
||||
|
||||
indexName string
|
||||
client *zinc.ZincClient
|
||||
publicFilter string
|
||||
privateFilter string
|
||||
friendFilter string
|
||||
}
|
||||
|
||||
type meiliTweetSearchServant struct {
|
||||
tweetSearchFilter
|
||||
|
||||
client *meilisearch.Client
|
||||
index *meilisearch.Index
|
||||
publicFilter string
|
||||
privateFilter string
|
||||
friendFilter string
|
||||
}
|
||||
|
||||
func NewTweetSearchService() core.TweetSearchService {
|
||||
bts := &bridgeTweetSearchServant{}
|
||||
|
||||
capacity := conf.TweetSearchSetting.MaxUpdateQPS
|
||||
if capacity < 10 {
|
||||
capacity = 10
|
||||
} else if capacity > 10000 {
|
||||
capacity = 10000
|
||||
}
|
||||
bts.updateDocsCh = make(chan *documents, capacity)
|
||||
|
||||
var v versionInfo
|
||||
if conf.CfgIf("Zinc") {
|
||||
bts.ts, v = newZincTweetSearchServant()
|
||||
} else if conf.CfgIf("Meili") {
|
||||
bts.ts, v = newMeiliTweetSearchServant()
|
||||
} else {
|
||||
// default use Zinc as tweet search service
|
||||
bts.ts, v = newZincTweetSearchServant()
|
||||
}
|
||||
logrus.Infof("use %s as tweet search serice by version %s", v.name(), v.version())
|
||||
|
||||
numWorker := conf.TweetSearchSetting.MinWorker
|
||||
if numWorker < 5 {
|
||||
numWorker = 5
|
||||
} else if numWorker > 1000 {
|
||||
numWorker = 1000
|
||||
}
|
||||
logrus.Debugf("use %d backend worker to update documents to search engine", numWorker)
|
||||
// 启动文档更新器
|
||||
for ; numWorker > 0; numWorker-- {
|
||||
go bts.startUpdateDocs()
|
||||
}
|
||||
|
||||
return bts
|
||||
}
|
@ -1,58 +1,36 @@
|
||||
package dao
|
||||
package search
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/Masterminds/semver/v3"
|
||||
"github.com/meilisearch/meilisearch-go"
|
||||
"github.com/rocboss/paopao-ce/internal/conf"
|
||||
"github.com/rocboss/paopao-ce/internal/core"
|
||||
"github.com/rocboss/paopao-ce/internal/model"
|
||||
"github.com/rocboss/paopao-ce/pkg/json"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func newMeiliTweetSearchServant() (*meiliTweetSearchServant, versionInfo) {
|
||||
s := conf.MeiliSetting
|
||||
client := meilisearch.NewClient(meilisearch.ClientConfig{
|
||||
Host: s.Endpoint(),
|
||||
APIKey: s.ApiKey,
|
||||
})
|
||||
|
||||
if _, err := client.Index(s.Index).FetchInfo(); err != nil {
|
||||
logrus.Debugf("create index because fetch index info error: %v", err)
|
||||
client.CreateIndex(&meilisearch.IndexConfig{
|
||||
Uid: s.Index,
|
||||
PrimaryKey: "id",
|
||||
})
|
||||
searchableAttributes := []string{"content", "tags"}
|
||||
sortableAttributes := []string{"is_top", "latest_replied_on"}
|
||||
filterableAttributes := []string{"tags", "visibility", "user_id"}
|
||||
|
||||
index := client.Index(s.Index)
|
||||
index.UpdateSearchableAttributes(&searchableAttributes)
|
||||
index.UpdateSortableAttributes(&sortableAttributes)
|
||||
index.UpdateFilterableAttributes(&filterableAttributes)
|
||||
}
|
||||
|
||||
obj := &meiliTweetSearchServant{
|
||||
tweetSearchFilter: tweetSearchFilter{
|
||||
ams: newAuthorizationManageService(),
|
||||
},
|
||||
client: client,
|
||||
index: client.Index(s.Index),
|
||||
publicFilter: fmt.Sprintf("visibility=%d", model.PostVisitPublic),
|
||||
privateFilter: fmt.Sprintf("visibility=%d AND user_id=", model.PostVisitPrivate),
|
||||
friendFilter: fmt.Sprintf("visibility=%d", model.PostVisitFriend),
|
||||
}
|
||||
return obj, obj
|
||||
var (
|
||||
_ core.TweetSearchService = (*meiliTweetSearchServant)(nil)
|
||||
_ core.VersionInfo = (*meiliTweetSearchServant)(nil)
|
||||
)
|
||||
|
||||
type meiliTweetSearchServant struct {
|
||||
tweetSearchFilter
|
||||
|
||||
client *meilisearch.Client
|
||||
index *meilisearch.Index
|
||||
publicFilter string
|
||||
privateFilter string
|
||||
friendFilter string
|
||||
}
|
||||
|
||||
func (s *meiliTweetSearchServant) name() string {
|
||||
func (s *meiliTweetSearchServant) Name() string {
|
||||
return "Meili"
|
||||
}
|
||||
|
||||
func (s *meiliTweetSearchServant) version() *semver.Version {
|
||||
func (s *meiliTweetSearchServant) Version() *semver.Version {
|
||||
return semver.MustParse("v0.2.0")
|
||||
}
|
||||
|
@ -0,0 +1,92 @@
|
||||
package search
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/meilisearch/meilisearch-go"
|
||||
"github.com/rocboss/paopao-ce/internal/conf"
|
||||
"github.com/rocboss/paopao-ce/internal/core"
|
||||
"github.com/rocboss/paopao-ce/internal/model"
|
||||
"github.com/rocboss/paopao-ce/pkg/zinc"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func NewMeiliTweetSearchService(ams core.AuthorizationManageService) (core.TweetSearchService, core.VersionInfo) {
|
||||
s := conf.MeiliSetting
|
||||
client := meilisearch.NewClient(meilisearch.ClientConfig{
|
||||
Host: s.Endpoint(),
|
||||
APIKey: s.ApiKey,
|
||||
})
|
||||
|
||||
if _, err := client.Index(s.Index).FetchInfo(); err != nil {
|
||||
logrus.Debugf("create index because fetch index info error: %v", err)
|
||||
client.CreateIndex(&meilisearch.IndexConfig{
|
||||
Uid: s.Index,
|
||||
PrimaryKey: "id",
|
||||
})
|
||||
searchableAttributes := []string{"content", "tags"}
|
||||
sortableAttributes := []string{"is_top", "latest_replied_on"}
|
||||
filterableAttributes := []string{"tags", "visibility", "user_id"}
|
||||
|
||||
index := client.Index(s.Index)
|
||||
index.UpdateSearchableAttributes(&searchableAttributes)
|
||||
index.UpdateSortableAttributes(&sortableAttributes)
|
||||
index.UpdateFilterableAttributes(&filterableAttributes)
|
||||
}
|
||||
|
||||
mts := &meiliTweetSearchServant{
|
||||
tweetSearchFilter: tweetSearchFilter{
|
||||
ams: ams,
|
||||
},
|
||||
client: client,
|
||||
index: client.Index(s.Index),
|
||||
publicFilter: fmt.Sprintf("visibility=%d", model.PostVisitPublic),
|
||||
privateFilter: fmt.Sprintf("visibility=%d AND user_id=", model.PostVisitPrivate),
|
||||
friendFilter: fmt.Sprintf("visibility=%d", model.PostVisitFriend),
|
||||
}
|
||||
return mts, mts
|
||||
}
|
||||
|
||||
func NewZincTweetSearchService(ams core.AuthorizationManageService) (core.TweetSearchService, core.VersionInfo) {
|
||||
s := conf.ZincSetting
|
||||
zts := &zincTweetSearchServant{
|
||||
tweetSearchFilter: tweetSearchFilter{
|
||||
ams: ams,
|
||||
},
|
||||
indexName: s.Index,
|
||||
client: zinc.NewClient(s),
|
||||
publicFilter: fmt.Sprintf("visibility:%d", model.PostVisitPublic),
|
||||
privateFilter: fmt.Sprintf("visibility:%d AND user_id:%%d", model.PostVisitPrivate),
|
||||
friendFilter: fmt.Sprintf("visibility:%d", model.PostVisitFriend),
|
||||
}
|
||||
zts.createIndex()
|
||||
|
||||
return zts, zts
|
||||
}
|
||||
|
||||
func NewBridgeTweetSearchService(ts core.TweetSearchService) core.TweetSearchService {
|
||||
capacity := conf.TweetSearchSetting.MaxUpdateQPS
|
||||
if capacity < 10 {
|
||||
capacity = 10
|
||||
} else if capacity > 10000 {
|
||||
capacity = 10000
|
||||
}
|
||||
bts := &bridgeTweetSearchServant{
|
||||
ts: ts,
|
||||
updateDocsCh: make(chan *documents, capacity),
|
||||
}
|
||||
|
||||
numWorker := conf.TweetSearchSetting.MinWorker
|
||||
if numWorker < 5 {
|
||||
numWorker = 5
|
||||
} else if numWorker > 1000 {
|
||||
numWorker = 1000
|
||||
}
|
||||
logrus.Debugf("use %d backend worker to update documents to search engine", numWorker)
|
||||
// 启动文档更新器
|
||||
for ; numWorker > 0; numWorker-- {
|
||||
go bts.startUpdateDocs()
|
||||
}
|
||||
|
||||
return bts
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package security
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/rocboss/paopao-ce/internal/conf"
|
||||
"github.com/rocboss/paopao-ce/internal/core"
|
||||
)
|
||||
|
||||
type attachmentCheckServant struct {
|
||||
domain string
|
||||
}
|
||||
|
||||
func (s *attachmentCheckServant) CheckAttachment(uri string) error {
|
||||
if strings.Index(uri, s.domain) != 0 {
|
||||
return fmt.Errorf("附件非本站资源")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewAttachmentCheckService() core.AttachmentCheckService {
|
||||
return &attachmentCheckServant{
|
||||
domain: conf.GetOssDomain(),
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
// Core service implement base sqlx+postgresql. All sub-service
|
||||
// will declare here and provide initial function.
|
||||
|
||||
package slonik
|
||||
|
||||
import (
|
||||
"github.com/rocboss/paopao-ce/internal/core"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func NewDataService() (core.DataService, core.VersionInfo) {
|
||||
logrus.Fatal("not support now")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func NewAuthorizationManageService() core.AuthorizationManageService {
|
||||
logrus.Fatal("not support now")
|
||||
return nil
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/aliyun/aliyun-oss-go-sdk/oss"
|
||||
"github.com/minio/minio-go/v7"
|
||||
"github.com/minio/minio-go/v7/pkg/credentials"
|
||||
"github.com/rocboss/paopao-ce/internal/conf"
|
||||
"github.com/rocboss/paopao-ce/internal/core"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func NewAliossService() (core.ObjectStorageService, core.VersionInfo) {
|
||||
client, err := oss.New(conf.AliOSSSetting.Endpoint, conf.AliOSSSetting.AccessKeyID, conf.AliOSSSetting.AccessKeySecret)
|
||||
if err != nil {
|
||||
logrus.Fatalf("alioss.New err: %v", err)
|
||||
}
|
||||
|
||||
bucket, err := client.Bucket(conf.AliOSSSetting.Bucket)
|
||||
if err != nil {
|
||||
logrus.Fatalf("client.Bucket err: %v", err)
|
||||
}
|
||||
|
||||
obj := &aliossServant{
|
||||
bucket: bucket,
|
||||
domain: conf.GetOssDomain(),
|
||||
}
|
||||
return obj, obj
|
||||
}
|
||||
|
||||
func NewLocalossService() (core.ObjectStorageService, core.VersionInfo) {
|
||||
savePath, err := filepath.Abs(conf.LocalOSSSetting.SavePath)
|
||||
if err != nil {
|
||||
logrus.Fatalf("get localOSS save path err: %v", err)
|
||||
}
|
||||
|
||||
obj := &localossServant{
|
||||
savePath: savePath + "/" + conf.LocalOSSSetting.Bucket + "/",
|
||||
domain: conf.GetOssDomain(),
|
||||
}
|
||||
return obj, obj
|
||||
}
|
||||
|
||||
func NewMinioService() (core.ObjectStorageService, core.VersionInfo) {
|
||||
// Initialize minio client object.
|
||||
client, err := minio.New(conf.MinIOSetting.Endpoint, &minio.Options{
|
||||
Creds: credentials.NewStaticV4(conf.MinIOSetting.AccessKey, conf.MinIOSetting.SecretKey, ""),
|
||||
Secure: conf.MinIOSetting.Secure,
|
||||
})
|
||||
if err != nil {
|
||||
logrus.Fatalf("minio.New err: %v", err)
|
||||
}
|
||||
|
||||
ms := &minioServant{
|
||||
client: client,
|
||||
bucket: conf.MinIOSetting.Bucket,
|
||||
domain: conf.GetOssDomain(),
|
||||
}
|
||||
return ms, ms
|
||||
}
|
||||
|
||||
func NewS3Service() (core.ObjectStorageService, core.VersionInfo) {
|
||||
// Initialize s3 client object use minio-go.
|
||||
client, err := minio.New(conf.S3Setting.Endpoint, &minio.Options{
|
||||
Creds: credentials.NewStaticV4(conf.S3Setting.AccessKey, conf.S3Setting.SecretKey, ""),
|
||||
Secure: conf.S3Setting.Secure,
|
||||
})
|
||||
if err != nil {
|
||||
logrus.Fatalf("s3.New err: %v", err)
|
||||
}
|
||||
|
||||
obj := &s3Servant{
|
||||
client: client,
|
||||
bucket: conf.MinIOSetting.Bucket,
|
||||
domain: conf.GetOssDomain(),
|
||||
}
|
||||
return obj, obj
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"github.com/rocboss/paopao-ce/internal/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func (d *dataServant) CreateTag(tag *model.Tag) (*model.Tag, error) {
|
||||
return d.createTag(d.engine, tag)
|
||||
}
|
||||
|
||||
func (d *dataServant) DeleteTag(tag *model.Tag) error {
|
||||
return d.deleteTag(d.engine, tag)
|
||||
}
|
||||
|
||||
func (d *dataServant) GetTags(conditions *model.ConditionsT, offset, limit int) ([]*model.Tag, error) {
|
||||
return (&model.Tag{}).List(d.engine, conditions, offset, limit)
|
||||
}
|
||||
|
||||
func (d *dataServant) createTag(db *gorm.DB, tag *model.Tag) (*model.Tag, error) {
|
||||
t, err := tag.Get(d.engine)
|
||||
if err != nil {
|
||||
tag.QuoteNum = 1
|
||||
return tag.Create(db)
|
||||
}
|
||||
|
||||
// 更新
|
||||
t.QuoteNum++
|
||||
err = t.Update(db)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (d *dataServant) deleteTag(db *gorm.DB, tag *model.Tag) error {
|
||||
tag, err := tag.Get(db)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tag.QuoteNum--
|
||||
return tag.Update(db)
|
||||
}
|
@ -1,165 +0,0 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/rocboss/paopao-ce/internal/conf"
|
||||
"github.com/rocboss/paopao-ce/internal/model"
|
||||
"github.com/rocboss/paopao-ce/pkg/json"
|
||||
"gopkg.in/resty.v1"
|
||||
)
|
||||
|
||||
type JuhePhoneCaptchaRsp struct {
|
||||
ErrorCode int `json:"error_code"`
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
|
||||
// 根据用户ID获取用户
|
||||
func (d *dataServant) GetUserByID(id int64) (*model.User, error) {
|
||||
user := &model.User{
|
||||
Model: &model.Model{
|
||||
ID: id,
|
||||
},
|
||||
}
|
||||
|
||||
return user.Get(d.engine)
|
||||
}
|
||||
|
||||
// 根据用户名获取用户
|
||||
func (d *dataServant) GetUserByUsername(username string) (*model.User, error) {
|
||||
user := &model.User{
|
||||
Username: username,
|
||||
}
|
||||
|
||||
return user.Get(d.engine)
|
||||
}
|
||||
|
||||
// 根据手机号获取用户
|
||||
func (d *dataServant) GetUserByPhone(phone string) (*model.User, error) {
|
||||
user := &model.User{
|
||||
Phone: phone,
|
||||
}
|
||||
|
||||
return user.Get(d.engine)
|
||||
}
|
||||
|
||||
// 根据IDs获取用户列表
|
||||
func (d *dataServant) GetUsersByIDs(ids []int64) ([]*model.User, error) {
|
||||
user := &model.User{}
|
||||
|
||||
return user.List(d.engine, &model.ConditionsT{
|
||||
"id IN ?": ids,
|
||||
}, 0, 0)
|
||||
}
|
||||
|
||||
// 根据关键词模糊获取用户列表
|
||||
func (d *dataServant) GetUsersByKeyword(keyword string) ([]*model.User, error) {
|
||||
user := &model.User{}
|
||||
|
||||
keyword = strings.Trim(keyword, " ") + "%"
|
||||
if keyword == "%" {
|
||||
return user.List(d.engine, &model.ConditionsT{
|
||||
"ORDER": "id ASC",
|
||||
}, 0, 6)
|
||||
} else {
|
||||
return user.List(d.engine, &model.ConditionsT{
|
||||
"username LIKE ?": keyword,
|
||||
}, 0, 6)
|
||||
}
|
||||
}
|
||||
|
||||
// 根据关键词模糊获取用户列表
|
||||
func (d *dataServant) GetTagsByKeyword(keyword string) ([]*model.Tag, error) {
|
||||
tag := &model.Tag{}
|
||||
|
||||
keyword = "%" + strings.Trim(keyword, " ") + "%"
|
||||
if keyword == "%%" {
|
||||
return tag.List(d.engine, &model.ConditionsT{
|
||||
"ORDER": "quote_num DESC",
|
||||
}, 0, 6)
|
||||
} else {
|
||||
return tag.List(d.engine, &model.ConditionsT{
|
||||
"tag LIKE ?": keyword,
|
||||
"ORDER": "quote_num DESC",
|
||||
}, 0, 6)
|
||||
}
|
||||
}
|
||||
|
||||
// 创建用户
|
||||
func (d *dataServant) CreateUser(user *model.User) (*model.User, error) {
|
||||
return user.Create(d.engine)
|
||||
}
|
||||
|
||||
// 更新用户
|
||||
func (d *dataServant) UpdateUser(user *model.User) error {
|
||||
return user.Update(d.engine)
|
||||
}
|
||||
|
||||
// 获取最新短信验证码
|
||||
func (d *dataServant) GetLatestPhoneCaptcha(phone string) (*model.Captcha, error) {
|
||||
return (&model.Captcha{
|
||||
Phone: phone,
|
||||
}).Get(d.engine)
|
||||
}
|
||||
|
||||
// 更新短信验证码
|
||||
func (d *dataServant) UsePhoneCaptcha(captcha *model.Captcha) error {
|
||||
captcha.UseTimes++
|
||||
return captcha.Update(d.engine)
|
||||
}
|
||||
|
||||
// 发送短信验证码
|
||||
func (d *dataServant) SendPhoneCaptcha(phone string) error {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
captcha := rand.Intn(900000) + 100000
|
||||
m := 5
|
||||
|
||||
gateway := "https://v.juhe.cn/sms/send"
|
||||
|
||||
client := resty.New()
|
||||
client.DisableWarn = true
|
||||
resp, err := client.R().
|
||||
SetFormData(map[string]string{
|
||||
"mobile": phone,
|
||||
"tpl_id": conf.SmsJuheSetting.TplID,
|
||||
"tpl_value": fmt.Sprintf(conf.SmsJuheSetting.TplVal, captcha, m),
|
||||
"key": conf.SmsJuheSetting.Key,
|
||||
}).Post(gateway)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if resp.StatusCode() != http.StatusOK {
|
||||
return errors.New(resp.Status())
|
||||
}
|
||||
|
||||
result := &JuhePhoneCaptchaRsp{}
|
||||
err = json.Unmarshal(resp.Body(), result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if result.ErrorCode != 0 {
|
||||
return errors.New(result.Reason)
|
||||
}
|
||||
|
||||
// 写入表
|
||||
captchaModel := &model.Captcha{
|
||||
Phone: phone,
|
||||
Captcha: strconv.Itoa(captcha),
|
||||
ExpiredOn: time.Now().Add(time.Minute * time.Duration(m)).Unix(),
|
||||
}
|
||||
captchaModel.Create(d.engine)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *dataServant) IsFriend(_userID int64, _friendID int64) bool {
|
||||
// TODO: you are friend in all now
|
||||
return true
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"github.com/rocboss/paopao-ce/internal/conf"
|
||||
)
|
||||
|
||||
func getOssDomain() string {
|
||||
uri := "https://"
|
||||
if conf.CfgIf("AliOSS") {
|
||||
return uri + conf.AliOSSSetting.Domain + "/"
|
||||
} else if conf.CfgIf("MinIO") {
|
||||
if !conf.MinIOSetting.Secure {
|
||||
uri = "http://"
|
||||
}
|
||||
return uri + conf.MinIOSetting.Domain + "/" + conf.MinIOSetting.Bucket + "/"
|
||||
} else if conf.CfgIf("S3") {
|
||||
if !conf.S3Setting.Secure {
|
||||
uri = "http://"
|
||||
}
|
||||
// TODO: will not work well need test in real world
|
||||
return uri + conf.S3Setting.Domain + "/" + conf.S3Setting.Bucket + "/"
|
||||
} else if conf.CfgIf("LocalOSS") {
|
||||
if !conf.LocalOSSSetting.Secure {
|
||||
uri = "http://"
|
||||
}
|
||||
return uri + conf.LocalOSSSetting.Domain + "/oss/" + conf.LocalOSSSetting.Bucket + "/"
|
||||
}
|
||||
return uri + conf.AliOSSSetting.Domain + "/"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"github.com/Masterminds/semver/v3"
|
||||
)
|
||||
|
||||
// versionInfo 版本信息
|
||||
type versionInfo interface {
|
||||
name() string
|
||||
version() *semver.Version
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package rest
|
||||
|
||||
import "github.com/rocboss/paopao-ce/internal/model"
|
||||
|
||||
type IndexTweetsResp struct {
|
||||
Tweets []*model.PostFormated
|
||||
Total int64
|
||||
}
|
Loading…
Reference in new issue