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
230 lines
5.7 KiB
package model
|
|
|
|
import (
|
|
"database/sql"
|
|
"errors"
|
|
"time"
|
|
|
|
"git.aiterp.net/AiteRP/aitestory/server"
|
|
)
|
|
|
|
// Header contains a subset of the page database
|
|
// table needed for the front page. It's a read-only
|
|
// model.
|
|
type Header struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
Author string `json:"author"`
|
|
Category string `json:"category"`
|
|
FictionalDate time.Time `json:"fictionalDate"`
|
|
PublishDate time.Time `json:"publishDate"`
|
|
EditDate time.Time `json:"editDate"`
|
|
PrimaryTag *Tag `json:"primaryTag"`
|
|
}
|
|
|
|
func (header *Header) Dated() bool {
|
|
return !header.FictionalDate.IsZero()
|
|
}
|
|
|
|
// CategoryInfo gets information about the category
|
|
func (header *Header) CategoryInfo() PageCategory {
|
|
for _, category := range PageCategories {
|
|
if category.Key == header.Category {
|
|
return category
|
|
}
|
|
}
|
|
|
|
return PageCategory{"Unknown", "Unknown", "?", ""}
|
|
}
|
|
|
|
// ListHeaders grabs all the general pages from
|
|
// the database to list them
|
|
func ListHeaders() ([]Header, error) {
|
|
const query = `
|
|
SELECT page.id,page.name,author,category,fictional_date,publish_date,edit_date,tag.id,tag.type,tag.name
|
|
FROM page
|
|
LEFT JOIN page_tag ON (page.id = page_tag.page_id AND page_tag.primary = true)
|
|
LEFT JOIN tag ON (tag.id = page_tag.tag_id)
|
|
WHERE page.specific=false AND page.published=true AND page.unlisted=false
|
|
ORDER BY page.publish_date DESC
|
|
`
|
|
|
|
db := server.Main.DB
|
|
|
|
rows, err := db.Query(query)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
results := make([]Header, 0, 64)
|
|
header := Header{}
|
|
for rows.Next() {
|
|
err := parseHeader(&header, rows)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
results = append(results, header)
|
|
}
|
|
|
|
return results, nil
|
|
}
|
|
|
|
// ListHeadersByCategory grabs all the pages in the given category
|
|
func ListHeadersByCategory(category string) ([]Header, error) {
|
|
const query = `
|
|
SELECT page.id,page.name,author,category,fictional_date,publish_date,edit_date,tag.id,tag.type,tag.name
|
|
FROM page
|
|
LEFT JOIN page_tag ON (page.id = page_tag.page_id AND page_tag.primary = true)
|
|
LEFT JOIN tag ON (tag.id = page_tag.tag_id)
|
|
WHERE page.specific=false AND page.published=true AND page.unlisted=false AND page.category = ?
|
|
ORDER BY page.publish_date DESC
|
|
`
|
|
|
|
db := server.Main.DB
|
|
|
|
rows, err := db.Query(query, category)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
results := make([]Header, 0, 64)
|
|
header := Header{}
|
|
for rows.Next() {
|
|
err := parseHeader(&header, rows)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
results = append(results, header)
|
|
}
|
|
|
|
return results, nil
|
|
}
|
|
|
|
// ListHeadersByTag lists all headers that has the tag. Leave the category empty
|
|
// to not filter by it
|
|
func ListHeadersByTag(category string, tag *Tag) ([]Header, error) {
|
|
const query1 = `
|
|
SELECT page.id,page.name,page.author,page.category,page.fictional_date,page.publish_date,page.edit_date,tag.id,tag.type,tag.name
|
|
FROM page_tag
|
|
RIGHT JOIN page ON page.id = page_tag.page_id
|
|
LEFT JOIN (page_tag AS pt2) ON (page.id = pt2.page_id AND pt2.primary = true)
|
|
LEFT JOIN (tag AS tag) ON (tag.id = pt2.tag_id)
|
|
WHERE page_tag.tag_id=? AND page.unlisted=false AND page.published=true
|
|
ORDER BY page.publish_date DESC
|
|
`
|
|
const query2 = `
|
|
SELECT page.id,page.name,page.author,page.category,page.fictional_date,page.publish_date,page.edit_date,tag.id,tag.type,tag.name
|
|
FROM page_tag
|
|
RIGHT JOIN page ON page.id = page_tag.page_id
|
|
LEFT JOIN (page_tag AS pt2) ON (page.id = pt2.page_id AND pt2.primary = true)
|
|
LEFT JOIN (tag AS tag) ON (tag.id = pt2.tag_id)
|
|
WHERE page_tag.tag_id=? AND page.category=? AND page.unlisted=false AND page.published=true
|
|
ORDER BY page.publish_date DESC
|
|
`
|
|
|
|
if tag == nil {
|
|
return nil, errors.New("no tag")
|
|
}
|
|
|
|
db := server.Main.DB
|
|
|
|
query := query1
|
|
if category != "" {
|
|
query = query2
|
|
}
|
|
|
|
rows, err := db.Query(query, tag.ID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
results := make([]Header, 0, 64)
|
|
header := Header{}
|
|
for rows.Next() {
|
|
err := parseHeader(&header, rows)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
results = append(results, header)
|
|
}
|
|
|
|
return results, nil
|
|
}
|
|
|
|
// ListHeadersByTags searches for the first tag, then filters the result based on the
|
|
// others. There is room for improvement in this function, but I'll have to judge whether
|
|
// there will be a need for that.
|
|
func ListHeadersByTags(category string, tags []Tag) ([]Header, error) {
|
|
if len(tags) == 0 {
|
|
return nil, errors.New("no tags")
|
|
}
|
|
|
|
headers, err := ListHeadersByTag(category, &tags[0])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(headers) == 0 {
|
|
return headers, nil
|
|
}
|
|
|
|
for _, tag := range tags[1:] {
|
|
headers2, err := ListHeadersByTag(category, &tag)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
results := make([]Header, 0, len(headers))
|
|
for _, header := range headers {
|
|
found := false
|
|
for _, header2 := range headers2 {
|
|
if header.ID == header2.ID {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if found {
|
|
results = append(results, header)
|
|
}
|
|
}
|
|
|
|
headers = results
|
|
}
|
|
|
|
return headers, nil
|
|
}
|
|
|
|
func parseHeader(header *Header, rows *sql.Rows) error {
|
|
var tagID, tagName, tagType string
|
|
var fictionalDate, publishDate, editDate string
|
|
var err error
|
|
|
|
rows.Scan(&header.ID, &header.Name, &header.Author, &header.Category, &fictionalDate, &publishDate, &editDate, &tagID, &tagType, &tagName)
|
|
if tagID != "" {
|
|
header.PrimaryTag = &Tag{tagID, tagType, tagName}
|
|
} else {
|
|
header.PrimaryTag = nil
|
|
}
|
|
|
|
header.FictionalDate, err = time.Parse("2006-01-02 15:04:05", fictionalDate)
|
|
if err != nil {
|
|
header.FictionalDate = time.Time{}
|
|
}
|
|
header.PublishDate, err = time.Parse("2006-01-02 15:04:05", publishDate)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
header.EditDate, err = time.Parse("2006-01-02 15:04:05", editDate)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|