package story import ( "crypto/rand" "encoding/binary" "strconv" "time" "git.aiterp.net/rpdata/api/internal/store" "github.com/globalsign/mgo" "github.com/globalsign/mgo/bson" ) var chapterCollection *mgo.Collection // A Chapter is a part of a story. type Chapter struct { ID string `bson:"_id"` StoryID string `bson:"storyId"` Title string `bson:"title"` Author string `bson:"author"` Source string `bson:"source"` CreatedDate time.Time `bson:"createdDate"` FictionalDate time.Time `bson:"fictionalDate,omitempty"` EditedDate time.Time `bson:"editedDate"` } // Edit edits a chapter, and updates EditedDate. While many Edit functions cheat if there's nothing to // change, this functill will due to EditedDate. func (chapter *Chapter) Edit(title, source *string, fictionalDate *time.Time) error { now := time.Now() changes := bson.M{"editedDate": now} changed := *chapter changed.EditedDate = now if title != nil && *title != chapter.Title { changes["title"] = *title changed.Title = *title } if source != nil && *source != chapter.Source { changes["source"] = *source changed.Source = *source } if fictionalDate != nil && *fictionalDate != chapter.FictionalDate { changes["fictionalDate"] = *fictionalDate changed.FictionalDate = *fictionalDate } err := chapterCollection.UpdateId(chapter.ID, bson.M{"$set": changes}) if err != nil { return err } *chapter = changed return nil } // Remove removes a chapter. func (chapter *Chapter) Remove() error { return chapterCollection.RemoveId(chapter.ID) } // FindChapterID finds a chapter by its own ID func FindChapterID(id string) (Chapter, error) { chapter := Chapter{} err := chapterCollection.FindId(id).One(&chapter) return chapter, err } // ListChapterStoryID lists all chapters for the story ID func ListChapterStoryID(storyID string) ([]Chapter, error) { chapters := make([]Chapter, 0, 8) err := chapterCollection.Find(bson.M{"storyId": storyID}).Sort("createdDate").All(&chapters) if err != nil { return nil, err } return chapters, nil } // makeChapterID makes a random chapter ID that's 24 characters long func makeChapterID() string { result := "SC" offset := 0 data := make([]byte, 32) rand.Read(data) for len(result) < 24 { result += strconv.FormatUint(binary.LittleEndian.Uint64(data[offset:]), 36) offset += 8 if offset >= 32 { rand.Read(data) offset = 0 } } return result[:24] } func init() { store.HandleInit(func(db *mgo.Database) { chapterCollection = db.C("story.chapters") chapterCollection.EnsureIndexKey("storyId") chapterCollection.EnsureIndexKey("author") chapterCollection.EnsureIndexKey("createdDate") }) }