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
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
This is just a relatively quick hack. Open to suggestions on new features and improvements.

View File

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

View File

@@ -2,6 +2,8 @@
<main role="main" class="inner DAU">
<h1 class="DAU-heading">Config</h1>
<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="">
<div class="form-row align-items-center config-item" data-key="webhook">
@@ -121,10 +123,11 @@ $(document).ready(function() {
.done(function(data) {
var this_el = $(".config-item[data-key='"+key+"']").find('.rest-field');
if (this_el.hasClass('rest-field-boolean')) {
this_el.prop('checked', data.Value);
this_el.prop('checked', data.value);
}
else {
this_el.val(data.Value);
this_el.val(data.value);
}
update_sadness();
@@ -140,10 +143,10 @@ $(document).ready(function() {
}
$.post('/rest/config/'+key, { value: val })
.done(function(d) {
if (d.Success) {
if (d.success) {
alert('Updated config');
} else {
alert("Error: " + d.Error);
alert("Error: " + d.error);
}
});

View File

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

View File

@@ -3,6 +3,6 @@
<h1 class="DAU-heading">Discord Auto Upload</h1>
<p class="lead">Hey look, it's DAU :-)</p>
<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>
</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">
<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 "logs.html"}} active {{ end }}" href="/logs.html">Logs</a>
</nav>
</div>
</header>

32
dau.go
View File

@@ -24,10 +24,12 @@ import (
"github.com/fogleman/gg"
"github.com/pborman/getopt"
// "github.com/skratchdot/open-golang/open"
"golang.org/x/image/font/inconsolata"
"github.com/tardisx/discord-auto-upload/config"
daulog "github.com/tardisx/discord-auto-upload/log"
"github.com/tardisx/discord-auto-upload/web"
)
@@ -40,11 +42,11 @@ func main() {
// log.Print("Opening web browser")
// open.Start("http://localhost:9090")
go web.StartWebServer()
web.StartWebServer()
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
for {
if checkPath(config.Config.Path) {
@@ -55,7 +57,7 @@ func main() {
}
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)
}
}
@@ -76,16 +78,18 @@ func checkPath(path string) bool {
func checkUpdates() {
type GithubRelease struct {
HTMLURL string
TagName string
Name string
Body string
HTMLURL string `json:"html_url"`
TagName string `json:"tag_name"`
Name string `json:"name"`
Body string `json:"body"`
}
daulog.SendLog("checking for new version", daulog.LogTypeInfo)
client := &http.Client{Timeout: time.Second * 5}
resp, err := client.Get("https://api.github.com/repos/tardisx/discord-auto-upload/releases/latest")
if err != nil {
log.Print("WARNING: Update check failed: ", err)
daulog.SendLog(fmt.Sprintf("WARNING: Update check failed: %v", err), daulog.LogTypeError)
return
}
defer resp.Body.Close()
@@ -107,6 +111,7 @@ func checkUpdates() {
fmt.Println(latest.Body)
fmt.Println("------------------------------------")
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 {
if f.ModTime().After(lastCheck) && f.Mode().IsRegular() {
if fileEligible(path) {
@@ -169,16 +173,16 @@ func fileEligible(file string) bool {
func processFile(file string) {
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)
}
if config.Config.WebHookURL == "" {
log.Print("WebHookURL is not configured - cannot upload!")
daulog.SendLog("WebHookURL is not configured - cannot upload!", daulog.LogTypeError)
return
}
log.Print("Uploading ", file)
daulog.SendLog("Uploading", daulog.LogTypeInfo)
extraParams := map[string]string{}
@@ -264,7 +268,7 @@ func processFile(file string) {
}
if !config.Config.NoWatermark {
log.Print("Removing temporary file ", file)
daulog.SendLog(fmt.Sprintf("Removing temporary file: %s", file), daulog.LogTypeDebug)
os.Remove(file)
}
@@ -278,7 +282,7 @@ func sleepForRetries(retry int) {
return
}
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)
}

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 (
"encoding/json"
"fmt"
"github.com/tardisx/discord-auto-upload/assets"
"github.com/tardisx/discord-auto-upload/config"
"log"
"mime"
"net/http"
@@ -13,6 +11,10 @@ import (
"regexp"
"strconv"
"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
@@ -21,23 +23,22 @@ type DAUWebServer struct {
}
type valueStringResponse struct {
Success bool `json: 'success'`
Value string `json: 'value'`
Success bool `json:"success"`
Value string `json:"value"`
}
type valueBooleanResponse struct {
Success bool `json: 'success'`
Value bool `json: 'value'`
Success bool `json:"success"`
Value bool `json:"value"`
}
type errorResponse struct {
Success bool `json: 'success'`
Error string `json: 'error'`
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)
re := regexp.MustCompile(`[^a-zA-Z0-9\.]`)
path := r.URL.Path[1:]
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() {
http.HandleFunc("/", getStatic)
http.HandleFunc("/rest/config/webhook", getSetWebhook)
http.HandleFunc("/rest/config/username", getSetUsername)
@@ -280,11 +296,12 @@ func StartWebServer() {
http.HandleFunc("/rest/config/directory", getSetDirectory)
http.HandleFunc("/rest/config/exclude", getSetExclude)
log.Print("Starting web server on http://localhost:9090")
err := http.ListenAndServe(":9090", nil) // set listen port
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
http.HandleFunc("/rest/logs", getLogs)
go func() {
log.Print("Starting web server on http://localhost:9090")
err := http.ListenAndServe(":9090", nil) // set listen port
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}()
}