GraphQL API and utilities for the rpdata project
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

  1. package mongodb
  2. import (
  3. "context"
  4. "errors"
  5. "git.aiterp.net/rpdata/api/internal/generate"
  6. "git.aiterp.net/rpdata/api/models"
  7. "git.aiterp.net/rpdata/api/repositories"
  8. "github.com/globalsign/mgo"
  9. "github.com/globalsign/mgo/bson"
  10. "log"
  11. "strings"
  12. )
  13. type chapterRepository struct {
  14. restoreIDs bool
  15. chapters *mgo.Collection
  16. comments *mgo.Collection
  17. }
  18. func newChapterRepository(db *mgo.Database, restoreIDs bool) (repositories.ChapterRepository, error) {
  19. collection := db.C("story.chapters")
  20. err := collection.EnsureIndexKey("storyId")
  21. if err != nil {
  22. return nil, err
  23. }
  24. err = collection.EnsureIndexKey("author")
  25. if err != nil {
  26. return nil, err
  27. }
  28. err = collection.EnsureIndexKey("createdDate")
  29. if err != nil {
  30. return nil, err
  31. }
  32. return &chapterRepository{
  33. restoreIDs: restoreIDs,
  34. chapters: collection,
  35. comments: db.C("story.comments"),
  36. }, nil
  37. }
  38. func (r *chapterRepository) Find(ctx context.Context, id string) (*models.Chapter, error) {
  39. chapter := new(models.Chapter)
  40. err := r.chapters.FindId(id).One(chapter)
  41. if err != nil {
  42. return nil, err
  43. }
  44. return chapter, nil
  45. }
  46. func (r *chapterRepository) List(ctx context.Context, filter models.ChapterFilter) ([]*models.Chapter, error) {
  47. query := bson.M{}
  48. if filter.StoryID != nil {
  49. query["storyId"] = *filter.StoryID
  50. }
  51. chapters := make([]*models.Chapter, 0, 32)
  52. err := r.chapters.Find(query).Sort("createdDate").Limit(filter.Limit).All(&chapters)
  53. if err != nil {
  54. if err == mgo.ErrNotFound {
  55. return chapters, nil
  56. }
  57. return nil, err
  58. }
  59. return chapters, nil
  60. }
  61. func (r *chapterRepository) Insert(ctx context.Context, chapter models.Chapter) (*models.Chapter, error) {
  62. if !r.restoreIDs {
  63. chapter.ID = generate.ChapterID()
  64. } else {
  65. if len(chapter.ID) != len(generate.ChapterID()) && strings.HasPrefix(chapter.ID, "S") {
  66. return nil, errors.New("invalid story id")
  67. }
  68. }
  69. err := r.chapters.Insert(chapter)
  70. if err != nil {
  71. return nil, err
  72. }
  73. return &chapter, nil
  74. }
  75. func (r *chapterRepository) Update(ctx context.Context, chapter models.Chapter, update models.ChapterUpdate) (*models.Chapter, error) {
  76. updateBson := bson.M{}
  77. if update.Title != nil {
  78. updateBson["title"] = *update.Title
  79. chapter.Title = *update.Title
  80. }
  81. if update.Source != nil {
  82. updateBson["source"] = *update.Source
  83. chapter.Source = *update.Source
  84. }
  85. if update.FictionalDate != nil {
  86. updateBson["fictionalDate"] = *update.FictionalDate
  87. chapter.FictionalDate = *update.FictionalDate
  88. }
  89. if update.CommentMode != nil {
  90. updateBson["commentMode"] = *update.CommentMode
  91. chapter.CommentMode = *update.CommentMode
  92. }
  93. if update.CommentsLocked != nil {
  94. updateBson["commentsLocked"] = *update.CommentsLocked
  95. chapter.CommentsLocked = *update.CommentsLocked
  96. }
  97. err := r.chapters.UpdateId(chapter.ID, bson.M{"$set": updateBson})
  98. if err != nil {
  99. return nil, err
  100. }
  101. return &chapter, nil
  102. }
  103. func (r *chapterRepository) Move(ctx context.Context, chapter models.Chapter, from, to models.Story) (*models.Chapter, error) {
  104. err := r.chapters.UpdateId(chapter.ID, bson.M{"$set": bson.M{"storyId": to.ID}})
  105. if err != nil {
  106. return nil, err
  107. }
  108. chapter.StoryID = to.ID
  109. return &chapter, nil
  110. }
  111. func (r *chapterRepository) Delete(ctx context.Context, chapter models.Chapter) error {
  112. err := r.chapters.RemoveId(chapter.ID)
  113. if err != nil {
  114. return err
  115. }
  116. c, err := r.comments.RemoveAll(bson.M{"chapterId": chapter.ID})
  117. if err != nil {
  118. log.Println("Failed to remove comments:", err)
  119. return nil
  120. }
  121. log.Printf("Removed chapter %s (%d comments)", chapter.ID, c.Removed)
  122. return nil
  123. }