aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rwxr-xr-xgen-initialize.sh6
-rw-r--r--initialize.sql34
-rw-r--r--main.go62
4 files changed, 101 insertions, 7 deletions
diff --git a/Makefile b/Makefile
index 9c5bc80..caefa2f 100644
--- a/Makefile
+++ b/Makefile
@@ -1,11 +1,13 @@
.POSIX:
.SUFFIXES:
-outputs = gallery public/mithril.js
+outputs = gallery initialize.go public/mithril.js
all: $(outputs)
-gallery: main.go
+gallery: main.go initialize.go
go build -o $@
+initialize.go: initialize.sql gen-initialize.sh
+ ./gen-initialize.sh initialize.sql > $@
public/mithril.js:
curl -Lo $@ https://unpkg.com/mithril/mithril.js
clean:
diff --git a/gen-initialize.sh b/gen-initialize.sh
new file mode 100755
index 0000000..8d8cb55
--- /dev/null
+++ b/gen-initialize.sh
@@ -0,0 +1,6 @@
+#!/bin/sh -e
+gofmt <<EOF
+package ${GOPACKAGE:-main}
+
+const initializeSQL = \`$(sed 's/`/` + "`" + `/g' "$@")\`
+EOF
diff --git a/initialize.sql b/initialize.sql
new file mode 100644
index 0000000..07d2969
--- /dev/null
+++ b/initialize.sql
@@ -0,0 +1,34 @@
+CREATE TABLE IF NOT EXISTS entry(
+ path TEXT NOT NULL, -- full FS directory path
+ basename TEXT NOT NULL, -- last FS path component
+ mtime INTEGER NOT NULL, -- Unix time of last modification in seconds
+ sha1 TEXT NOT NULL, -- SHA-1 hash of file in lowercase hexadecimal
+ PRIMARY KEY (path, basename)
+);
+
+CREATE INDEX IF NOT EXISTS entry_sha1 ON entry(sha1, path, basename);
+
+CREATE TABLE IF NOT EXISTS image(
+ sha1 TEXT NOT NULL REFERENCES entry(sha1),
+ thumbw INTEGER,
+ thumbh INTEGER,
+ dhash INTEGER, -- uint64 as a signed integer
+ PRIMARY KEY (sha1)
+);
+
+CREATE INDEX IF NOT EXISTS image_dhash ON image(dhash, sha1);
+
+CREATE TABLE IF NOT EXISTS image_tag(
+ sha1 TEXT NOT NULL REFERENCES entry(sha1),
+ tag TEXT NOT NULL,
+ PRIMARY KEY (sha1)
+);
+
+CREATE TABLE IF NOT EXISTS image_autotag(
+ sha1 TEXT NOT NULL REFERENCES entry(sha1),
+ tag TEXT NOT NULL,
+ weight REAL NOT NULL, -- 0..1 normalized weight assigned to tag
+ PRIMARY KEY (sha1, tag)
+);
+
+CREATE INDEX IF NOT EXISTS image_autotag_tag ON image_autotag(tag, sha1);
diff --git a/main.go b/main.go
index 240f245..b3a3019 100644
--- a/main.go
+++ b/main.go
@@ -3,11 +3,21 @@ package main
import (
"database/sql"
"log"
+ "net"
+ "net/http"
"os"
+ "path/filepath"
+ "time"
_ "github.com/mattn/go-sqlite3"
)
+// TODO: Perhaps maintain the DB, and the gallery directory, as globals.
+
+func openDB(gd string) (*sql.DB, error) {
+ return sql.Open("sqlite3", filepath.Join(gd, "gallery.db"))
+}
+
// init GD - initialize a "gallery directory" that contains gallery.sqlite,
// images, thumbs.
func cmdInit(args []string) {
@@ -16,19 +26,61 @@ func cmdInit(args []string) {
}
gd := args[0]
-
- db, err := sql.Open("sqlite3", gd+"/foo.db")
+ db, err := openDB(gd)
if err != nil {
log.Fatalln(err)
}
- // TODO: Figure out a go generate to create a Go file to create the db.
- _ = db
+ if _, err = db.Query(initializeSQL); err != nil {
+ log.Fatalln(err)
+ }
+ if err := os.MkdirAll(filepath.Join(gd, "images"), 0777); err != nil {
+ log.Fatalln(err)
+ }
+ if err := os.MkdirAll(filepath.Join(gd, "thumbs"), 0777); err != nil {
+ log.Fatalln(err)
+ }
}
// run GD ADDRESS - run a web UI against GD on ADDRESS
func cmdRun(args []string) {
- // TODO: Use "public" from CWD for files.
+ if len(args) != 2 {
+ log.Fatalln("usage: GD ADDRESS")
+ }
+
+ gd := args[0]
+ db, err := openDB(gd)
+ if err != nil {
+ log.Fatalln(err)
+ }
+
+ _ = db
+ address := args[1]
+
+ http.Handle("/", http.FileServer(http.Dir("public")))
+ // TODO: These subdirectories should be indirect
+ // (skip the hash subpath, don't require the .webp suffix).
+ http.Handle("/images",
+ http.FileServer(http.Dir(filepath.Join(gd, "images"))))
+ http.Handle("/thumbs",
+ http.FileServer(http.Dir(filepath.Join(gd, "thumbs"))))
+
+ host, port, err := net.SplitHostPort(address)
+ if err != nil {
+ log.Println(err)
+ } else if host == "" {
+ log.Println("http://" + net.JoinHostPort("localhost", port))
+ } else {
+ log.Println("http://" + address)
+ }
+
+ s := &http.Server{
+ Addr: address,
+ ReadTimeout: 60 * time.Second,
+ WriteTimeout: 60 * time.Second,
+ MaxHeaderBytes: 32 << 10,
+ }
+ log.Fatalln(s.ListenAndServe())
}
// import GD ROOT... - add files to the "entry" table