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.
111 lines
2.7 KiB
111 lines
2.7 KiB
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.Equal(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")
|
|
})
|
|
}
|