diff --git a/build-release.pl b/build-release.pl
index d6d4c26..b9a9a4c 100755
--- a/build-release.pl
+++ b/build-release.pl
@@ -3,11 +3,11 @@
use strict;
use warnings;
-open my $fh, "<", "dau.go" || die $!;
+open my $fh, "<", "config/config.go" || die $!;
my $version;
while (<$fh>) {
- $version = $1 if /^const\s+currentVersion.*?"([\d\.]+)"/;
+ $version = $1 if /^const\s+CurrentVersion.*?"([\d\.]+)"/;
}
close $fh;
diff --git a/config/config.go b/config/config.go
new file mode 100644
index 0000000..1e8e82a
--- /dev/null
+++ b/config/config.go
@@ -0,0 +1,13 @@
+package config
+
+// Config for the application
+var Config struct {
+ WebHookURL string
+ Path string
+ Watch int
+ Username string
+ NoWatermark bool
+ Exclude string
+}
+
+const CurrentVersion string = "0.6"
diff --git a/data/config.html b/data/config.html
new file mode 100644
index 0000000..fb7a0d0
--- /dev/null
+++ b/data/config.html
@@ -0,0 +1,8 @@
+
+
+ Config
+ Hey look it's DAU.
+
+ Learn more
+
+
diff --git a/data/dau.css b/data/dau.css
new file mode 100644
index 0000000..7c6d33c
--- /dev/null
+++ b/data/dau.css
@@ -0,0 +1,106 @@
+/*
+ * Globals
+ */
+
+/* Links */
+a,
+a:focus,
+a:hover {
+ color: #fff;
+}
+
+/* Custom default button */
+.btn-secondary,
+.btn-secondary:hover,
+.btn-secondary:focus {
+ color: #333;
+ text-shadow: none; /* Prevent inheritance from `body` */
+ background-color: #fff;
+ border: .05rem solid #fff;
+}
+
+
+/*
+ * Base structure
+ */
+
+html,
+body {
+ height: 100%;
+ background-color: #333;
+}
+
+body {
+ display: -ms-flexbox;
+ display: flex;
+ color: #fff;
+ text-shadow: 0 .05rem .1rem rgba(0, 0, 0, .5);
+ box-shadow: inset 0 0 5rem rgba(0, 0, 0, .5);
+}
+
+.cover-container {
+ max-width: 42em;
+}
+
+
+/*
+ * Header
+ */
+.masthead {
+ margin-bottom: 2rem;
+}
+
+.masthead-brand {
+ margin-bottom: 0;
+}
+
+.nav-masthead .nav-link {
+ padding: .25rem 0;
+ font-weight: 700;
+ color: rgba(255, 255, 255, .5);
+ background-color: transparent;
+ border-bottom: .25rem solid transparent;
+}
+
+.nav-masthead .nav-link:hover,
+.nav-masthead .nav-link:focus {
+ border-bottom-color: rgba(255, 255, 255, .25);
+}
+
+.nav-masthead .nav-link + .nav-link {
+ margin-left: 1rem;
+}
+
+.nav-masthead .active {
+ color: #fff;
+ border-bottom-color: #fff;
+}
+
+@media (min-width: 48em) {
+ .masthead-brand {
+ float: left;
+ }
+ .nav-masthead {
+ float: right;
+ }
+}
+
+
+/*
+ * Cover
+ */
+.cover {
+ padding: 0 1.5rem;
+}
+.cover .btn-lg {
+ padding: .75rem 1.25rem;
+ font-weight: 700;
+}
+
+
+/*
+ * Footer
+ */
+.mastfoot {
+ color: rgba(255, 255, 255, .5);
+}
diff --git a/data/index.html b/data/index.html
index 46c9a48..1a3cc09 100644
--- a/data/index.html
+++ b/data/index.html
@@ -1 +1,8 @@
-THIS IS SPARTA
+
+
+ Discord Auto Upload
+ Hey look it's DAU.
+
+ Learn more
+
+
diff --git a/data/wrapper.tmpl b/data/wrapper.tmpl
new file mode 100644
index 0000000..c65cc58
--- /dev/null
+++ b/data/wrapper.tmpl
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dau.go b/dau.go
index 7e89a40..f29546c 100644
--- a/dau.go
+++ b/dau.go
@@ -24,58 +24,39 @@ import (
"github.com/fogleman/gg"
"github.com/pborman/getopt"
- "github.com/skratchdot/open-golang/open"
+ // "github.com/skratchdot/open-golang/open"
"golang.org/x/image/font/inconsolata"
"github.com/tardisx/discord-auto-upload/web"
+ "github.com/tardisx/discord-auto-upload/config"
)
-const currentVersion = "0.7"
-
var lastCheck = time.Now()
var newLastCheck = time.Now()
-// Config for the application
-type Config struct {
- webhookURL string
- path string
- watch int
- username string
- noWatermark bool
- exclude string
-}
func main() {
- config := parseOptions()
- checkPath(config.path)
- wconfig := web.Init()
- go processWebChanges(wconfig)
+ parseOptions()
+ checkPath(config.Config.Path)
- log.Print("Opening web browser")
- open.Start("http://localhost:9090")
+ // log.Print("Opening web browser")
+ // open.Start("http://localhost:9090")
+ go web.StartWebServer()
checkUpdates()
- log.Print("Waiting for images to appear in ", config.path)
+ log.Print("Waiting for images to appear in ", config.Config.Path)
// wander the path, forever
for {
- err := filepath.Walk(config.path,
- func(path string, f os.FileInfo, err error) error { return checkFile(path, f, err, config) })
+ err := filepath.Walk(config.Config.Path,
+ func(path string, f os.FileInfo, err error) error { return checkFile(path, f, err) })
if err != nil {
log.Fatal("could not watch path", err)
}
lastCheck = newLastCheck
log.Print("sleeping before next check");
- time.Sleep(time.Duration(config.watch) * time.Second)
- }
-}
-
-func processWebChanges(wc web.DAUWebServer) {
- for {
- change := <-wc.ConfigChange
- log.Print(change)
- log.Print("Got a change!")
+ time.Sleep(time.Duration(config.Config.Watch) * time.Second)
}
}
@@ -118,8 +99,8 @@ func checkUpdates() {
log.Fatal("could not parse JSON: ", err)
}
- if currentVersion < latest.TagName {
- fmt.Printf("You are currently on version %s, but version %s is available\n", currentVersion, latest.TagName)
+ if config.CurrentVersion < latest.TagName {
+ fmt.Printf("You are currently on version %s, but version %s is available\n", config.CurrentVersion, latest.TagName)
fmt.Println("----------- Release Info -----------")
fmt.Println(latest.Body)
fmt.Println("------------------------------------")
@@ -128,9 +109,8 @@ func checkUpdates() {
}
-func parseOptions() Config {
+func parseOptions() {
- var newConfig Config
// Declare the flags to be used
webhookFlag := getopt.StringLong("webhook", 'w', "", "discord webhook URL")
pathFlag := getopt.StringLong("directory", 'd', "", "directory to scan, optional, defaults to current directory")
@@ -151,7 +131,7 @@ func parseOptions() Config {
if *versionFlag {
fmt.Println("dau - https://github.com/tardisx/discord-auto-upload")
- fmt.Printf("Version: %s\n", currentVersion)
+ fmt.Printf("Version: %s\n", config.CurrentVersion)
os.Exit(0)
}
@@ -164,23 +144,22 @@ func parseOptions() Config {
log.Fatal("ERROR: You must specify a --webhook URL")
}
- newConfig.path = *pathFlag
- newConfig.webhookURL = *webhookFlag
- newConfig.watch = int(*watchFlag)
- newConfig.username = *usernameFlag
- newConfig.noWatermark = *noWatermarkFlag
- newConfig.exclude = *excludeFlag
+ config.Config.Path = *pathFlag
+ config.Config.WebHookURL = *webhookFlag
+ config.Config.Watch = int(*watchFlag)
+ config.Config.Username = *usernameFlag
+ config.Config.NoWatermark = *noWatermarkFlag
+ config.Config.Exclude = *excludeFlag
- return newConfig
}
-func checkFile(path string, f os.FileInfo, err error, config Config) error {
+func checkFile(path string, f os.FileInfo, err error) error {
if f.ModTime().After(lastCheck) && f.Mode().IsRegular() {
- if fileEligible(config, path) {
+ if fileEligible(path) {
// process file
- processFile(config, path)
+ processFile(path)
}
if newLastCheck.Before(f.ModTime()) {
@@ -191,9 +170,9 @@ func checkFile(path string, f os.FileInfo, err error, config Config) error {
return nil
}
-func fileEligible(config Config, file string) bool {
+func fileEligible(file string) bool {
- if config.exclude != "" && strings.Contains(file, config.exclude) {
+ if config.Config.Exclude != "" && strings.Contains(file, config.Config.Exclude) {
return false
}
@@ -205,9 +184,9 @@ func fileEligible(config Config, file string) bool {
return false
}
-func processFile(config Config, file string) {
+func processFile(file string) {
- if !config.noWatermark {
+ if !config.Config.NoWatermark {
log.Print("Copying to temp location and watermarking ", file)
file = mungeFile(file)
}
@@ -216,8 +195,9 @@ func processFile(config Config, file string) {
extraParams := map[string]string{}
- if config.username != "" {
- extraParams["username"] = config.username
+ if config.Config.Username != "" {
+ log.Print("Overriding username with " + config.Config.Username)
+ extraParams["username"] = config.Config.Username
}
type DiscordAPIResponseAttachment struct {
@@ -237,7 +217,7 @@ func processFile(config Config, file string) {
var retriesRemaining = 5
for retriesRemaining > 0 {
- request, err := newfileUploadRequest(config.webhookURL, extraParams, "file", file)
+ request, err := newfileUploadRequest(config.Config.WebHookURL, extraParams, "file", file)
if err != nil {
log.Fatal(err)
}
@@ -296,7 +276,7 @@ func processFile(config Config, file string) {
}
}
- if !config.noWatermark {
+ if !config.Config.NoWatermark {
log.Print("Removing temporary file ", file)
os.Remove(file)
}
diff --git a/web/server.go b/web/server.go
index 65ae2d7..fb8d147 100644
--- a/web/server.go
+++ b/web/server.go
@@ -8,6 +8,12 @@ import (
"github.com/tardisx/discord-auto-upload/assets"
// "strings"
"regexp"
+ "github.com/tardisx/discord-auto-upload/config"
+ "os"
+ "path/filepath"
+ "mime"
+ "text/template"
+
)
// DAUWebServer - stuff for the web server
@@ -15,66 +21,124 @@ type DAUWebServer struct {
ConfigChange chan int
}
-type response struct {
- Success int
+type valueStringResponse struct {
+ Success bool `json: 'success'`
+ Value string `json: 'value'`
}
-// I am too noob to work out how to pass context around
-var wsConfig DAUWebServer
-
-// r.ParseForm() // parse arguments, you have to call this by yourself
-// fmt.Println(r.Form) // print form information in server side
-// fmt.Println("path", r.URL.Path)
-// fmt.Println("scheme", r.URL.Scheme)
-// fmt.Println(r.Form["url_long"])
-// for k, v := range r.Form {
-// fmt.Println("key:", k)
-// fmt.Println("val:", strings.Join(v, ""))
-// }
+type errorResponse struct {
+ Success bool `json: 'success'`
+ Error string `json: 'error'`
+}
func getStatic(w http.ResponseWriter, r *http.Request) {
// haha this is dumb and I should change it
- fmt.Println(r.URL)
+ // fmt.Println(r.URL)
re := regexp.MustCompile(`[^a-zA-Z0-9\.]`)
- path := r.URL.Path
+ path := r.URL.Path[1:]
sanitized_path := re.ReplaceAll([]byte(path), []byte("_"))
- fmt.Println(sanitized_path)
+ if string(sanitized_path) == "" {
+ sanitized_path = []byte("index.html");
+ }
data, err := assets.Asset(string(sanitized_path))
if err != nil {
// Asset was not found.
fmt.Fprintln(w, err)
}
+
+
+ extension := filepath.Ext(string(sanitized_path))
+
+ // is this a HTML file? if so wrap it in the template
+ if extension == ".html" {
+ wrapper, _ := assets.Asset("wrapper.tmpl")
+ t := template.Must(template.New("wrapper").Parse(string(wrapper)))
+ var b struct {
+ Body string
+ Path string
+ Version string
+ }
+ b.Body = string(data)
+ b.Path = string(sanitized_path)
+ b.Version = config.CurrentVersion
+ t.Execute(w, b)
+ return
+ }
+
+ // otherwise we are a static thing
+ w.Header().Set("Content-Type", mime.TypeByExtension(extension))
+
w.Write(data)
//
}
+// TODO there should be locks around all these config accesses
func getSetWebhook(w http.ResponseWriter, r *http.Request) {
- wsConfig.ConfigChange <- 1
- goodResponse := response{1}
- js, err := json.Marshal(goodResponse)
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
-
w.Header().Set("Content-Type", "application/json")
- w.Write(js)
+ if r.Method == "GET" {
+ getResponse := valueStringResponse{ Success: true, Value: config.Config.WebHookURL }
+
+ // I can't see any way this will fail
+ js, _ := json.Marshal(getResponse)
+ w.Write(js)
+ } else if r.Method == "POST" {
+ err := r.ParseForm()
+ if err != nil {
+ log.Fatal(err)
+ }
+ config.Config.WebHookURL = r.PostForm.Get("value")
+ postResponse := valueStringResponse{ Success: true, Value: config.Config.WebHookURL }
+
+ js, _ := json.Marshal(postResponse)
+ w.Write(js)
+ }
}
func getSetDirectory(w http.ResponseWriter, r *http.Request) {
+ log.Print("ok")
+ w.Header().Set("Content-Type", "application/json")
+
+ if r.Method == "GET" {
+ getResponse := valueStringResponse{ Success: true, Value: config.Config.Path }
+
+ // I can't see any way this will fail
+ js, _ := json.Marshal(getResponse)
+ w.Write(js)
+ } else if r.Method == "POST" {
+ err := r.ParseForm()
+ if err != nil {
+ log.Fatal(err)
+ }
+ newPath := r.PostForm.Get("value")
+
+ // sanity check this path
+ stat, err := os.Stat(newPath)
+ if os.IsNotExist(err) {
+ // not exist
+ response := errorResponse{ Success: false, Error: fmt.Sprintf("Path: %s - does not exist", newPath) }
+ js, _ := json.Marshal(response)
+ w.Write(js)
+ return;
+ } else if ! stat.IsDir() {
+ // not a directory
+ response := errorResponse{ Success: false, Error: fmt.Sprintf("Path: %s - is not a directory", newPath) }
+ js, _ := json.Marshal(response)
+ w.Write(js)
+ return;
+ }
+
+ config.Config.Path = newPath
+ postResponse := valueStringResponse{ Success: true, Value: config.Config.Path }
+
+ js, _ := json.Marshal(postResponse)
+ w.Write(js)
+ }
}
-// Init is great
-func Init() DAUWebServer {
- wsConfig.ConfigChange = make(chan int)
- go startWebServer()
- return wsConfig
-}
-
-func startWebServer() {
+func StartWebServer() {
http.HandleFunc("/", getStatic)
http.HandleFunc("/rest/config/webhook", getSetWebhook)
http.HandleFunc("/rest/config/directory", getSetDirectory)