12 Commits
0.7 ... 0.9

Author SHA1 Message Date
d23e31c0e0 Bump version 2021-06-04 10:42:26 +09:30
9cb79a846e Umm, how did this ever work? 😫 2021-06-04 10:41:23 +09:30
a5ce0c7f63 Documenation update 2021-06-03 19:42:12 +09:30
bcc4e145a2 Limit number of log entries stored 2021-06-03 19:40:53 +09:30
d8c0b7d0ea Fix error popup 2021-06-03 19:40:43 +09:30
fdf70daba7 Improve log display, use a <pre> so it can be easily cut and pasted. 2021-06-03 19:36:48 +09:30
b69cdebf3b Send logs to web server for display there 2021-06-02 23:42:29 +09:30
9e22490fe2 Merge pull request #10 from NoahBohme/master
Open discord link in a new tab
2021-03-15 23:30:56 +10:30
NoahBohme
ae24f16631 Delete .github/workflows directory 2021-03-15 11:51:07 +01:00
NoahBohme
b69acac0d0 Create go.yml 2021-02-23 09:46:47 +01:00
noah
c833f185cc add link for discord webhook 2021-02-23 08:23:10 +01:00
noah
b3ee0d9d1d Open discord link in a new tab 2021-02-23 08:16:59 +01:00
10 changed files with 178 additions and 75 deletions

View File

@@ -80,6 +80,11 @@ thumbnail files.
* Files to upload are determined by the file modification time. If you drag and drop existing files they will * Files to upload are determined by the file modification time. If you drag and drop existing files they will
not be detected and uploaded. Only newly created files will be detected. not be detected and uploaded. Only newly created files will be detected.
## Troubleshooting
Please check the "log" page on the web interface for information when things are
not working as you expect.
## TODO ## TODO
This is just a relatively quick hack. Open to suggestions on new features and improvements. This is just a relatively quick hack. Open to suggestions on new features and improvements.

View File

@@ -1,11 +1,15 @@
package config package config
import ( import (
"github.com/mitchellh/go-homedir" "encoding/json"
"log" "fmt"
"os" "io/ioutil"
"encoding/json" "log"
"io/ioutil" "os"
daulog "github.com/tardisx/discord-auto-upload/log"
"github.com/mitchellh/go-homedir"
) )
// Config for the application // Config for the application
@@ -18,55 +22,57 @@ var Config struct {
Exclude string Exclude string
} }
const CurrentVersion string = "0.7" const CurrentVersion string = "0.9"
// Load the current config or initialise with defaults // Load the current config or initialise with defaults
func LoadOrInit() { func LoadOrInit() {
configPath := configPath() configPath := configPath()
log.Printf("Trying to load from %s\n", configPath) daulog.SendLog(fmt.Sprintf("Trying to load config from %s", configPath), daulog.LogTypeDebug)
_, err := os.Stat(configPath) _, err := os.Stat(configPath)
if os.IsNotExist(err) { if os.IsNotExist(err) {
log.Printf("NOTE: No config file, writing out sample configuration") daulog.SendLog("NOTE: No config file, writing out sample configuration", daulog.LogTypeInfo)
log.Printf("You need to set the configuration via the web interface") daulog.SendLog("You need to set the configuration via the web interface", daulog.LogTypeInfo)
Config.WebHookURL = "" Config.WebHookURL = ""
Config.Path = homeDir() + string(os.PathSeparator) + "screenshots" Config.Path = homeDir() + string(os.PathSeparator) + "screenshots"
Config.Watch = 10 Config.Watch = 10
SaveConfig() SaveConfig()
} else { } else {
LoadConfig() LoadConfig()
} }
} }
func LoadConfig() { func LoadConfig() {
path := configPath() path := configPath()
data, err := ioutil.ReadFile(path) data, err := ioutil.ReadFile(path)
if err != nil { if err != nil {
log.Fatalf("cannot read config file %s: %s", path, err.Error()) log.Fatalf("cannot read config file %s: %s", path, err.Error())
} }
err = json.Unmarshal([]byte(data), &Config) err = json.Unmarshal([]byte(data), &Config)
if err != nil { if err != nil {
log.Fatalf("cannot decode config file %s: %s", path, err.Error()) log.Fatalf("cannot decode config file %s: %s", path, err.Error())
} }
} }
func SaveConfig() { func SaveConfig() {
log.Print("saving configuration") daulog.SendLog("saving configuration", daulog.LogTypeInfo)
path := configPath() path := configPath()
jsonString, _ := json.Marshal(Config) jsonString, _ := json.Marshal(Config)
err := ioutil.WriteFile(path, jsonString, os.ModePerm) err := ioutil.WriteFile(path, jsonString, os.ModePerm)
if (err != nil) { if err != nil {
log.Fatalf("Cannot save config %s: %s", path, err.Error()) log.Fatalf("Cannot save config %s: %s", path, err.Error())
} }
} }
func homeDir() string { func homeDir() string {
dir, err := homedir.Dir() dir, err := homedir.Dir()
if (err != nil) { panic (err) } if err != nil {
return dir; panic(err)
}
return dir
} }
func configPath() string { func configPath() string {
homeDir := homeDir() homeDir := homeDir()
return homeDir + string(os.PathSeparator) + ".dau.json" return homeDir + string(os.PathSeparator) + ".dau.json"
} }

