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.

210 lines
5.2 KiB

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