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 commentRepository struct { restoreIDs bool comments *mgo.Collection } func newCommentRepository(db *mgo.Database, restoreIDs bool) (repositories.CommentRepository, error) { collection := db.C("story.comments") err := collection.EnsureIndexKey("chapterId") 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 } r := &commentRepository{ restoreIDs: restoreIDs, comments: collection, } go r.fixFieldTypo() return r, nil } func (r *commentRepository) Find(ctx context.Context, id string) (*models.Comment, error) { comment := new(models.Comment) err := r.comments.FindId(id).One(comment) if err != nil { return nil, err } return comment, nil } func (r *commentRepository) List(ctx context.Context, filter models.CommentFilter) ([]*models.Comment, error) { query := bson.M{} if filter.ChapterID != nil { query["chapterId"] = *filter.ChapterID } comments := make([]*models.Comment, 0, 32) err := r.comments.Find(query).Sort("createdDate").Limit(filter.Limit).All(&comments) if err != nil { if err == mgo.ErrNotFound { return comments, nil } return nil, err } return comments, nil } func (r *commentRepository) Insert(ctx context.Context, comment models.Comment) (*models.Comment, error) { if !r.restoreIDs { comment.ID = generate.CommentID() } else { if len(comment.ID) != len(generate.CommentID()) && strings.HasPrefix(comment.ID, "SSC") { return nil, errors.New("invalid story id") } } err := r.comments.Insert(comment) if err != nil { return nil, err } return &comment, nil } func (r *commentRepository) Update(ctx context.Context, comment models.Comment, update models.CommentUpdate) (*models.Comment, error) { updateBson := bson.M{} if update.Subject != nil { updateBson["subject"] = *update.Subject comment.Subject = *update.Subject } if update.Source != nil { updateBson["source"] = *update.Source comment.Source = *update.Source } if update.FictionalDate != nil { updateBson["fictionalDate"] = *update.FictionalDate comment.FictionalDate = *update.FictionalDate } if update.CharacterID != nil { updateBson["characterId"] = *update.CharacterID comment.CharacterID = *update.CharacterID } if update.CharacterName != nil { updateBson["characterName"] = *update.CharacterName comment.CharacterName = *update.CharacterName } err := r.comments.UpdateId(comment.ID, bson.M{"$set": updateBson}) if err != nil { return nil, err } return &comment, nil } func (r *commentRepository) Delete(ctx context.Context, comment models.Comment) error { return r.comments.RemoveId(comment.ID) } func (r *commentRepository) fixFieldTypo() { c, err := r.comments.UpdateAll(bson.M{ "editeddDate": bson.M{"$ne": nil}, }, bson.M{ "$rename": bson.M{"editeddDate": "editedDate"}, }) if err != nil { if err == mgo.ErrNotFound { return } log.Println("Failed to run name typo fix:", err) return } if c.Updated > 0 { log.Println("Fixed editeddDate field name typo in", c.Updated, "comments") } }