The backend for the AiteStory website
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.

230 lines
5.7 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  1. package model
  2. import (
  3. "database/sql"
  4. "errors"
  5. "time"
  6. "git.aiterp.net/AiteRP/aitestory/server"
  7. )
  8. // Header contains a subset of the page database
  9. // table needed for the front page. It's a read-only
  10. // model.
  11. type Header struct {
  12. ID string `json:"id"`
  13. Name string `json:"name"`
  14. Author string `json:"author"`
  15. Category string `json:"category"`
  16. FictionalDate time.Time `json:"fictionalDate"`
  17. PublishDate time.Time `json:"publishDate"`
  18. EditDate time.Time `json:"editDate"`
  19. PrimaryTag *Tag `json:"primaryTag"`
  20. }
  21. func (header *Header) Dated() bool {
  22. return !header.FictionalDate.IsZero()
  23. }
  24. // CategoryInfo gets information about the category
  25. func (header *Header) CategoryInfo() PageCategory {
  26. for _, category := range PageCategories {
  27. if category.Key == header.Category {
  28. return category
  29. }
  30. }
  31. return PageCategory{"Unknown", "Unknown", "?", ""}
  32. }
  33. // ListHeaders grabs all the general pages from
  34. // the database to list them
  35. func ListHeaders() ([]Header, error) {
  36. const query = `
  37. SELECT page.id,page.name,author,category,fictional_date,publish_date,edit_date,tag.id,tag.type,tag.name
  38. FROM page
  39. LEFT JOIN page_tag ON (page.id = page_tag.page_id AND page_tag.primary = true)
  40. LEFT JOIN tag ON (tag.id = page_tag.tag_id)
  41. WHERE page.specific=false AND page.published=true AND page.unlisted=false
  42. ORDER BY page.publish_date DESC
  43. `
  44. db := server.Main.DB
  45. rows, err := db.Query(query)
  46. if err != nil {
  47. return nil, err
  48. }
  49. defer rows.Close()
  50. results := make([]Header, 0, 64)
  51. header := Header{}
  52. for rows.Next() {
  53. err := parseHeader(&header, rows)
  54. if err != nil {
  55. return nil, err
  56. }
  57. results = append(results, header)
  58. }
  59. return results, nil
  60. }
  61. // ListHeadersByCategory grabs all the pages in the given category
  62. func ListHeadersByCategory(category string) ([]Header, error) {
  63. const query = `
  64. SELECT page.id,page.name,author,category,fictional_date,publish_date,edit_date,tag.id,tag.type,tag.name
  65. FROM page
  66. LEFT JOIN page_tag ON (page.id = page_tag.page_id AND page_tag.primary = true)
  67. LEFT JOIN tag ON (tag.id = page_tag.tag_id)
  68. WHERE page.specific=false AND page.published=true AND page.unlisted=false AND page.category = ?
  69. ORDER BY page.publish_date DESC
  70. `
  71. db := server.Main.DB
  72. rows, err := db.Query(query, category)
  73. if err != nil {
  74. return nil, err
  75. }
  76. defer rows.Close()
  77. results := make([]Header, 0, 64)
  78. header := Header{}
  79. for rows.Next() {
  80. err := parseHeader(&header, rows)
  81. if err != nil {
  82. return nil, err
  83. }
  84. results = append(results, header)
  85. }
  86. return results, nil
  87. }
  88. // ListHeadersByTag lists all headers that has the tag. Leave the category empty
  89. // to not filter by it
  90. func ListHeadersByTag(category string, tag *Tag) ([]Header, error) {
  91. const query1 = `
  92. SELECT page.id,page.name,page.author,page.category,page.fictional_date,page.publish_date,page.edit_date,tag.id,tag.type,tag.name
  93. FROM page_tag
  94. RIGHT JOIN page ON page.id = page_tag.page_id
  95. LEFT JOIN (page_tag AS pt2) ON (page.id = pt2.page_id AND pt2.primary = true)
  96. LEFT JOIN (tag AS tag) ON (tag.id = pt2.tag_id)
  97. WHERE page_tag.tag_id=? AND page.unlisted=false AND page.published=true
  98. ORDER BY page.publish_date DESC
  99. `
  100. const query2 = `
  101. SELECT page.id,page.name,page.author,page.category,page.fictional_date,page.publish_date,page.edit_date,tag.id,tag.type,tag.name
  102. FROM page_tag
  103. RIGHT JOIN page ON page.id = page_tag.page_id
  104. LEFT JOIN (page_tag AS pt2) ON (page.id = pt2.page_id AND pt2.primary = true)
  105. LEFT JOIN (tag AS tag) ON (tag.id = pt2.tag_id)
  106. WHERE page_tag.tag_id=? AND page.category=? AND page.unlisted=false AND page.published=true
  107. ORDER BY page.publish_date DESC
  108. `
  109. if tag == nil {
  110. return nil, errors.New("no tag")
  111. }
  112. db := server.Main.DB
  113. query := query1
  114. if category != "" {
  115. query = query2
  116. }
  117. rows, err := db.Query(query, tag.ID)
  118. if err != nil {
  119. return nil, err
  120. }
  121. defer rows.Close()
  122. results := make([]Header, 0, 64)
  123. header := Header{}
  124. for rows.Next() {
  125. err := parseHeader(&header, rows)
  126. if err != nil {
  127. return nil, err
  128. }
  129. results = append(results, header)
  130. }
  131. return results, nil
  132. }
  133. // ListHeadersByTags searches for the first tag, then filters the result based on the
  134. // others. There is room for improvement in this function, but I'll have to judge whether
  135. // there will be a need for that.
  136. func ListHeadersByTags(category string, tags []Tag) ([]Header, error) {
  137. if len(tags) == 0 {
  138. return nil, errors.New("no tags")
  139. }
  140. headers, err := ListHeadersByTag(category, &tags[0])
  141. if err != nil {
  142. return nil, err
  143. }
  144. if len(headers) == 0 {
  145. return headers, nil
  146. }
  147. for _, tag := range tags[1:] {
  148. headers2, err := ListHeadersByTag(category, &tag)
  149. if err != nil {
  150. return nil, err
  151. }
  152. results := make([]Header, 0, len(headers))
  153. for _, header := range headers {
  154. found := false
  155. for _, header2 := range headers2 {
  156. if header.ID == header2.ID {
  157. found = true
  158. break
  159. }
  160. }
  161. if found {
  162. results = append(results, header)
  163. }
  164. }
  165. headers = results
  166. }
  167. return headers, nil
  168. }
  169. func parseHeader(header *Header, rows *sql.Rows) error {
  170. var tagID, tagName, tagType string
  171. var fictionalDate, publishDate, editDate string
  172. var err error
  173. rows.Scan(&header.ID, &header.Name, &header.Author, &header.Category, &fictionalDate, &publishDate, &editDate, &tagID, &tagType, &tagName)
  174. if tagID != "" {
  175. header.PrimaryTag = &Tag{tagID, tagType, tagName}
  176. } else {
  177. header.PrimaryTag = nil
  178. }
  179. header.FictionalDate, err = time.Parse("2006-01-02 15:04:05", fictionalDate)
  180. if err != nil {
  181. header.FictionalDate = time.Time{}
  182. }
  183. header.PublishDate, err = time.Parse("2006-01-02 15:04:05", publishDate)
  184. if err != nil {
  185. return err
  186. }
  187. header.EditDate, err = time.Parse("2006-01-02 15:04:05", editDate)
  188. if err != nil {
  189. return err
  190. }
  191. return nil
  192. }