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.
146 lines
4.1 KiB
146 lines
4.1 KiB
package model
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"time"
|
|
|
|
"git.aiterp.net/AiteRP/aitestory/formparser"
|
|
"git.aiterp.net/gisle/wrouter/generate"
|
|
"github.com/microcosm-cc/bluemonday"
|
|
"github.com/russross/blackfriday"
|
|
)
|
|
|
|
// PageCategories are used by the view model and page to enforce
|
|
// a limited selection of categories. I may move it to a configuration
|
|
var PageCategories = []string{
|
|
"OoC",
|
|
"Story",
|
|
"Background",
|
|
"Document",
|
|
"News",
|
|
"Item",
|
|
"Info",
|
|
}
|
|
|
|
// PageTypes describes how the source is rendered. For now it's only markdown,
|
|
// but who knows what the future holds.
|
|
var PageTypes = []string{
|
|
"Markdown",
|
|
}
|
|
|
|
// PageMinDate is the earliest date possible. Stories from Matriarch Eriana's childhood
|
|
// are thus not going to happen.
|
|
var PageMinDate, _ = time.Parse(time.RFC3339, "1753-01-01T00:00:00Z")
|
|
|
|
// Page is the model describing the individual articles posted
|
|
// by users.
|
|
type Page 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"`
|
|
Dated bool `json:"dated"`
|
|
Published bool `json:"published"`
|
|
Unlisted bool `json:"unlisted"`
|
|
Specific bool `json:"specific"`
|
|
Indexed bool `json:"indexed"`
|
|
BackgroundURL string `json:"backgroundUrl"`
|
|
Type string `json:"type"`
|
|
Source string `json:"source"`
|
|
|
|
cachedOutput string
|
|
}
|
|
|
|
// Defaults fills in the default details for a page, suited for populating a form
|
|
func (page *Page) Defaults() {
|
|
page.Category = PageCategories[0]
|
|
|
|
page.Dated = true
|
|
page.Published = true
|
|
page.Unlisted = false
|
|
page.Specific = false
|
|
page.Indexed = true
|
|
|
|
page.BackgroundURL = ""
|
|
page.Type = PageTypes[0]
|
|
page.Source = ""
|
|
}
|
|
|
|
// Insert adds the page to the database
|
|
func (page *Page) Insert() error {
|
|
page.generateID()
|
|
|
|
return nil
|
|
}
|
|
|
|
// Content parses the content of the page
|
|
func (page *Page) Content() (string, error) {
|
|
if page.cachedOutput != "" {
|
|
return page.cachedOutput, nil
|
|
}
|
|
|
|
if page.Type == "Markdown" {
|
|
// TODO: Convert [[Ehanis Tioran]] to [Ehanis Tioran](https://wiki.aiterp.net/index.php?title=Ehanis%20Tioran)
|
|
|
|
unsafe := blackfriday.MarkdownCommon([]byte(page.Source))
|
|
page.cachedOutput = string(bluemonday.UGCPolicy().SanitizeBytes(unsafe))
|
|
|
|
return page.cachedOutput, nil
|
|
}
|
|
|
|
return "", fmt.Errorf("Page type '%s' is not supported", page.Type)
|
|
}
|
|
|
|
// ParseForm validates the values in a form and sets the page's values whenever possible regardless
|
|
// so that it can be pushed to the viewmodel to allow the user to correct their mistakes without fear
|
|
// of losing their hard work
|
|
func (page *Page) ParseForm(form url.Values) []error {
|
|
errors := make([]error, 0, 4)
|
|
page.cachedOutput = ""
|
|
|
|
err := formparser.Select(form.Get("category"), &page.Category, PageCategories, page.Category != "")
|
|
if err != nil {
|
|
errors = append(errors, fmt.Errorf("Category: %s", err))
|
|
}
|
|
|
|
err = formparser.Date(form.Get("fictionalDate"), &page.FictionalDate, !page.FictionalDate.IsZero())
|
|
if err != nil {
|
|
errors = append(errors, fmt.Errorf("Fictonal Date: %s", err))
|
|
}
|
|
|
|
page.Dated = form.Get("dated") != ""
|
|
page.Published = form.Get("published") != ""
|
|
page.Unlisted = form.Get("unlisted") != ""
|
|
page.Specific = form.Get("specific") != ""
|
|
page.Indexed = form.Get("indexed") != ""
|
|
|
|
err = formparser.String(form.Get("backgroundUrl"), &page.BackgroundURL, 0, 255)
|
|
if err != nil {
|
|
errors = append(errors, fmt.Errorf("Background URL: %s", err))
|
|
}
|
|
|
|
err = formparser.Select(form.Get("type"), &page.Type, PageTypes, page.Type != "")
|
|
if err != nil {
|
|
errors = append(errors, fmt.Errorf("Category: %s", err))
|
|
}
|
|
|
|
err = formparser.String(form.Get("source"), &page.Source, 0, 102400)
|
|
if err != nil {
|
|
errors = append(errors, fmt.Errorf("Content is too long, max: 100 KB (~17,000 words)"))
|
|
}
|
|
|
|
if len(errors) > 0 {
|
|
errors = nil
|
|
}
|
|
|
|
return errors
|
|
}
|
|
|
|
// Standardize page ID generation
|
|
func (page *Page) generateID() {
|
|
page.ID = generate.FriendlyID(16)
|
|
}
|