Store article content outside of DB and convert and serve on request from respective file
This commit is contained in:
parent
3f1b18c29f
commit
4663cedec5
@ -12,8 +12,10 @@ type Article struct {
|
|||||||
Title string
|
Title string
|
||||||
Created time.Time
|
Created time.Time
|
||||||
Description string
|
Description string
|
||||||
Content string
|
|
||||||
Link string
|
Link string
|
||||||
|
EncURL string
|
||||||
|
EncLength int
|
||||||
|
EncType string
|
||||||
Published bool
|
Published bool
|
||||||
Rejected bool
|
Rejected bool
|
||||||
ID int64
|
ID int64
|
||||||
@ -27,8 +29,8 @@ func (db *DB) AddArticle(a *Article) (int64, error) {
|
|||||||
selectQuery := "SELECT id FROM issues WHERE published = false"
|
selectQuery := "SELECT id FROM issues WHERE published = false"
|
||||||
insertQuery := `
|
insertQuery := `
|
||||||
INSERT INTO articles
|
INSERT INTO articles
|
||||||
(title, description, content, link, published, rejected, author_id, issue_id)
|
(title, description, link, enc_url, enc_length, enc_type, published, rejected, author_id, issue_id)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
`
|
`
|
||||||
|
|
||||||
for i := 0; i < TxMaxRetries; i++ {
|
for i := 0; i < TxMaxRetries; i++ {
|
||||||
@ -45,8 +47,8 @@ func (db *DB) AddArticle(a *Article) (int64, error) {
|
|||||||
return 0, fmt.Errorf("error getting issue ID when adding article to DB: %v", err)
|
return 0, fmt.Errorf("error getting issue ID when adding article to DB: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := tx.Exec(insertQuery, a.Title, a.Description,
|
result, err := tx.Exec(insertQuery, a.Title, a.Description, a.Link,
|
||||||
a.Content, a.Link, a.Published, a.Rejected, a.AuthorID, id)
|
a.EncURL, a.EncLength, a.EncType, a.Published, a.Rejected, a.AuthorID, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if rollbackErr := tx.Rollback(); rollbackErr != nil {
|
if rollbackErr := tx.Rollback(); rollbackErr != nil {
|
||||||
log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
|
log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
|
||||||
@ -80,7 +82,7 @@ func (db *DB) AddArticle(a *Article) (int64, error) {
|
|||||||
|
|
||||||
func (db *DB) GetArticle(id int64) (*Article, error) {
|
func (db *DB) GetArticle(id int64) (*Article, error) {
|
||||||
query := `
|
query := `
|
||||||
SELECT title, created, description, content, link, published, author_id
|
SELECT title, created, description, link, enc_url, enc_length, enc_type, published, author_id
|
||||||
FROM articles
|
FROM articles
|
||||||
WHERE id = ?
|
WHERE id = ?
|
||||||
`
|
`
|
||||||
@ -91,7 +93,8 @@ func (db *DB) GetArticle(id int64) (*Article, error) {
|
|||||||
var err error
|
var err error
|
||||||
|
|
||||||
if err := row.Scan(&article.Title, &created, &article.Description,
|
if err := row.Scan(&article.Title, &created, &article.Description,
|
||||||
&article.Content, &article.Link, &article.Published, &article.AuthorID); err != nil {
|
&article.Link, &article.EncURL, &article.EncLength, &article.EncType,
|
||||||
|
&article.Published, &article.AuthorID); err != nil {
|
||||||
return nil, fmt.Errorf("error scanning article row: %v", err)
|
return nil, fmt.Errorf("error scanning article row: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +109,7 @@ func (db *DB) GetArticle(id int64) (*Article, error) {
|
|||||||
|
|
||||||
func (db *DB) GetCertainArticles(published, rejected bool) ([]*Article, error) {
|
func (db *DB) GetCertainArticles(published, rejected bool) ([]*Article, error) {
|
||||||
query := `
|
query := `
|
||||||
SELECT id, title, created, description, content, link, author_id, issue_id
|
SELECT id, title, created, description, link, enc_url, enc_length, enc_type, author_id, issue_id
|
||||||
FROM articles
|
FROM articles
|
||||||
WHERE published = ?
|
WHERE published = ?
|
||||||
AND rejected = ?
|
AND rejected = ?
|
||||||
@ -122,8 +125,8 @@ func (db *DB) GetCertainArticles(published, rejected bool) ([]*Article, error) {
|
|||||||
var created []byte
|
var created []byte
|
||||||
|
|
||||||
if err = rows.Scan(&article.ID, &article.Title, &created,
|
if err = rows.Scan(&article.ID, &article.Title, &created,
|
||||||
&article.Description, &article.Content, &article.Link,
|
&article.Description, &article.Link, &article.EncURL, &article.EncLength,
|
||||||
&article.AuthorID, &article.IssueID); err != nil {
|
&article.EncType, &article.AuthorID, &article.IssueID); err != nil {
|
||||||
return nil, fmt.Errorf("error scanning article row: %v", err)
|
return nil, fmt.Errorf("error scanning article row: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +147,7 @@ func (db *DB) GetCurrentIssueArticles() ([]*Article, error) {
|
|||||||
txOptions := &sql.TxOptions{Isolation: sql.LevelSerializable}
|
txOptions := &sql.TxOptions{Isolation: sql.LevelSerializable}
|
||||||
issueQuery := "SELECT id FROM issues WHERE published = false"
|
issueQuery := "SELECT id FROM issues WHERE published = false"
|
||||||
articlesQuery := `
|
articlesQuery := `
|
||||||
SELECT id, title, created, description, content, link, author_id
|
SELECT id, title, created, description, link, enc_url, enc_length, enc_type, author_id
|
||||||
FROM articles
|
FROM articles
|
||||||
WHERE issue_id = ? AND published = true
|
WHERE issue_id = ? AND published = true
|
||||||
`
|
`
|
||||||
@ -178,7 +181,8 @@ func (db *DB) GetCurrentIssueArticles() ([]*Article, error) {
|
|||||||
var created []byte
|
var created []byte
|
||||||
|
|
||||||
if err = rows.Scan(&article.ID, &article.Title, &created,
|
if err = rows.Scan(&article.ID, &article.Title, &created,
|
||||||
&article.Description, &article.Content, &article.Link, &article.AuthorID); err != nil {
|
&article.Description, &article.Link, &article.EncURL, &article.EncLength,
|
||||||
|
&article.EncType, &article.AuthorID); err != nil {
|
||||||
if rollbackErr := tx.Rollback(); rollbackErr != nil {
|
if rollbackErr := tx.Rollback(); rollbackErr != nil {
|
||||||
log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
|
log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
|
||||||
}
|
}
|
||||||
|
@ -9,47 +9,6 @@ import (
|
|||||||
"git.streifling.com/jason/rss"
|
"git.streifling.com/jason/rss"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetChannel(db *DB, title, link, description string) (*rss.Channel, error) {
|
|
||||||
channel := &rss.Channel{
|
|
||||||
Title: title,
|
|
||||||
Link: link,
|
|
||||||
Description: description,
|
|
||||||
Items: make([]*rss.Item, 0),
|
|
||||||
}
|
|
||||||
|
|
||||||
articles, err := db.GetCertainArticles(true, false)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error fetching published articles: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, article := range articles {
|
|
||||||
tags, err := db.GetArticleTags(article.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error fetching tags for article %v: %v", article.Title, err)
|
|
||||||
}
|
|
||||||
tagNames := make([]string, 0)
|
|
||||||
for _, tag := range tags {
|
|
||||||
tagNames = append(tagNames, tag.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
user, err := db.GetUser(article.AuthorID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error finding user %v: %v", article.AuthorID, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
channel.Items = append(channel.Items, &rss.Item{
|
|
||||||
Title: article.Title,
|
|
||||||
Author: fmt.Sprint(user.FirstName, " ", user.LastName),
|
|
||||||
PubDate: article.Created.Format(time.RFC1123Z),
|
|
||||||
Description: article.Description,
|
|
||||||
Content: &rss.Content{Value: article.Content},
|
|
||||||
Categories: tagNames,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return channel, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GenerateRSS(c *Config, db *DB) (*string, error) {
|
func GenerateRSS(c *Config, db *DB) (*string, error) {
|
||||||
channel := &rss.Channel{
|
channel := &rss.Channel{
|
||||||
Title: c.Title,
|
Title: c.Title,
|
||||||
@ -93,15 +52,19 @@ func GenerateRSS(c *Config, db *DB) (*string, error) {
|
|||||||
Author: fmt.Sprint(user.FirstName, " ", user.LastName),
|
Author: fmt.Sprint(user.FirstName, " ", user.LastName),
|
||||||
Categories: tagNames,
|
Categories: tagNames,
|
||||||
Description: articleDescription,
|
Description: articleDescription,
|
||||||
|
Guid: string(article.ID),
|
||||||
|
Link: article.Link,
|
||||||
PubDate: article.Created.Format(time.RFC1123Z),
|
PubDate: article.Created.Format(time.RFC1123Z),
|
||||||
Title: articleTitle,
|
Title: articleTitle,
|
||||||
}
|
}
|
||||||
fmt.Println(article.Link, ": ", len(article.Link))
|
fmt.Println(article.Link, ": ", len(article.Link))
|
||||||
|
|
||||||
if article.Link == "" {
|
if article.Title == "Autogenerated cpolis Issue Article" {
|
||||||
item.Link = fmt.Sprint("http://", c.Domain, "/article/serve/", article.ID, ".html")
|
item.Enclosure = &rss.Enclosure{
|
||||||
} else {
|
Url: article.EncURL,
|
||||||
item.Link = article.Link
|
Lenght: article.EncLength,
|
||||||
|
Type: article.EncType,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
channel.Items = append(channel.Items, item)
|
channel.Items = append(channel.Items, item)
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
b "streifling.com/jason/cpolis/cmd/backend"
|
b "streifling.com/jason/cpolis/cmd/backend"
|
||||||
@ -30,6 +31,24 @@ func ServeArticle(c *b.Config, db *b.DB) http.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprint(w, article.Content)
|
if !article.Published {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
contentBytes, err := os.ReadFile(article.Link)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
content, err := b.ConvertToHTML(string(contentBytes))
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprint(w, content)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,6 @@ func SubmitArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc {
|
|||||||
article := &b.Article{
|
article := &b.Article{
|
||||||
Title: r.PostFormValue("article-title"),
|
Title: r.PostFormValue("article-title"),
|
||||||
Description: r.PostFormValue("article-description"),
|
Description: r.PostFormValue("article-description"),
|
||||||
Content: r.PostFormValue("article-content"),
|
|
||||||
Published: false,
|
Published: false,
|
||||||
Rejected: false,
|
Rejected: false,
|
||||||
AuthorID: session.Values["id"].(int64),
|
AuthorID: session.Values["id"].(int64),
|
||||||
@ -88,6 +87,20 @@ func SubmitArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
articleAbsName := fmt.Sprint(c.ArticleDir, "/", article.ID, ".md")
|
||||||
|
if err = os.WriteFile(articleAbsName, []byte(r.PostFormValue("article-content")), 0644); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
article.Link = fmt.Sprint("http://", c.Domain, c.Port, "/article/serve/", article.ID)
|
||||||
|
if err = db.UpdateAttributes(&b.Attribute{Table: "articles", ID: article.ID, AttName: "link", Value: article.Link}); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
r.ParseForm()
|
r.ParseForm()
|
||||||
tags := make([]int64, 0)
|
tags := make([]int64, 0)
|
||||||
for _, tag := range r.Form["tags"] {
|
for _, tag := range r.Form["tags"] {
|
||||||
@ -129,10 +142,16 @@ func ResubmitArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc {
|
|||||||
description := r.PostFormValue("article-description")
|
description := r.PostFormValue("article-description")
|
||||||
content := r.PostFormValue("article-content")
|
content := r.PostFormValue("article-content")
|
||||||
|
|
||||||
|
link := fmt.Sprint(c.ArticleDir, "/", id, ".md")
|
||||||
|
if err = os.WriteFile(link, []byte(content), 0644); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if err = db.UpdateAttributes(
|
if err = db.UpdateAttributes(
|
||||||
&b.Attribute{Table: "articles", ID: id, AttName: "title", Value: title},
|
&b.Attribute{Table: "articles", ID: id, AttName: "title", Value: title},
|
||||||
&b.Attribute{Table: "articles", ID: id, AttName: "description", Value: description},
|
&b.Attribute{Table: "articles", ID: id, AttName: "description", Value: description},
|
||||||
&b.Attribute{Table: "articles", ID: id, AttName: "content", Value: content},
|
|
||||||
&b.Attribute{Table: "articles", ID: id, AttName: "rejected", Value: false},
|
&b.Attribute{Table: "articles", ID: id, AttName: "rejected", Value: false},
|
||||||
); err != nil {
|
); err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
@ -260,7 +279,15 @@ func ReviewUnpublishedArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.Hand
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
content, err := b.ConvertToHTML(article.Content)
|
articleAbsName := fmt.Sprint(c.ArticleDir, "/", article.ID, ".md")
|
||||||
|
contentBytes, err := os.ReadFile(articleAbsName)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
content, err := b.ConvertToHTML(string(contentBytes))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
@ -290,6 +317,7 @@ func ReviewRejectedArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.Handler
|
|||||||
type htmlData struct {
|
type htmlData struct {
|
||||||
Selected map[int64]bool
|
Selected map[int64]bool
|
||||||
Article *b.Article
|
Article *b.Article
|
||||||
|
Content string
|
||||||
Tags []*b.Tag
|
Tags []*b.Tag
|
||||||
}
|
}
|
||||||
data := new(htmlData)
|
data := new(htmlData)
|
||||||
@ -308,6 +336,16 @@ func ReviewRejectedArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.Handler
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
articleAbsName := fmt.Sprint(c.ArticleDir, "/", data.Article.ID, ".md")
|
||||||
|
contentBytes, err := os.ReadFile(articleAbsName)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data.Content = string(contentBytes)
|
||||||
|
|
||||||
data.Tags, err = db.GetTagList()
|
data.Tags, err = db.GetTagList()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
@ -346,27 +384,6 @@ func PublishArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
article, err := db.GetArticle(id)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
content, err := b.ConvertToHTML(article.Content)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = os.WriteFile(fmt.Sprint(c.ArticleDir, "/", article.ID, ".html"), []byte(content), 0444)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = db.AddArticleToCurrentIssue(id); err != nil {
|
if err = db.AddArticleToCurrentIssue(id); err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
@ -555,7 +572,14 @@ func ReviewArticleForDeletion(c *b.Config, db *b.DB, s *b.CookieStore) http.Hand
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
content, err := b.ConvertToHTML(article.Content)
|
contentBytes, err := os.ReadFile(article.Link)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
content, err := b.ConvertToHTML(string(contentBytes))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
|
"mime"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -36,10 +37,32 @@ func PublishLatestIssue(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFun
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
imgFileName := session.Values["issue-image"].(string)
|
||||||
|
imgAbsName := fmt.Sprint(c.PicsDir, "/", imgFileName)
|
||||||
|
|
||||||
|
imgFile, err := os.Open(imgAbsName)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer imgFile.Close()
|
||||||
|
|
||||||
|
imgInfo, err := imgFile.Stat()
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
imgSize := imgInfo.Size()
|
||||||
|
mimeType := mime.TypeByExtension(filepath.Ext(imgAbsName))
|
||||||
|
|
||||||
article := &b.Article{
|
article := &b.Article{
|
||||||
Title: "Autogenerated Issue Article",
|
Title: "Autogenerated cpolis Issue Article",
|
||||||
Content: r.PostFormValue("issue-content"),
|
EncURL: fmt.Sprint("http://", c.Domain, c.Port, "/image/serve/", imgFileName),
|
||||||
Link: session.Values["issue-image"].(string),
|
EncLength: int(imgSize),
|
||||||
|
EncType: mimeType,
|
||||||
Published: true,
|
Published: true,
|
||||||
Rejected: false,
|
Rejected: false,
|
||||||
Created: time.Now(),
|
Created: time.Now(),
|
||||||
@ -47,20 +70,6 @@ func PublishLatestIssue(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFun
|
|||||||
}
|
}
|
||||||
fmt.Println(article.Link)
|
fmt.Println(article.Link)
|
||||||
|
|
||||||
content, err := b.ConvertToHTML(article.Content)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = os.WriteFile(fmt.Sprint(c.ArticleDir, "/", article.ID, ".html"), []byte(content), 0444)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
article.ID, err = db.AddArticle(article)
|
article.ID, err = db.AddArticle(article)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
@ -68,6 +77,26 @@ func PublishLatestIssue(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFun
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
articleAbsName := fmt.Sprint(c.ArticleDir, "/", article.ID, ".md")
|
||||||
|
if err = os.WriteFile(articleAbsName, []byte(r.PostFormValue("article-content")), 0644); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
article.Link = fmt.Sprint("http://", c.Domain, c.Port, "/article/serve/", article.ID)
|
||||||
|
if err = db.UpdateAttributes(&b.Attribute{Table: "articles", ID: article.ID, AttName: "link", Value: article.Link}); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = db.UpdateAttributes(&b.Attribute{Table: "articles", ID: article.ID, AttName: "link", Value: article.Link}); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if err = db.AddArticleToCurrentIssue(article.ID); err != nil {
|
if err = db.AddArticleToCurrentIssue(article.ID); err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
@ -26,6 +26,9 @@ CREATE TABLE articles (
|
|||||||
created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
description TEXT NOT NULL,
|
description TEXT NOT NULL,
|
||||||
link VARCHAR(255),
|
link VARCHAR(255),
|
||||||
|
enc_url VARCHAR(255),
|
||||||
|
enc_length INT,
|
||||||
|
enc_type VARCHAR(255),
|
||||||
published BOOL NOT NULL,
|
published BOOL NOT NULL,
|
||||||
rejected BOOL NOT NULL,
|
rejected BOOL NOT NULL,
|
||||||
author_id INT NOT NULL,
|
author_id INT NOT NULL,
|
||||||
|
2
go.mod
2
go.mod
@ -4,7 +4,7 @@ go 1.22.0
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
firebase.google.com/go/v4 v4.14.1
|
firebase.google.com/go/v4 v4.14.1
|
||||||
git.streifling.com/jason/rss v0.1.2
|
git.streifling.com/jason/rss v0.1.3
|
||||||
github.com/BurntSushi/toml v1.3.2
|
github.com/BurntSushi/toml v1.3.2
|
||||||
github.com/go-sql-driver/mysql v1.7.1
|
github.com/go-sql-driver/mysql v1.7.1
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
|
4
go.sum
4
go.sum
@ -15,8 +15,8 @@ cloud.google.com/go/storage v1.40.0 h1:VEpDQV5CJxFmJ6ueWNsKxcr1QAYOXEgxDa+sBbJah
|
|||||||
cloud.google.com/go/storage v1.40.0/go.mod h1:Rrj7/hKlG87BLqDJYtwR0fbPld8uJPbQ2ucUMY7Ir0g=
|
cloud.google.com/go/storage v1.40.0/go.mod h1:Rrj7/hKlG87BLqDJYtwR0fbPld8uJPbQ2ucUMY7Ir0g=
|
||||||
firebase.google.com/go/v4 v4.14.1 h1:4qiUETaFRWoFGE1XP5VbcEdtPX93Qs+8B/7KvP2825g=
|
firebase.google.com/go/v4 v4.14.1 h1:4qiUETaFRWoFGE1XP5VbcEdtPX93Qs+8B/7KvP2825g=
|
||||||
firebase.google.com/go/v4 v4.14.1/go.mod h1:fgk2XshgNDEKaioKco+AouiegSI9oTWVqRaBdTTGBoM=
|
firebase.google.com/go/v4 v4.14.1/go.mod h1:fgk2XshgNDEKaioKco+AouiegSI9oTWVqRaBdTTGBoM=
|
||||||
git.streifling.com/jason/rss v0.1.2 h1:UB3UHJXMt5WDDh9y8n0Z6nS1XortbPXjEr7QZTdovY4=
|
git.streifling.com/jason/rss v0.1.3 h1:fd3j4ZtcLehapcmmroo3AP3X34gRHC4xzpfV6bDV1ZU=
|
||||||
git.streifling.com/jason/rss v0.1.2/go.mod h1:gpZF0nZbQSstMpyHD9DTAvlQEG7v4pjO5c7aIMWM4Jg=
|
git.streifling.com/jason/rss v0.1.3/go.mod h1:gpZF0nZbQSstMpyHD9DTAvlQEG7v4pjO5c7aIMWM4Jg=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
<div class="flex flex-col gap-y-1">
|
<div class="flex flex-col gap-y-1">
|
||||||
<label for="easyMDE">Artikel</label>
|
<label for="easyMDE">Artikel</label>
|
||||||
<textarea id="easyMDE">{{.Article.Content}}</textarea>
|
<textarea id="easyMDE">{{.Content}}</textarea>
|
||||||
<input id="article-content" name="article-content" type="hidden" />
|
<input id="article-content" name="article-content" type="hidden" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user