Big refactor to allow for multiple watchers, v2 configuration file with migration and new UI for configuration
This commit is contained in:
@@ -1,159 +1,153 @@
|
||||
{{ define "content" }}
|
||||
|
||||
<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>
|
||||
<main role="main" class="inner DAU" x-data="configuration()" x-init="get_config()">
|
||||
<h1 class="DAU-heading">Config</h1>
|
||||
|
||||
</a>
|
||||
|
||||
<form class="">
|
||||
|
||||
<p>Configuration changes are not made until the Save button is pressed
|
||||
at the bottom of this page.
|
||||
</p>
|
||||
|
||||
<h3>global configuration</h3>
|
||||
|
||||
<p>The server port dictates which TCP port the web server listens on.
|
||||
If you change this number you will need to restart.
|
||||
</p>
|
||||
|
||||
<p>The Watch Interval is how often new files will be discovered by your
|
||||
watchers (configured below).</p>
|
||||
|
||||
<div class="form-row align-items-center">
|
||||
<div class="col-sm-6 my-1">
|
||||
<span>Server port</span>
|
||||
</div>
|
||||
<div class="col-sm-6 my-1">
|
||||
<label class="sr-only">Server port</label>
|
||||
<input type="text" class="form-control" placeholder="" x-model.number="config.Port">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row align-items-center">
|
||||
<div class="col-sm-6 my-1">
|
||||
<span>Watch interval</span>
|
||||
</div>
|
||||
<div class="col-sm-6 my-1">
|
||||
<label class="sr-only">Watch interval</label>
|
||||
<input type="text" class="form-control" placeholder="" x-model.number="config.WatchInterval">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<form class="">
|
||||
<div class="form-row align-items-center config-item" data-key="webhook">
|
||||
<div class="col-sm-5 my-1">
|
||||
<span>Discord WebHook URL</span>
|
||||
</div>
|
||||
<div class="col-sm-4 my-1">
|
||||
<label class="sr-only" for="inlineFormInputName">Name</label>
|
||||
<input type="text" class="form-control rest-field" placeholder="https://....">
|
||||
</div>
|
||||
<div class="col-auto my-1">
|
||||
<button type="submit" class="btn btn-primary">update</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<h3>watcher configuration</h3>
|
||||
|
||||
<form class="">
|
||||
<div class="form-row align-items-center config-item" data-key="username">
|
||||
<div class="col-sm-5 my-1">
|
||||
<span>Bot username (optional)</span>
|
||||
</div>
|
||||
<div class="col-sm-4 my-1">
|
||||
<label class="sr-only" for="inlineFormInputName">Name</label>
|
||||
<input type="text" class="form-control rest-field" placeholder="">
|
||||
</div>
|
||||
<div class="col-auto my-1">
|
||||
<button type="submit" class="btn btn-primary">update</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<p>You may configure one or more watchers. Each watcher watches a
|
||||
single directory (and all subdirectories) and when a new image file
|
||||
is found it uploads it to the specified channel via the webhook URL.
|
||||
</p>
|
||||
|
||||
<form class="">
|
||||
<div class="form-row align-items-center config-item" data-key="directory">
|
||||
<div class="col-sm-5 my-1">
|
||||
<span>Directory to watch</span>
|
||||
</div>
|
||||
<div class="col-sm-4 my-1">
|
||||
<label class="sr-only" for="inlineFormInputName">Name</label>
|
||||
<input type="text" class="form-control rest-field" placeholder="/...">
|
||||
</div>
|
||||
<div class="col-auto my-1">
|
||||
<button type="submit" class="btn btn-primary">update</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<p><a href="https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks">
|
||||
Click here</a> for information on how to find your discord webhook URL.</p>
|
||||
|
||||
<form class="">
|
||||
<div class="form-row align-items-center config-item" data-key="watch">
|
||||
<div class="col-sm-5 my-1">
|
||||
<span>Period between filesystem checks (seconds)</span>
|
||||
</div>
|
||||
<div class="col-sm-4 my-1">
|
||||
<label class="sr-only" for="inlineFormInputName">Seconds</label>
|
||||
<input type="text" class="form-control rest-field " placeholder="/...">
|
||||
</div>
|
||||
<div class="col-auto my-1">
|
||||
<button type="submit" class="btn btn-primary">update</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<p>You may also specify a username for the bot to masquerade as. This is a cosmetic
|
||||
change only, and does not hide the uploaders actual identity.
|
||||
</p>
|
||||
|
||||
<form class="">
|
||||
<div class="form-row align-items-center config-item" data-key="nowatermark">
|
||||
<div class="col-sm-5 my-1">
|
||||
<span>Do not watermark images</span>
|
||||
</div>
|
||||
<div class="col-sm-4 my-1">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input rest-field rest-field-boolean" id="input-nowatermark">
|
||||
<label class="custom-control-label" for="input-nowatermark"> </label>
|
||||
<span id="sadness" style="">😭</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto my-1">
|
||||
<button type="submit" class="btn btn-primary">update</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<template x-for="(watcher, i) in config.Watchers">
|
||||
<div class="my-5">
|
||||
<div class="form-row align-items-center">
|
||||
<div class="col-sm-6 my-1">
|
||||
<span>Directory to watch</span>
|
||||
</div>
|
||||
<div class="col-sm-6 my-1">
|
||||
<label class="sr-only" for="">Directory</label>
|
||||
<input type="text" class="form-control" placeholder="" x-model="watcher.Path">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form class="">
|
||||
<div class="form-row align-items-center config-item" data-key="exclude">
|
||||
<div class="col-sm-5 my-1">
|
||||
<span>Files to exclude</span>
|
||||
</div>
|
||||
<div class="col-sm-4 my-1">
|
||||
<label class="sr-only" for="input-exclude">Name</label>
|
||||
<input type="text" id="input-exclude" class="form-control rest-field" placeholder="">
|
||||
</div>
|
||||
<div class="col-auto my-1">
|
||||
<button type="submit" class="btn btn-primary">update</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="form-row align-items-center">
|
||||
<div class="col-sm-6 my-1">
|
||||
<span>Webhook URL</span>
|
||||
</div>
|
||||
<div class="col-sm-6 my-1">
|
||||
<label class="sr-only" for="">WebHook URL</label>
|
||||
<input type="text" class="form-control" placeholder="" x-model="watcher.WebHookURL">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
<div class="form-row align-items-center">
|
||||
<div class="col-sm-6 my-1">
|
||||
<span>Username</span>
|
||||
</div>
|
||||
<div class="col-sm-6 my-1">
|
||||
<label class="sr-only" for="">Username</label>
|
||||
<input type="text" class="form-control" placeholder="" x-model="watcher.Username">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row align-items-center">
|
||||
<div class="col-sm-6 my-1">
|
||||
<span>Watermark</span>
|
||||
</div>
|
||||
<div class="col-sm-6 my-1">
|
||||
<button type="button" @click="config.Watchers[i].NoWatermark = ! config.Watchers[i].NoWatermark" class="btn btn-success" x-text="watcher.NoWatermark ? 'Disabled 😢' : 'Enabled'"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn btn-primary" href="#" @click.prevent="config.Watchers.splice(i, 1);">Remove
|
||||
this watcher</button>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<div class="my-5">
|
||||
<button type="button" class="btn btn-secondary" href="#"
|
||||
@click.prevent="config.Watchers.push({Username: '', WebHookURL: '', Path: '', NoWatermark: false});">
|
||||
Add a new watcher</button>
|
||||
</div>
|
||||
|
||||
<div class="my-5">
|
||||
|
||||
<button type="button" class="my-4 btn btn-danger" href="#" @click="save_config()">
|
||||
Save all Configuration
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
</main>
|
||||
{{ end }}
|
||||
|
||||
{{ define "js" }}
|
||||
<script src="//unpkg.com/alpinejs" defer></script>
|
||||
<script>
|
||||
function update_sadness () {
|
||||
if ($('#input-nowatermark').prop('checked')) {
|
||||
$('#sadness').css('visibility','');
|
||||
}
|
||||
else {
|
||||
$('#sadness').css('visibility','hidden');
|
||||
}
|
||||
}
|
||||
$(document).ready(function() {
|
||||
function configuration() {
|
||||
return {
|
||||
config: {},
|
||||
get_config() {
|
||||
fetch('/rest/config')
|
||||
.then(response => response.json()) // convert to json
|
||||
.then(json => {
|
||||
this.config = json;
|
||||
console.log(json);
|
||||
})
|
||||
},
|
||||
save_config() {
|
||||
fetch('/rest/config', { method: 'POST', body: JSON.stringify(this.config) })
|
||||
.then(response => response.json()) // convert to json
|
||||
.then(json => {
|
||||
this.config = json;
|
||||
console.log(json);
|
||||
})
|
||||
}
|
||||
|
||||
$('#input-nowatermark').on('click', function() { update_sadness(); });
|
||||
|
||||
// populate each field
|
||||
$('.config-item').each(function() {
|
||||
let el = $(this);
|
||||
let key = el.data('key');
|
||||
|
||||
$.ajax({ method: 'get', url: '/rest/config/'+key})
|
||||
.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);
|
||||
}
|
||||
else {
|
||||
|
||||
this_el.val(data.value);
|
||||
}
|
||||
update_sadness();
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
// respond to button clicks to update
|
||||
$('.config-item button').on('click', function(e,f) {
|
||||
key = $(this).parents('.config-item').data('key');
|
||||
val = $(this).parents('.config-item').find('.rest-field').val();
|
||||
if ($(this).parents('.config-item').find('.rest-field-boolean').length) {
|
||||
val = $(this).parents('.config-item').find('.rest-field').prop('checked') ? 1 : 0;
|
||||
}
|
||||
$.post('/rest/config/'+key, { value: val })
|
||||
.done(function(d) {
|
||||
if (d.success) {
|
||||
alert('Updated config');
|
||||
} else {
|
||||
alert("Error: " + d.error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
283
web/server.go
283
web/server.go
@@ -5,44 +5,32 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"mime"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/tardisx/discord-auto-upload/config"
|
||||
daulog "github.com/tardisx/discord-auto-upload/log"
|
||||
"github.com/tardisx/discord-auto-upload/uploads"
|
||||
"github.com/tardisx/discord-auto-upload/version"
|
||||
)
|
||||
|
||||
type WebService struct {
|
||||
Config config.ConfigService
|
||||
}
|
||||
|
||||
//go:embed data
|
||||
var webFS embed.FS
|
||||
|
||||
// DAUWebServer - stuff for the web server
|
||||
type DAUWebServer struct {
|
||||
ConfigChange chan int
|
||||
// ConfigChange chan int
|
||||
|
||||
}
|
||||
|
||||
type valueStringResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type valueBooleanResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Value bool `json:"value"`
|
||||
}
|
||||
|
||||
type errorResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
func getStatic(w http.ResponseWriter, r *http.Request) {
|
||||
func (ws *WebService) getStatic(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
path := r.URL.Path
|
||||
path = strings.TrimLeft(path, "/")
|
||||
@@ -52,8 +40,7 @@ func getStatic(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
extension := filepath.Ext(string(path))
|
||||
|
||||
if extension == ".html" {
|
||||
|
||||
if extension == ".html" { // html file
|
||||
t, err := template.ParseFS(webFS, "data/wrapper.tmpl", "data/"+path)
|
||||
if err != nil {
|
||||
log.Printf("when fetching: %s got: %s", path, err)
|
||||
@@ -78,7 +65,7 @@ func getStatic(w http.ResponseWriter, r *http.Request) {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
} else {
|
||||
} else { // anything else
|
||||
otherStatic, err := webFS.ReadFile("data/" + path)
|
||||
|
||||
if err != nil {
|
||||
@@ -96,200 +83,7 @@ func getStatic(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
}
|
||||
|
||||
// TODO there should be locks around all these config accesses
|
||||
func getSetWebhook(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
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")
|
||||
config.SaveConfig()
|
||||
postResponse := valueStringResponse{Success: true, Value: config.Config.WebHookURL}
|
||||
|
||||
js, _ := json.Marshal(postResponse)
|
||||
w.Write(js)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO there should be locks around all these config accesses
|
||||
func getSetUsername(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if r.Method == "GET" {
|
||||
getResponse := valueStringResponse{Success: true, Value: config.Config.Username}
|
||||
|
||||
// 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.Username = r.PostForm.Get("value")
|
||||
config.SaveConfig()
|
||||
|
||||
postResponse := valueStringResponse{Success: true, Value: config.Config.Username}
|
||||
|
||||
js, _ := json.Marshal(postResponse)
|
||||
w.Write(js)
|
||||
}
|
||||
}
|
||||
|
||||
func getSetWatch(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if r.Method == "GET" {
|
||||
getResponse := valueStringResponse{Success: true, Value: strconv.Itoa(config.Config.Watch)}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
i, err := strconv.Atoi(r.PostForm.Get("value"))
|
||||
|
||||
if err != nil {
|
||||
response := errorResponse{Success: false, Error: fmt.Sprintf("Bad value for watch: %v", err)}
|
||||
js, _ := json.Marshal(response)
|
||||
w.Write(js)
|
||||
return
|
||||
}
|
||||
|
||||
if i < 1 {
|
||||
response := errorResponse{Success: false, Error: "must be > 0"}
|
||||
js, _ := json.Marshal(response)
|
||||
w.Write(js)
|
||||
return
|
||||
}
|
||||
|
||||
config.Config.Watch = i
|
||||
config.SaveConfig()
|
||||
|
||||
postResponse := valueStringResponse{Success: true, Value: strconv.Itoa(config.Config.Watch)}
|
||||
|
||||
js, _ := json.Marshal(postResponse)
|
||||
w.Write(js)
|
||||
}
|
||||
}
|
||||
|
||||
func getSetNoWatermark(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if r.Method == "GET" {
|
||||
getResponse := valueBooleanResponse{Success: true, Value: config.Config.NoWatermark}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
v := r.PostForm.Get("value")
|
||||
|
||||
if v != "0" && v != "1" {
|
||||
response := errorResponse{Success: false, Error: fmt.Sprintf("Bad value for nowatermark: %v", err)}
|
||||
js, _ := json.Marshal(response)
|
||||
w.Write(js)
|
||||
return
|
||||
}
|
||||
|
||||
if v == "0" {
|
||||
config.Config.NoWatermark = false
|
||||
} else {
|
||||
config.Config.NoWatermark = true
|
||||
}
|
||||
config.SaveConfig()
|
||||
|
||||
postResponse := valueBooleanResponse{Success: true, Value: config.Config.NoWatermark}
|
||||
|
||||
js, _ := json.Marshal(postResponse)
|
||||
w.Write(js)
|
||||
}
|
||||
}
|
||||
|
||||
func getSetDirectory(w http.ResponseWriter, r *http.Request) {
|
||||
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
|
||||
config.SaveConfig()
|
||||
|
||||
postResponse := valueStringResponse{Success: true, Value: config.Config.Path}
|
||||
|
||||
js, _ := json.Marshal(postResponse)
|
||||
w.Write(js)
|
||||
}
|
||||
}
|
||||
|
||||
func getSetExclude(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if r.Method == "GET" {
|
||||
getResponse := valueStringResponse{Success: true, Value: config.Config.Exclude}
|
||||
// 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.Exclude = r.PostForm.Get("value")
|
||||
config.SaveConfig()
|
||||
|
||||
postResponse := valueStringResponse{Success: true, Value: config.Config.Exclude}
|
||||
|
||||
js, _ := json.Marshal(postResponse)
|
||||
w.Write(js)
|
||||
}
|
||||
}
|
||||
|
||||
func getLogs(w http.ResponseWriter, r *http.Request) {
|
||||
func (ws *WebService) getLogs(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/plain")
|
||||
|
||||
showDebug := false
|
||||
@@ -312,29 +106,50 @@ func getLogs(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte(text))
|
||||
}
|
||||
|
||||
func getUploads(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
ups := uploads.Uploads
|
||||
text, _ := json.Marshal(ups)
|
||||
w.Write([]byte(text))
|
||||
func (ws *WebService) handleConfig(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "POST" {
|
||||
newConfig := config.ConfigV2{}
|
||||
|
||||
defer r.Body.Close()
|
||||
b, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
w.Write([]byte("bad body"))
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(b, &newConfig)
|
||||
if err != nil {
|
||||
w.Write([]byte("bad data"))
|
||||
log.Printf("%s", err)
|
||||
return
|
||||
}
|
||||
ws.Config.Config = newConfig
|
||||
ws.Config.Save()
|
||||
|
||||
}
|
||||
|
||||
b, _ := json.Marshal(ws.Config.Config)
|
||||
w.Write(b)
|
||||
}
|
||||
|
||||
func StartWebServer() {
|
||||
// func getUploads(w http.ResponseWriter, r *http.Request) {
|
||||
// w.Header().Set("Content-Type", "application/json")
|
||||
// ups := uploads.Uploads
|
||||
// text, _ := json.Marshal(ups)
|
||||
// w.Write([]byte(text))
|
||||
// }
|
||||
|
||||
http.HandleFunc("/", getStatic)
|
||||
http.HandleFunc("/rest/config/webhook", getSetWebhook)
|
||||
http.HandleFunc("/rest/config/username", getSetUsername)
|
||||
http.HandleFunc("/rest/config/watch", getSetWatch)
|
||||
http.HandleFunc("/rest/config/nowatermark", getSetNoWatermark)
|
||||
http.HandleFunc("/rest/config/directory", getSetDirectory)
|
||||
http.HandleFunc("/rest/config/exclude", getSetExclude)
|
||||
func (ws *WebService) StartWebServer() {
|
||||
|
||||
http.HandleFunc("/rest/logs", getLogs)
|
||||
http.HandleFunc("/rest/uploads", getUploads)
|
||||
http.HandleFunc("/", ws.getStatic)
|
||||
|
||||
http.HandleFunc("/rest/logs", ws.getLogs)
|
||||
// http.HandleFunc("/rest/uploads", getUploads)
|
||||
http.HandleFunc("/rest/config", ws.handleConfig)
|
||||
|
||||
go func() {
|
||||
log.Print("Starting web server on http://localhost:9090")
|
||||
err := http.ListenAndServe(":9090", nil) // set listen port
|
||||
listen := fmt.Sprintf(":%d", ws.Config.Config.Port)
|
||||
log.Print("Starting web server on http://localhost%s", listen)
|
||||
err := http.ListenAndServe(listen, nil) // set listen port
|
||||
if err != nil {
|
||||
log.Fatal("ListenAndServe: ", err)
|
||||
}
|
||||
|
||||
@@ -6,15 +6,19 @@ import (
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/tardisx/discord-auto-upload/config"
|
||||
)
|
||||
|
||||
func TestHome(t *testing.T) {
|
||||
s := WebService{}
|
||||
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
w := httptest.NewRecorder()
|
||||
getStatic(w, req)
|
||||
s.getStatic(w, req)
|
||||
res := w.Result()
|
||||
defer res.Body.Close()
|
||||
|
||||
data, err := ioutil.ReadAll(res.Body)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("expected error to be nil got %v", err)
|
||||
}
|
||||
@@ -28,6 +32,7 @@ func TestHome(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNotFound(t *testing.T) {
|
||||
s := WebService{}
|
||||
|
||||
notFounds := []string{
|
||||
"/abc.html", "/foo.html", "/foo.html", "/../foo.html",
|
||||
@@ -38,8 +43,9 @@ func TestNotFound(t *testing.T) {
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, nf, nil)
|
||||
w := httptest.NewRecorder()
|
||||
getStatic(w, req)
|
||||
s.getStatic(w, req)
|
||||
res := w.Result()
|
||||
|
||||
defer res.Body.Close()
|
||||
b, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
@@ -54,3 +60,25 @@ func TestNotFound(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetConfig(t *testing.T) {
|
||||
conf := config.DefaultConfigService()
|
||||
conf.Config = *config.DefaultConfig()
|
||||
s := WebService{Config: *conf}
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/rest/config", nil)
|
||||
w := httptest.NewRecorder()
|
||||
s.handleConfig(w, req)
|
||||
res := w.Result()
|
||||
defer res.Body.Close()
|
||||
|
||||
b, err := ioutil.ReadAll(res.Body)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("expected error to be nil got %v", err)
|
||||
}
|
||||
|
||||
if string(b) != `{"WatchInterval":10,"Version":2,"Watchers":[{"WebHookURL":"abcedf","Path":"/Users/justin/tmp","Username":"","NoWatermark":false,"Exclude":[]}]}` {
|
||||
t.Errorf("Got unexpected response %v", string(b))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user