/models/posts.go

http://github.com/TheOnly92/bloody.go · Go · 266 lines · 233 code · 29 blank · 4 comment · 53 complexity · 78ccc9869e5ca18885e7cf52f9520304 MD5 · raw file

  1. package main
  2. import (
  3. "launchpad.net/gobson/bson"
  4. "launchpad.net/mgo"
  5. "time"
  6. "hash"
  7. "crypto/sha1"
  8. "encoding/hex"
  9. "math"
  10. "strconv"
  11. "github.com/russross/blackfriday"
  12. )
  13. type Post struct {
  14. Id bson.ObjectId "_id,omitempty"
  15. Title string
  16. Content string
  17. Created int64 "timestamp"
  18. Modified int64
  19. Status uint64
  20. Type uint
  21. Comments []Comment
  22. }
  23. type Comment struct {
  24. Id string
  25. Content string
  26. Author string
  27. Created int64
  28. }
  29. type PostModel struct {
  30. c mgo.Collection
  31. extensions int
  32. html_flags int
  33. }
  34. func PostModelInit() *PostModel {
  35. p := new(PostModel)
  36. p.c = mSession.DB(config.Get("mongodb")).C("posts")
  37. p.extensions |= blackfriday.EXTENSION_NO_INTRA_EMPHASIS
  38. p.extensions |= blackfriday.EXTENSION_TABLES
  39. p.extensions |= blackfriday.EXTENSION_FENCED_CODE
  40. p.extensions |= blackfriday.EXTENSION_AUTOLINK
  41. p.extensions |= blackfriday.EXTENSION_STRIKETHROUGH
  42. p.extensions |= blackfriday.EXTENSION_SPACE_HEADERS
  43. p.extensions |= blackfriday.EXTENSION_HARD_LINE_BREAK
  44. p.html_flags |= blackfriday.HTML_USE_XHTML
  45. p.html_flags |= blackfriday.HTML_USE_SMARTYPANTS
  46. p.html_flags |= blackfriday.HTML_SMARTYPANTS_FRACTIONS
  47. p.html_flags |= blackfriday.HTML_SMARTYPANTS_LATEX_DASHES
  48. return p
  49. }
  50. func (post *PostModel) FrontPage() []map[string]string {
  51. var result *Post
  52. results := []map[string]string{}
  53. posts, _ := strconv.Atoi(blogConfig.Get("postsPerPage"))
  54. err := post.c.Find(bson.M{"status":1}).Sort(bson.M{"timestamp":-1}).Limit(posts).For(&result, func() error {
  55. t := time.Unix(result.Created, 0)
  56. if result.Type == 1 {
  57. renderer := blackfriday.HtmlRenderer(post.html_flags,"","")
  58. result.Content = string(blackfriday.Markdown([]byte(result.Content), renderer, post.extensions))
  59. }
  60. results = append(results, map[string]string {"Title":result.Title, "Content":result.Content, "Date":t.Format(blogConfig.Get("dateFormat")), "Id": objectIdHex(result.Id.String())})
  61. return nil
  62. })
  63. if err != nil {
  64. panic(err)
  65. }
  66. return results
  67. }
  68. func (post *PostModel) RSS() []map[string]string {
  69. var result *Post
  70. results := []map[string]string{}
  71. err := post.c.Find(bson.M{"status":1}).Sort(bson.M{"timestamp":-1}).Limit(20).For(&result, func() error {
  72. t := time.Unix(result.Created, 0)
  73. if result.Type == 1 {
  74. renderer := blackfriday.HtmlRenderer(post.html_flags,"","")
  75. result.Content = string(blackfriday.Markdown([]byte(result.Content), renderer, post.extensions))
  76. }
  77. results = append(results, map[string]string {"Title":result.Title, "Content":result.Content, "Date":t.Format(time.RFC1123), "Id": objectIdHex(result.Id.String())})
  78. return nil
  79. })
  80. if err != nil {
  81. panic(err)
  82. }
  83. return results
  84. }
  85. func (post *PostModel) RenderPost(postId string) *Post {
  86. result := post.Get(postId)
  87. renderer := blackfriday.HtmlRenderer(post.html_flags,"","")
  88. if result.Type == 1 {
  89. result.Content = string(blackfriday.Markdown([]byte(result.Content), renderer, post.extensions))
  90. }
  91. // Also render all blog comments as markdown
  92. for i, v := range result.Comments {
  93. result.Comments[i].Content = string(blackfriday.Markdown([]byte(v.Content), renderer, post.extensions))
  94. }
  95. return result
  96. }
  97. func (post *PostModel) Get(postId string) *Post {
  98. var result *Post
  99. err := post.c.Find(bson.M{"_id": bson.ObjectIdHex(postId)}).One(&result)
  100. if err != nil {
  101. panic(err)
  102. }
  103. return result
  104. }
  105. func (post *PostModel) GetNextId(postId string) (string, bool) {
  106. var next *Post
  107. result := post.Get(postId)
  108. err := post.c.Find(bson.M{"status":1, "timestamp": bson.M{"$gt":result.Created}}).Sort(bson.M{"timestamp":1}).One(&next)
  109. if err != nil && err != mgo.NotFound {
  110. panic(err)
  111. }
  112. if err == mgo.NotFound {
  113. return "", false
  114. }
  115. return objectIdHex(next.Id.String()), true
  116. }
  117. func (post *PostModel) GetLastId(postId string) (string, bool) {
  118. var last *Post
  119. result := post.Get(postId)
  120. err := post.c.Find(bson.M{"status":1, "timestamp": bson.M{"$lt":result.Created}}).Sort(bson.M{"timestamp":-1}).One(&last)
  121. if err != nil && err != mgo.NotFound {
  122. panic(err)
  123. }
  124. if err == mgo.NotFound {
  125. return "", false
  126. }
  127. return objectIdHex(last.Id.String()), true
  128. }
  129. func (post *PostModel) TotalPages() int {
  130. total, err := post.c.Find(bson.M{"status":1}).Count()
  131. if err != nil {
  132. panic(err)
  133. }
  134. posts, _ := strconv.Atoi(blogConfig.Get("postsPerPage"))
  135. pages := float64(total) / float64(posts)
  136. return int(math.Ceil(pages))
  137. }
  138. func (post *PostModel) PostListing(page int) []map[string]string {
  139. var result *Post
  140. results := []map[string]string{}
  141. callback := func() error {
  142. t := time.Unix(result.Created, 0)
  143. p := map[string]string {"Title":result.Title, "Date":t.Format(blogConfig.Get("dateFormat")), "Id": objectIdHex(result.Id.String())}
  144. if (result.Status == 0) {
  145. p["Draft"] = "1"
  146. }
  147. results = append(results, p)
  148. return nil
  149. }
  150. var err error
  151. if page == 0 {
  152. err = post.c.Find(nil).Sort(bson.M{"timestamp":-1}).For(&result, callback)
  153. } else {
  154. posts, _ := strconv.Atoi(blogConfig.Get("postsPerPage"))
  155. err = post.c.Find(bson.M{"status":1}).Sort(bson.M{"timestamp":-1}).Skip(posts * (page - 1)).Limit(posts).For(&result, callback)
  156. }
  157. if err != nil {
  158. panic(err)
  159. }
  160. return results
  161. }
  162. func (post *PostModel) Create(title string, content string, status string, markdown uint) {
  163. t := time.Now()
  164. tmp, _ := strconv.ParseUint(status, 10, 64)
  165. err := post.c.Insert(&Post{"", title, content, t.Unix(), 0, tmp, markdown, make([]Comment,0)})
  166. if err != nil {
  167. panic(err)
  168. }
  169. }
  170. func (post *PostModel) InsertComment(postId string, content string, author string) {
  171. result := post.Get(postId)
  172. if author == "" {
  173. author = "Anonymous"
  174. }
  175. // Generate ID
  176. t := time.Now()
  177. var h hash.Hash = sha1.New()
  178. h.Write([]byte(author+strconv.FormatInt(t.Unix(),10)))
  179. id := hex.EncodeToString(h.Sum(nil))
  180. comment := Comment{id, content, author, t.Unix()}
  181. result.Comments = append(result.Comments, comment)
  182. err := post.c.Update(bson.M{"_id":bson.ObjectIdHex(postId)},result)
  183. if err != nil {
  184. panic(err)
  185. }
  186. }
  187. func (post *PostModel) DeleteComment(postId string, id string) {
  188. result := post.Get(postId)
  189. // Copy everything from the old one and skip those that we want to delete
  190. newComments := make([]Comment,0)
  191. for _, comment := range result.Comments {
  192. if comment.Id != id {
  193. newComments = append(newComments, comment)
  194. }
  195. }
  196. result.Comments = newComments
  197. // Save result
  198. err := post.c.Update(bson.M{"_id":bson.ObjectIdHex(postId)},result)
  199. if err != nil {
  200. panic(err)
  201. }
  202. }
  203. func (post *PostModel) Update(title string, content string, status string, postId string) {
  204. result := post.Get(postId)
  205. result.Title = title
  206. result.Content = content
  207. result.Modified = time.Now().Unix()
  208. result.Status, _ = strconv.ParseUint(status,0,64)
  209. err := post.c.Update(bson.M{"_id":bson.ObjectIdHex(postId)},result)
  210. if err != nil {
  211. panic(err)
  212. }
  213. }
  214. func (post *PostModel) Publish(postId string) {
  215. result := post.Get(postId)
  216. result.Status = 1
  217. err := post.c.Update(bson.M{"_id":bson.ObjectIdHex(postId)},result)
  218. if err != nil {
  219. panic(err)
  220. }
  221. }
  222. func (post *PostModel) Delete(postId string) {
  223. err := post.c.Remove(bson.M{"_id":bson.ObjectIdHex(postId)})
  224. if err != nil {
  225. panic(err)
  226. }
  227. }
  228. func (post *PostModel) DeleteBulk(postIds []string) {
  229. for _, v := range postIds {
  230. post.Delete(v)
  231. }
  232. }
  233. func (post *PostModel) PublishBulk(postIds []string) {
  234. for _, v := range postIds {
  235. post.Publish(v)
  236. }
  237. }