You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
147 lines
3.5 KiB
147 lines
3.5 KiB
package mongodb
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"git.aiterp.net/rpdata/api/internal/generate"
|
|
"git.aiterp.net/rpdata/api/models"
|
|
"git.aiterp.net/rpdata/api/repositories"
|
|
"github.com/globalsign/mgo"
|
|
"github.com/globalsign/mgo/bson"
|
|
"log"
|
|
"strings"
|
|
)
|
|
|
|
type chapterRepository struct {
|
|
restoreIDs bool
|
|
chapters *mgo.Collection
|
|
comments *mgo.Collection
|
|
}
|
|
|
|
func newChapterRepository(db *mgo.Database, restoreIDs bool) (repositories.ChapterRepository, error) {
|
|
collection := db.C("story.chapters")
|
|
|
|
err := collection.EnsureIndexKey("storyId")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = collection.EnsureIndexKey("author")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = collection.EnsureIndexKey("createdDate")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &chapterRepository{
|
|
restoreIDs: restoreIDs,
|
|
chapters: collection,
|
|
comments: db.C("story.comments"),
|
|
}, nil
|
|
}
|
|
|
|
func (r *chapterRepository) Find(ctx context.Context, id string) (*models.Chapter, error) {
|
|
chapter := new(models.Chapter)
|
|
err := r.chapters.FindId(id).One(chapter)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return chapter, nil
|
|
}
|
|
|
|
func (r *chapterRepository) List(ctx context.Context, filter models.ChapterFilter) ([]*models.Chapter, error) {
|
|
query := bson.M{}
|
|
if filter.StoryID != nil {
|
|
query["storyId"] = *filter.StoryID
|
|
}
|
|
|
|
chapters := make([]*models.Chapter, 0, 32)
|
|
err := r.chapters.Find(query).Sort("createdDate").Limit(filter.Limit).All(&chapters)
|
|
if err != nil {
|
|
if err == mgo.ErrNotFound {
|
|
return chapters, nil
|
|
}
|
|
|
|
return nil, err
|
|
}
|
|
|
|
return chapters, nil
|
|
}
|
|
|
|
func (r *chapterRepository) Insert(ctx context.Context, chapter models.Chapter) (*models.Chapter, error) {
|
|
if !r.restoreIDs {
|
|
chapter.ID = generate.ChapterID()
|
|
} else {
|
|
if len(chapter.ID) != len(generate.ChapterID()) && strings.HasPrefix(chapter.ID, "S") {
|
|
return nil, errors.New("invalid story id")
|
|
}
|
|
}
|
|
|
|
err := r.chapters.Insert(chapter)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &chapter, nil
|
|
}
|
|
|
|
func (r *chapterRepository) Update(ctx context.Context, chapter models.Chapter, update models.ChapterUpdate) (*models.Chapter, error) {
|
|
updateBson := bson.M{}
|
|
if update.Title != nil {
|
|
updateBson["title"] = *update.Title
|
|
chapter.Title = *update.Title
|
|
}
|
|
if update.Source != nil {
|
|
updateBson["source"] = *update.Source
|
|
chapter.Source = *update.Source
|
|
}
|
|
if update.FictionalDate != nil {
|
|
updateBson["fictionalDate"] = *update.FictionalDate
|
|
chapter.FictionalDate = *update.FictionalDate
|
|
}
|
|
if update.CommentMode != nil {
|
|
updateBson["commentMode"] = *update.CommentMode
|
|
chapter.CommentMode = *update.CommentMode
|
|
}
|
|
if update.CommentsLocked != nil {
|
|
updateBson["commentsLocked"] = *update.CommentsLocked
|
|
chapter.CommentsLocked = *update.CommentsLocked
|
|
}
|
|
|
|
err := r.chapters.UpdateId(chapter.ID, bson.M{"$set": updateBson})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &chapter, nil
|
|
}
|
|
|
|
func (r *chapterRepository) Move(ctx context.Context, chapter models.Chapter, from, to models.Story) (*models.Chapter, error) {
|
|
err := r.chapters.UpdateId(chapter.ID, bson.M{"$set": bson.M{"storyId": to.ID}})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
chapter.StoryID = to.ID
|
|
|
|
return &chapter, nil
|
|
}
|
|
|
|
func (r *chapterRepository) Delete(ctx context.Context, chapter models.Chapter) error {
|
|
err := r.chapters.RemoveId(chapter.ID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
c, err := r.comments.RemoveAll(bson.M{"chapterId": chapter.ID})
|
|
if err != nil {
|
|
log.Println("Failed to remove comments:", err)
|
|
return nil
|
|
}
|
|
|
|
log.Printf("Removed chapter %s (%d comments)", chapter.ID, c.Removed)
|
|
|
|
return nil
|
|
}
|