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.

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