asgard.git

commit e5d54a64f23a829da75411f38316390a455b3beb

Author: Adam Evyčędo <git@apiote.xyz>

try XDG directories in sequence

 db.go | 32 +++++++++++++++++++++++++++++++-
 eostre.sh | 18 ++++++++++++++++--
 main.go | 44 +++++++++++++++++++++++++++++++++-----------
 mimir.go | 7 ++++---
 tyr.go | 5 +++--


diff --git a/db.go b/db.go
index b12efb681ea49bc271a60eb3b598c07f919fdca5..6434483dfd08745128726949c6d3d4de57e48c3c 100644
--- a/db.go
+++ b/db.go
@@ -3,6 +3,7 @@
 import (
 	"database/sql"
 	"fmt"
+	"os"
 	"path/filepath"
 	"strings"
 	"time"
@@ -65,7 +66,36 @@ 	}
 }
 
 func migrate(dbPath string) (*sql.DB, error) {
-	db, err := open(dbPath)
+	home, err := os.UserHomeDir()
+	if err != nil {
+		return nil, fmt.Errorf("while getting user home dir: %w", err)
+	}
+	possibleDbDirs := []string{
+		"/var/lib/asgard",
+		home + "/.local/state/asgard",
+		".",
+	}
+
+	if dbPath != "" {
+		possibleDbDirs = append([]string{filepath.Dir(dbPath)}, possibleDbDirs...)
+	}
+
+	finalDbPath := ""
+	for _, possibleDbDir := range possibleDbDirs {
+		dirInfo, err := os.Stat(possibleDbDir)
+		if err == nil && dirInfo.IsDir() {
+			if filepath.Dir(dbPath) == possibleDbDir && dbPath != "" {
+				finalDbPath = dbPath
+			} else {
+				finalDbPath = possibleDbDir + "/asgard.db"
+			}
+			break
+		}
+	}
+	if finalDbPath == "" {
+		return nil, fmt.Errorf("no suitable db directory found")
+	}
+	db, err := open(finalDbPath)
 	_, err = db.Exec(`create table tyr_knownAddresses(address_from text, address_to text, ban boolean, unique(address, direction))`)
 	if err != nil && err.Error() != "table tyr_knownAddresses already exists" {
 		return nil, err




diff --git a/eostre.sh b/eostre.sh
index 96b7791a2e906b58b1f38c7e8d38280c1a8ad359..02f1910cc343e0d319debe2e0ac1a542fb41e54d 100755
--- a/eostre.sh
+++ b/eostre.sh
@@ -1,6 +1,19 @@
 #!/bin/sh
 # NEEDS sed,grep,zip,unzip
 
+findTemplate() {
+	templateName=$1
+	for d in /usr/share/asgard/templates ~/.local/share/asgard/templates templates .
+	do
+		if stat "$d/$templateName" >/dev/null 2>&1
+		then
+			echo "$d/$templateName"
+			return
+		fi
+	done
+	return 1
+}
+
 set -e
 
 # shellcheck disable=SC2010
@@ -49,12 +62,13 @@ for year in $years
 do
 	manifest="$manifest\n\t\t<item href=\"Text/$year.xhtml\" id=\"$year.xhtml\" media-type=\"application/xhtml+xml\"/>"
 	spine="$spine\n\t\t<itemref idref=\"$year.xhtml\"/>"
-	cp templates/content.opf.template tmp/OEBPS/content.opf
+	
+	cp "$(findTemplate content.opf.template)" tmp/OEBPS/content.opf
 	sed -i "s|{{manifest}}|$manifest|" tmp/OEBPS/content.opf
 	sed -i "s|{{spine}}|$spine|" tmp/OEBPS/content.opf
 
 	toc="$toc\n\t\t<li><a href=\"$year.xhtml\">$year</a></li>"
-	cp templates/nav.xhtml.template tmp/OEBPS/Text/nav.xhtml
+	cp "$(findTemplate nav.xhtml.template)" tmp/OEBPS/Text/nav.xhtml
 	sed -i "s|{{toc}}|$toc|" tmp/OEBPS/Text/nav.xhtml
 done
 




diff --git a/main.go b/main.go
index 3b2acfbbdd9dd9369b7a7459b3bf6c5a1eb8be16..a76995e2dbf5b2811b1f4e49919e3d3b1b96d0ca 100644
--- a/main.go
+++ b/main.go
@@ -1,7 +1,9 @@
 package main
 
 import (
+	"embed"
 	"errors"
+	"fmt"
 	"log"
 	"net/http"
 	"os"
@@ -9,6 +11,9 @@
 	"apiote.xyz/p/go-dirty"
 	"git.sr.ht/~sircmpwn/getopt"
 )
+
+//go:embed templates
+var templatesFS embed.FS
 
 type TyrConfig struct {
 	ImapAddress          string
@@ -93,17 +98,34 @@ 	Gersemi GersemiConfig
 }
 
 func readConfig(configPath string) (Config, error) {
-	if configPath == "" {
-		// TODO try XDG_CONFIG/asgard.dirty, /etc/asgard.dirty, ~/.config/asgard.dirty
-		configPath = "asgard.dirty"
+	config := Config{}
+	userConfigDir, err := os.UserConfigDir()
+	if err != nil {
+		return config, fmt.Errorf("while getting user config dir: %w", err)
+	}
+	possibleConfigs := []string{
+		configPath,
+		"/etc/asgard.dirty",
+		userConfigDir + "/asgard.dirty",
+		"asgard.dirty",
 	}
-	file, err := os.Open(configPath)
+	finalConfigPath := ""
+	for _, possibleConfig := range possibleConfigs {
+		_, err := os.Stat(possibleConfig)
+		if err == nil {
+			finalConfigPath = possibleConfig
+			break
+		}
+	}
+	if finalConfigPath == "" {
+		return config, fmt.Errorf("no config found")
+	}
+	file, err := os.Open(finalConfigPath)
 	if err != nil {
 		log.Printf("error opening configuration %v\n", err)
-		return Config{}, err
+		return config, err
 	}
 	defer file.Close()
-	config := Config{}
 	err = dirty.LoadStruct(file, &config)
 	return config, err
 }
@@ -114,14 +136,14 @@ 		configPath string
 		dbPath     string
 	)
 	getopt.StringVar(&configPath, "c", "", "path to config file")
-	getopt.StringVar(&dbPath, "b", "asgard.db", "path to database file")
+	getopt.StringVar(&dbPath, "b", "", "path to database file")
 	getopt.Parse()
 
 	config, err := readConfig(configPath)
 	if err != nil {
 		log.Fatalln(err)
 	}
-	//log.Printf("running with conifig\n%+v\n", config)
+
 	db, err := migrate(dbPath)
 	if err != nil {
 		log.Fatalln(err)
@@ -205,9 +227,9 @@ 	case "gersemi":
 		log.Println(gersemi(config))
 
 	case "serve":
-		http.HandleFunc("/tyr", tyr_serve(db, config))
-		http.HandleFunc("/mimir", mimir_serve(db))
-		http.HandleFunc("/mimir/", mimir_serve(db))
+		http.HandleFunc("/tyr", tyr_serve(db, config, templatesFS))
+		http.HandleFunc("/mimir", mimir_serve(db, templatesFS))
+		http.HandleFunc("/mimir/", mimir_serve(db, templatesFS))
 		e := http.ListenAndServe(":8081", nil)
 		if e != nil {
 			log.Println(e)




diff --git a/mimir.go b/mimir.go
index 7c5bb051e45645c23da647bd493e2d9eb3cc3c65..61b7ad93687c58c4caa87cfabe9795b591a2fbd7 100644
--- a/mimir.go
+++ b/mimir.go
@@ -31,6 +31,7 @@
 import (
 	"bytes"
 	"database/sql"
+	"embed"
 	"errors"
 	"fmt"
 	"html/template"
@@ -274,7 +275,7 @@ 	m := am.(*MimirImapMessage)
 	return removeMessage(m.client(), m.message().Uid, m.mboxName)
 }
 
-func mimir_serve(db *sql.DB) func(w http.ResponseWriter, r *http.Request) {
+func mimir_serve(db *sql.DB, templatesFs embed.FS) func(w http.ResponseWriter, r *http.Request) {
 	// todo on back check with cache
 	return func(w http.ResponseWriter, r *http.Request) {
 		path := strings.Split(r.URL.Path[1:], "/")
@@ -297,7 +298,7 @@ 			if err != nil {
 				w.WriteHeader(http.StatusInternalServerError)
 				log.Println(err)
 			}
-			t, err := template.ParseFiles("templates/mimir_threads.html")
+			t, err := template.ParseFS(templatesFs, "templates/mimir_threads.html")
 			if err != nil {
 				w.WriteHeader(http.StatusInternalServerError)
 				log.Println(err)
@@ -322,7 +323,7 @@ 					log.Println(err)
 				}
 				return
 			}
-			t, err := template.ParseFiles("templates/mimir_message.html")
+			t, err := template.ParseFS(templatesFs, "templates/mimir_message.html")
 			if err != nil {
 				w.WriteHeader(http.StatusInternalServerError)
 				log.Println(err)




diff --git a/tyr.go b/tyr.go
index c4f2459c9bb2cf2ff20ee7044d21e7ecf9521bb6..f2f2e67f28cdf1c678645f1d0ed2be734018b043 100644
--- a/tyr.go
+++ b/tyr.go
@@ -4,6 +4,7 @@ import (
 	"bytes"
 	"crypto/sha256"
 	"database/sql"
+	"embed"
 	"fmt"
 	"html/template"
 	"io"
@@ -287,7 +288,7 @@ 	moveFromQuarantine(c, mbox, lock.address, dest)
 	return nil
 }
 
-func tyr_serve(db *sql.DB, config Config) func(w http.ResponseWriter, r *http.Request) {
+func tyr_serve(db *sql.DB, config Config, templatesFs embed.FS) func(w http.ResponseWriter, r *http.Request) {
 	return func(w http.ResponseWriter, r *http.Request) {
 		r.ParseForm()
 		formAddress := r.Form.Get("address")
@@ -300,7 +301,7 @@ 				Token:   formToken,
 				Captcha: "$696a04444feea781aeca9c546e220e0981aff4a8db0b2998decdf13265a95c31", // todo with salt and randomised time
 				Error:   formError,
 			}
-			t, _ := template.ParseFiles("templates/tyr.html")
+			t, _ := template.ParseFS(templatesFs, "templates/tyr.html")
 			b := bytes.NewBuffer([]byte{})
 			_ = t.Execute(b, tyrData)
 			io.Copy(w, b)