View File

@@ -2,6 +2,8 @@
<main role="main" class="inner DAU"> <main role="main" class="inner DAU">
<h1 class="DAU-heading">Config</h1> <h1 class="DAU-heading">Config</h1>
<p class="lead">Discord-auto-upload configuration</p> <p class="lead">Discord-auto-upload configuration</p>
<a href="https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks"><p class="lead">How to find your discord webhook</p></a>
<form class=""> <form class="">
<div class="form-row align-items-center config-item" data-key="webhook"> <div class="form-row align-items-center config-item" data-key="webhook">
@@ -121,10 +123,11 @@ $(document).ready(function() {
.done(function(data) { .done(function(data) {
var this_el = $(".config-item[data-key='"+key+"']").find('.rest-field'); var this_el = $(".config-item[data-key='"+key+"']").find('.rest-field');
if (this_el.hasClass('rest-field-boolean')) { if (this_el.hasClass('rest-field-boolean')) {
this_el.prop('checked', data.Value); this_el.prop('checked', data.value);
} }
else { else {
this_el.val(data.Value);
this_el.val(data.value);
} }
update_sadness(); update_sadness();
@@ -140,10 +143,10 @@ $(document).ready(function() {
} }
$.post('/rest/config/'+key, { value: val }) $.post('/rest/config/'+key, { value: val })
.done(function(d) { .done(function(d) {
if (d.Success) { if (d.success) {
alert('Updated config'); alert('Updated config');
} else { } else {
alert("Error: " + d.Error); alert("Error: " + d.error);
} }
}); });

View File

@@ -42,6 +42,10 @@ body {
max-width: 42em; max-width: 42em;
} }
pre {
background-color: black;
color: aliceblue;
}
/* /*
* Header * Header

View File

@@ -3,6 +3,6 @@
<h1 class="DAU-heading">Discord Auto Upload</h1> <h1 class="DAU-heading">Discord Auto Upload</h1>
<p class="lead">Hey look, it's DAU :-)</p> <p class="lead">Hey look, it's DAU :-)</p>
<p class="lead"> <p class="lead">
<a href="https://github.com/tardisx/discord-auto-upload" class="btn btn-lg btn-secondary">Learn more</a> <a href="https://github.com/tardisx/discord-auto-upload" class="btn btn-lg btn-secondary" target="_blank">Learn more</a>
</p> </p>
</main> </main>

18
data/logs.html Normal file
View File

@@ -0,0 +1,18 @@
<main role="main" class="inner DAU">
<h1 class="DAU-heading">Config</h1>
<p class="lead">Discord-auto-upload logs</p>
<pre id="logs" class="text-left pre-scrollable">
</pre>
</main>
<script>
$(document).ready(function() {
$.ajax({ method: 'get', url: '/rest/logs'})
.done(function(data) {
console.log(data);
$('#logs').text(data);
});
});
</script>

View File

@@ -40,6 +40,7 @@
<nav class="nav nav-masthead justify-content-center"> <nav class="nav nav-masthead justify-content-center">
<a class="nav-link {{ if eq .Path "index.html"}} active {{ end }}" href="/">Home</a> <a class="nav-link {{ if eq .Path "index.html"}} active {{ end }}" href="/">Home</a>
<a class="nav-link {{ if eq .Path "config.html"}} active {{ end }}" href="/config.html">Config</a> <a class="nav-link {{ if eq .Path "config.html"}} active {{ end }}" href="/config.html">Config</a>
<a class="nav-link {{ if eq .Path "logs.html"}} active {{ end }}" href="/logs.html">Logs</a>
</nav> </nav>
</div> </div>
</header> </header>

32
dau.go
View File

@@ -24,10 +24,12 @@ import (
"github.com/fogleman/gg" "github.com/fogleman/gg"
"github.com/pborman/getopt" "github.com/pborman/getopt"
// "github.com/skratchdot/open-golang/open" // "github.com/skratchdot/open-golang/open"
"golang.org/x/image/font/inconsolata" "golang.org/x/image/font/inconsolata"
"github.com/tardisx/discord-auto-upload/config" "github.com/tardisx/discord-auto-upload/config"
daulog "github.com/tardisx/discord-auto-upload/log"
"github.com/tardisx/discord-auto-upload/web" "github.com/tardisx/discord-auto-upload/web"
) )
@@ -40,11 +42,11 @@ func main() {
// log.Print("Opening web browser") // log.Print("Opening web browser")
// open.Start("http://localhost:9090") // open.Start("http://localhost:9090")
go web.StartWebServer() web.StartWebServer()
checkUpdates() checkUpdates()
log.Print("Waiting for images to appear in ", config.Config.Path) daulog.SendLog(fmt.Sprintf("Waiting for images to appear in %s", config.Config.Path), daulog.LogTypeInfo)
// wander the path, forever // wander the path, forever
for { for {
if checkPath(config.Config.Path) { if checkPath(config.Config.Path) {
@@ -55,7 +57,7 @@ func main() {
} }
lastCheck = newLastCheck lastCheck = newLastCheck
} }
log.Printf("sleeping for %ds before next check of %s", config.Config.Watch, config.Config.Path) daulog.SendLog(fmt.Sprintf("sleeping for %ds before next check of %s", config.Config.Watch, config.Config.Path), daulog.LogTypeDebug)
time.Sleep(time.Duration(config.Config.Watch) * time.Second) time.Sleep(time.Duration(config.Config.Watch) * time.Second)
} }
} }
@@ -76,16 +78,18 @@ func checkPath(path string) bool {
func checkUpdates() { func checkUpdates() {
type GithubRelease struct { type GithubRelease struct {
HTMLURL string HTMLURL string `json:"html_url"`
TagName string TagName string `json:"tag_name"`
Name string Name string `json:"name"`
Body string Body string `json:"body"`
} }
daulog.SendLog("checking for new version", daulog.LogTypeInfo)
client := &http.Client{Timeout: time.Second * 5} client := &http.Client{Timeout: time.Second * 5}
resp, err := client.Get("https://api.github.com/repos/tardisx/discord-auto-upload/releases/latest") resp, err := client.Get("https://api.github.com/repos/tardisx/discord-auto-upload/releases/latest")
if err != nil { if err != nil {
log.Print("WARNING: Update check failed: ", err) daulog.SendLog(fmt.Sprintf("WARNING: Update check failed: %v", err), daulog.LogTypeError)
return return
} }
defer resp.Body.Close() defer resp.Body.Close()
@@ -107,6 +111,7 @@ func checkUpdates() {
fmt.Println(latest.Body) fmt.Println(latest.Body)
fmt.Println("------------------------------------") fmt.Println("------------------------------------")
fmt.Println("Upgrade at https://github.com/tardisx/discord-auto-upload/releases/latest") fmt.Println("Upgrade at https://github.com/tardisx/discord-auto-upload/releases/latest")
daulog.SendLog(fmt.Sprintf("New version available: %s - download at https://github.com/tardisx/discord-auto-upload/releases/latest", latest.TagName), daulog.LogTypeInfo)
} }
} }
@@ -136,7 +141,6 @@ func parseOptions() {
} }
func checkFile(path string, f os.FileInfo, err error) error { func checkFile(path string, f os.FileInfo, err error) error {
if f.ModTime().After(lastCheck) && f.Mode().IsRegular() { if f.ModTime().After(lastCheck) && f.Mode().IsRegular() {
if fileEligible(path) { if fileEligible(path) {
@@ -169,16 +173,16 @@ func fileEligible(file string) bool {
func processFile(file string) { func processFile(file string) {
if !config.Config.NoWatermark { if !config.Config.NoWatermark {
log.Print("Copying to temp location and watermarking ", file) daulog.SendLog("Copying to temp location and watermarking ", daulog.LogTypeInfo)
file = mungeFile(file) file = mungeFile(file)
} }
if config.Config.WebHookURL == "" { if config.Config.WebHookURL == "" {
log.Print("WebHookURL is not configured - cannot upload!") daulog.SendLog("WebHookURL is not configured - cannot upload!", daulog.LogTypeError)
return return
} }
log.Print("Uploading ", file) daulog.SendLog("Uploading", daulog.LogTypeInfo)
extraParams := map[string]string{} extraParams := map[string]string{}
@@ -264,7 +268,7 @@ func processFile(file string) {
} }
if !config.Config.NoWatermark { if !config.Config.NoWatermark {
log.Print("Removing temporary file ", file) daulog.SendLog(fmt.Sprintf("Removing temporary file: %s", file), daulog.LogTypeDebug)
os.Remove(file) os.Remove(file)
} }
@@ -278,7 +282,7 @@ func sleepForRetries(retry int) {
return return
} }
retryTime := (6-retry)*(6-retry) + 6 retryTime := (6-retry)*(6-retry) + 6
log.Printf("Will retry in %d seconds (%d remaining attempts)", retryTime, retry) daulog.SendLog(fmt.Sprintf("Will retry in %d seconds (%d remaining attempts)", retryTime, retry), daulog.LogTypeError)
time.Sleep(time.Duration(retryTime) * time.Second) time.Sleep(time.Duration(retryTime) * time.Second)
} }

45
log/log.go Normal file
View File

@@ -0,0 +1,45 @@
package log
import (
"time"
)
type LogEntryType string
type LogEntry struct {
Timestamp time.Time `json:"ts"`
Type LogEntryType `json:"type"`
Entry string `json:"log"`
}
const (
LogTypeInfo = "info"
LogTypeError = "error"
LogTypeDebug = "debug"
)
var LogEntries []LogEntry
var logInput chan LogEntry
func init() {
// wait for log entries
logInput = make(chan LogEntry)
go func() {
for {
aLog := <-logInput
LogEntries = append(LogEntries, aLog)
for len(LogEntries) > 100 {
LogEntries = LogEntries[1:]
}
}
}()
}
func SendLog(entry string, entryType LogEntryType) {
logInput <- LogEntry{
Timestamp: time.Now(),
Entry: entry,
Type: entryType,
}
}

View File

@@ -3,8 +3,6 @@ package web
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/tardisx/discord-auto-upload/assets"
"github.com/tardisx/discord-auto-upload/config"
"log" "log"
"mime" "mime"
"net/http" "net/http"
@@ -13,6 +11,10 @@ import (
"regexp" "regexp"
"strconv" "strconv"
"text/template" "text/template"
"github.com/tardisx/discord-auto-upload/assets"
"github.com/tardisx/discord-auto-upload/config"
daulog "github.com/tardisx/discord-auto-upload/log"
) )
// DAUWebServer - stuff for the web server // DAUWebServer - stuff for the web server
@@ -21,23 +23,22 @@ type DAUWebServer struct {
} }
type valueStringResponse struct { type valueStringResponse struct {
Success bool `json: 'success'` Success bool `json:"success"`
Value string `json: 'value'` Value string `json:"value"`
} }
type valueBooleanResponse struct { type valueBooleanResponse struct {
Success bool `json: 'success'` Success bool `json:"success"`
Value bool `json: 'value'` Value bool `json:"value"`
} }
type errorResponse struct { type errorResponse struct {
Success bool `json: 'success'` Success bool `json:"success"`
Error string `json: 'error'` Error string `json:"error"`
} }
func getStatic(w http.ResponseWriter, r *http.Request) { func getStatic(w http.ResponseWriter, r *http.Request) {
// haha this is dumb and I should change it // haha this is dumb and I should change it
// fmt.Println(r.URL)
re := regexp.MustCompile(`[^a-zA-Z0-9\.]`) re := regexp.MustCompile(`[^a-zA-Z0-9\.]`)
path := r.URL.Path[1:] path := r.URL.Path[1:]
sanitized_path := re.ReplaceAll([]byte(path), []byte("_")) sanitized_path := re.ReplaceAll([]byte(path), []byte("_"))
@@ -270,8 +271,23 @@ func getSetExclude(w http.ResponseWriter, r *http.Request) {
} }
} }
func getLogs(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain")
text := ""
for _, log := range daulog.LogEntries {
text = text + fmt.Sprintf(
"%-6s %-19s %s\n", log.Type, log.Timestamp.Format("2006-01-02 15:04:05"), log.Entry,
)
}
// js, _ := json.Marshal(daulog.LogEntries)
w.Write([]byte(text))
}
func StartWebServer() { func StartWebServer() {
http.HandleFunc("/", getStatic) http.HandleFunc("/", getStatic)
http.HandleFunc("/rest/config/webhook", getSetWebhook) http.HandleFunc("/rest/config/webhook", getSetWebhook)
http.HandleFunc("/rest/config/username", getSetUsername) http.HandleFunc("/rest/config/username", getSetUsername)
@@ -280,11 +296,12 @@ func StartWebServer() {
http.HandleFunc("/rest/config/directory", getSetDirectory) http.HandleFunc("/rest/config/directory", getSetDirectory)
http.HandleFunc("/rest/config/exclude", getSetExclude) http.HandleFunc("/rest/config/exclude", getSetExclude)
http.HandleFunc("/rest/logs", getLogs)
log.Print("Starting web server on http://localhost:9090") go func() {
err := http.ListenAndServe(":9090", nil) // set listen port log.Print("Starting web server on http://localhost:9090")
if err != nil { err := http.ListenAndServe(":9090", nil) // set listen port
log.Fatal("ListenAndServe: ", err) if err != nil {
} log.Fatal("ListenAndServe: ", err)
}
}()
} }