Send logs to web server for display there

This commit is contained in:
Justin Hawkins 2021-06-02 23:42:29 +09:30
parent 9e22490fe2
commit b69cdebf3b
6 changed files with 140 additions and 67 deletions

View File

@ -1,11 +1,12 @@
package config package config
import ( import (
"github.com/mitchellh/go-homedir" "encoding/json"
"log" "io/ioutil"
"os" "log"
"encoding/json" "os"
"io/ioutil"
"github.com/mitchellh/go-homedir"
) )
// Config for the application // Config for the application
@ -18,55 +19,57 @@ var Config struct {
Exclude string Exclude string
} }
const CurrentVersion string = "0.7" const CurrentVersion string = "0.8"
// 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) log.Printf("Trying to load from %s\n", configPath)
_, 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") log.Printf("NOTE: No config file, writing out sample configuration")
log.Printf("You need to set the configuration via the web interface") log.Printf("You need to set the configuration via the web interface")
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") log.Print("saving configuration")
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,7 +2,7 @@
<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> <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="">

35
data/logs.html Normal file
View File

@ -0,0 +1,35 @@
<main role="main" class="inner DAU">
<h1 class="DAU-heading">Config</h1>
<p class="lead">Discord-auto-upload logs</p>
<table class="table table-condensed">
<thead>
<tr>
<th>time</th><th>entry</th>
</tr>
</thead>
<tbody id="logs">
</tbody>
</table>
</main>
<script>
$(document).ready(function() {
$.ajax({ method: 'get', url: '/rest/logs'})
.done(function(data) {
console.log(data);
$.each(data, function(i, d) {
console.log('do', d);
$('#logs').append(
$('<tr>').append(
$('<th>').text(d.ts),
$('<td>').text(d.log)
)
);
});
});
});
</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>

30
dau.go
View File

@ -24,6 +24,7 @@ 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"
@ -40,11 +41,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) sendLogToWeb(fmt.Sprintf("Waiting for images to appear in %s", config.Config.Path))
// wander the path, forever // wander the path, forever
for { for {
if checkPath(config.Config.Path) { if checkPath(config.Config.Path) {
@ -55,7 +56,7 @@ func main() {
} }
lastCheck = newLastCheck lastCheck = newLastCheck
} }
log.Printf("sleeping for %ds before next check of %s", config.Config.Watch, config.Config.Path) sendLogToWeb(fmt.Sprintf("sleeping for %ds before next check of %s", config.Config.Watch, config.Config.Path))
time.Sleep(time.Duration(config.Config.Watch) * time.Second) time.Sleep(time.Duration(config.Config.Watch) * time.Second)
} }
} }
@ -82,10 +83,12 @@ func checkUpdates() {
Body string Body string
} }
sendLogToWeb("checking for new version")
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) sendLogToWeb(fmt.Sprintf("WARNING: Update check failed: %v", err))
return return
} }
defer resp.Body.Close() defer resp.Body.Close()
@ -107,6 +110,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")
sendLogToWeb(fmt.Sprintf("New version available: %s - download at https://github.com/tardisx/discord-auto-upload/releases/latest"))
} }
} }
@ -136,7 +140,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) {
@ -152,6 +155,13 @@ func checkFile(path string, f os.FileInfo, err error) error {
return nil return nil
} }
func sendLogToWeb(entry string) {
web.LogInput <- web.LogEntry{
Timestamp: time.Now(),
Entry: entry,
}
}
func fileEligible(file string) bool { func fileEligible(file string) bool {
if config.Config.Exclude != "" && strings.Contains(file, config.Config.Exclude) { if config.Config.Exclude != "" && strings.Contains(file, config.Config.Exclude) {
@ -169,16 +179,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) sendLogToWeb("Copying to temp location and watermarking ")
file = mungeFile(file) file = mungeFile(file)
} }
if config.Config.WebHookURL == "" { if config.Config.WebHookURL == "" {
log.Print("WebHookURL is not configured - cannot upload!") sendLogToWeb("WebHookURL is not configured - cannot upload!")
return return
} }
log.Print("Uploading ", file) sendLogToWeb("Uploading")
extraParams := map[string]string{} extraParams := map[string]string{}
@ -264,7 +274,7 @@ func processFile(file string) {
} }
if !config.Config.NoWatermark { if !config.Config.NoWatermark {
log.Print("Removing temporary file ", file) sendLogToWeb(fmt.Sprintf("Removing temporary file: %s", file))
os.Remove(file) os.Remove(file)
} }
@ -278,7 +288,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) sendLogToWeb(fmt.Sprintf("Will retry in %d seconds (%d remaining attempts)", retryTime, retry))
time.Sleep(time.Duration(retryTime) * time.Second) time.Sleep(time.Duration(retryTime) * time.Second)
} }

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"
"time"
"github.com/tardisx/discord-auto-upload/assets"
"github.com/tardisx/discord-auto-upload/config"
) )
// DAUWebServer - stuff for the web server // DAUWebServer - stuff for the web server
@ -21,23 +23,30 @@ 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"`
} }
type LogEntry struct {
Timestamp time.Time `json:"ts"`
Entry string `json:"log"`
}
var logEntries []LogEntry
var LogInput chan LogEntry
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 +279,22 @@ func getSetExclude(w http.ResponseWriter, r *http.Request) {
} }
} }
func getLogs(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
js, _ := json.Marshal(logEntries)
w.Write(js)
}
func StartWebServer() { func StartWebServer() {
// wait for log entries
LogInput = make(chan LogEntry)
go func() {
for {
aLog := <-LogInput
logEntries = append(logEntries, aLog)
}
}()
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 +303,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)
}
}()
} }