startpage/main.go
2022-05-08 21:43:47 +02:00

139 lines
3.0 KiB
Go

package main
import (
"embed"
"errors"
"flag"
"fmt"
"html/template"
"io"
"net/http"
"net/url"
"strings"
_ "embed"
)
var (
intf = flag.String("i", "", "interface")
port = flag.Uint("p", 80, "port")
)
var (
//go:embed templates/*
TemplateFS embed.FS
//go:embed static/*
StaticFS embed.FS
Templates *template.Template
)
func main() {
flag.Parse()
ParseBookmarks()
if tmpl, err := template.New("homepage").ParseFS(TemplateFS, "templates/*"); err == nil {
Templates = tmpl
} else {
panic(err)
}
http.HandleFunc("/", handler)
http.HandleFunc("/search", search)
http.HandleFunc("/style.css", style)
http.HandleFunc("/icons.ttf", ProvideFile("static/icons.ttf", "font/ttf"))
http.HandleFunc("/transmission.png", ProvideFile("static/transmission.png", "image/png"))
http.HandleFunc("/pihole.svg", ProvideFile("static/pihole.svg", "image/svg+xml"))
http.HandleFunc("/gitea.png", ProvideFile("static/gitea.png", "image/png"))
if err := http.ListenAndServe(fmt.Sprintf("%s:%d", *intf, *port), nil); err != nil {
panic(err)
}
}
func handler(w http.ResponseWriter, r *http.Request) {
data := &TmplData{
text: GetText(r),
Bookmarks: Bookmarks,
Settings: DefaultSettings,
}
if err := Templates.ExecuteTemplate(w, "index.html", data); err != nil {
panic(err)
}
}
func style(w http.ResponseWriter, r *http.Request) {
file, err := TemplateFS.Open("templates/style.css")
if err != nil {
fmt.Println(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
defer file.Close()
w.Header().Add("Content-Type", "text/css")
if err := Templates.ExecuteTemplate(w, "style.css", DefaultSettings); err != nil {
panic(err)
}
}
func ProvideFile(path, contentType string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
file, err := StaticFS.Open(path)
if err != nil {
fmt.Println(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
defer file.Close()
w.Header().Add("Content-Type", contentType)
io.Copy(w, file)
}
}
func search(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil {
fmt.Println(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
query := r.Form.Get("query")
if uri, err := ParseURI(query); err == nil {
// url
w.Header().Add("Location", uri.String())
w.WriteHeader(http.StatusMovedPermanently)
} else {
// search string
w.Header().Add("Location", fmt.Sprintf("https://duckduckgo.com/?q=%s", query))
w.WriteHeader(http.StatusMovedPermanently)
}
}
func ParseURI(uri string) (*url.URL, error) {
if !strings.HasPrefix(uri, "http://") && !strings.HasPrefix(uri, "https://") {
uri = "https://" + uri
}
ret, err := url.ParseRequestURI(uri)
if err != nil {
return nil, err
}
splits := strings.Split(ret.Hostname(), ".")
if len(splits) <= 1 {
return nil, errors.New("hostname doesn't have a TLD")
}
if _, ok := TLDs[splits[len(splits)-1]]; !ok {
return nil, errors.New("invalid top level domain")
}
return ret, nil
}