create web interface
This commit is contained in:
parent
e25999832c
commit
794e1ef668
|
@ -3,6 +3,7 @@ package main
|
|||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"git.32bit.cafe/yequari/rss-gen/rss"
|
||||
)
|
||||
|
@ -16,7 +17,10 @@ func main() {
|
|||
if *siteUrl == "" || *siteTitle == "" || *siteDesc == "" {
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
|
||||
fmt.Println(rss.GenerateRss(*siteUrl, *siteTitle, *siteDesc, flag.Args()...))
|
||||
feed, err := rss.GenerateRss(*siteUrl, *siteTitle, *siteDesc, flag.Args()...)
|
||||
if err != nil {
|
||||
os.Stderr.WriteString(err.Error())
|
||||
}
|
||||
fmt.Println(feed)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,38 @@
|
|||
package main
|
||||
|
||||
import "net/http"
|
||||
import (
|
||||
"html"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"git.32bit.cafe/yequari/rss-gen/rss"
|
||||
)
|
||||
|
||||
func (app *application) home(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
app.render(w, http.StatusOK, "home.tmpl.html", nil)
|
||||
}
|
||||
|
||||
func (app *application) generateRss(w http.ResponseWriter, r *http.Request) {
|
||||
q := r.URL.Query()
|
||||
siteName := q.Get("site-name")
|
||||
siteUrl := q.Get("site-url")
|
||||
siteDesc := q.Get("site-description")
|
||||
pageUrls := q.Get("page-urls")
|
||||
pages := strings.Split(pageUrls, "\n")
|
||||
for i := range pages {
|
||||
pages[i] = strings.TrimSpace(pages[i])
|
||||
}
|
||||
|
||||
feed, err := rss.GenerateRss(siteUrl, siteName, siteDesc, pages...)
|
||||
if err != nil {
|
||||
app.infoLog.Printf("Error generating feed: %s\n", err.Error())
|
||||
}
|
||||
for _, line := range strings.Split(feed, "\n") {
|
||||
w.Write([]byte(html.EscapeString(line) + "\n"))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (app *application) serverError(w http.ResponseWriter, err error) {
|
||||
trace := fmt.Sprintf("%s\n%s", err.Error(), debug.Stack())
|
||||
app.errorLog.Print(trace)
|
||||
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
func (app *application) clientError(w http.ResponseWriter, status int) {
|
||||
http.Error(w, http.StatusText(status), status)
|
||||
}
|
||||
|
||||
func (app *application) notFound(w http.ResponseWriter) {
|
||||
app.clientError(w, http.StatusNotFound)
|
||||
}
|
||||
|
||||
func (app *application) cleanUrl(url string) string {
|
||||
s := strings.TrimPrefix(url, "http://")
|
||||
s = strings.TrimPrefix(s, "https://")
|
||||
s = path.Base(path.Clean(s))
|
||||
s = "http://" + s
|
||||
return s
|
||||
}
|
||||
|
||||
func (app *application) render(w http.ResponseWriter, status int, page string, data *templateData) {
|
||||
ts, ok := app.templateCache[page]
|
||||
if !ok {
|
||||
err := fmt.Errorf("the template %s does not exist", page)
|
||||
app.serverError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// a buffer to attempt to write the template to
|
||||
// before writing it to the ResponseWriter w
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
err := ts.ExecuteTemplate(buf, "base", data)
|
||||
if err != nil {
|
||||
app.serverError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(status)
|
||||
|
||||
buf.WriteTo(w)
|
||||
}
|
|
@ -5,11 +5,13 @@ import (
|
|||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
type application struct {
|
||||
errorLog *log.Logger
|
||||
infoLog *log.Logger
|
||||
templateCache map[string]*template.Template
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
@ -20,9 +22,15 @@ func main() {
|
|||
infoLog := log.New(os.Stdout, "INFO\t", log.Ldate|log.Ltime)
|
||||
errorLog := log.New(os.Stderr, "ERROR\t", log.Ldate|log.Ltime|log.Lshortfile)
|
||||
|
||||
templateCache, err := newTemplateCache()
|
||||
if err != nil {
|
||||
errorLog.Fatal(err)
|
||||
}
|
||||
|
||||
app := &application {
|
||||
errorLog: errorLog,
|
||||
infoLog: infoLog,
|
||||
templateCache: templateCache,
|
||||
}
|
||||
|
||||
srv := &http.Server {
|
||||
|
@ -32,6 +40,6 @@ func main() {
|
|||
}
|
||||
|
||||
infoLog.Printf("Starting server on %s", *addr)
|
||||
err := srv.ListenAndServe()
|
||||
err = srv.ListenAndServe()
|
||||
errorLog.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
type templateData struct {
|
||||
}
|
||||
|
||||
func newTemplateCache() (map[string]*template.Template, error) {
|
||||
cache := map[string]*template.Template{}
|
||||
|
||||
pages, err := filepath.Glob("./ui/html/pages/*.tmpl.html")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, page := range pages {
|
||||
name := filepath.Base(page)
|
||||
|
||||
ts, err := template.ParseFiles("./ui/html/base.tmpl.html")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// parse all partials into the template set
|
||||
ts, err = ts.ParseGlob("./ui/html/partials/*.tmpl.html")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// parse the page template last
|
||||
ts, err = ts.ParseFiles(page)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cache[name] = ts
|
||||
}
|
||||
|
||||
return cache, nil
|
||||
}
|
|
@ -17,8 +17,7 @@ const feedfmt = `<?xml version="1.0" encoding="utf-8"?>
|
|||
<description>%s</description>
|
||||
%s
|
||||
</channel>
|
||||
</rss>
|
||||
`
|
||||
</rss>`
|
||||
|
||||
const itemfmt = `<item>
|
||||
<title>Content Title</title>
|
||||
|
@ -26,7 +25,7 @@ const itemfmt = `<item>
|
|||
<guid>%s</guid>
|
||||
<pubDate>%s</pubDate>
|
||||
<description><![CDATA[%s]]></description>
|
||||
</item>`;
|
||||
</item>`
|
||||
|
||||
func fetchPage(url string) (string, error) {
|
||||
resp, err := http.Get(url)
|
||||
|
@ -102,6 +101,7 @@ func GenerateRss(siteUrl, siteTitle, siteDesc string, pageUrls ...string) (strin
|
|||
var err error
|
||||
|
||||
for _, u := range pageUrls {
|
||||
var err error
|
||||
page, err := fetchPage(u)
|
||||
if err != nil {
|
||||
continue
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
{{define "base"}}
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="/static/css/main.css">
|
||||
<title>RSS Generator</title>
|
||||
<script src="/static/js/htmx.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
{{template "main" .}}
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
|
@ -0,0 +1,35 @@
|
|||
{{define "main"}}
|
||||
<h1>yequari's RSS Feed Generator</h1>
|
||||
<!--<form action="/generate" method="get" id="generate-form">-->
|
||||
<form id="generate-form">
|
||||
<p>
|
||||
<label>
|
||||
Site Name:
|
||||
<input name="site-name" />
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
<label>
|
||||
Site URL:
|
||||
<input name="site-url" />
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
<label>
|
||||
Site Description:
|
||||
<input name="site-description" />
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
<label>
|
||||
Pages to Include:
|
||||
<textarea name="page-urls" cols="40" rows="6">List of URLs, one per line</textarea>
|
||||
</label>
|
||||
</p>
|
||||
<button id="generate-button" hx-get="/generate" hx-include="#generate-form" hx-params="*" hx-target="#output">Generate</button>
|
||||
</form>
|
||||
<div class="output-container">
|
||||
<code id="output">
|
||||
</code>
|
||||
</div>
|
||||
{{end}}
|
|
@ -0,0 +1,3 @@
|
|||
#output {
|
||||
white-space: pre;
|
||||
}
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue