Rework to use golang 1.16 embed package instead of go-bindata. Rework templates to be less insane
This commit is contained in:
159
web/data/config.html
Normal file
159
web/data/config.html
Normal file
@@ -0,0 +1,159 @@
|
||||
{{ 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>
|
||||
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
</main>
|
||||
{{ end }}
|
||||
|
||||
{{ define "js" }}
|
||||
<script>
|
||||
function update_sadness () {
|
||||
if ($('#input-nowatermark').prop('checked')) {
|
||||
$('#sadness').css('visibility','');
|
||||
}
|
||||
else {
|
||||
$('#sadness').css('visibility','hidden');
|
||||
}
|
||||
}
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#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 }}
|
||||
110
web/data/dau.css
Normal file
110
web/data/dau.css
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
.DAU-container {
|
||||
max-width: 42em;
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: black;
|
||||
color: aliceblue;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
12
web/data/index.html
Normal file
12
web/data/index.html
Normal file
@@ -0,0 +1,12 @@
|
||||
{{ define "content" }}
|
||||
<main role="main" class="inner DAU">
|
||||
<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" target="_blank">Learn more</a>
|
||||
</p>
|
||||
</main>
|
||||
{{ end }}
|
||||
|
||||
{{ define "js" }}
|
||||
{{ end }}
|
||||
61
web/data/logs.html
Normal file
61
web/data/logs.html
Normal file
@@ -0,0 +1,61 @@
|
||||
{{ define "content" }}
|
||||
|
||||
<main role="main" class="inner DAU">
|
||||
<h1 class="DAU-heading">Logs</h1>
|
||||
<p class="lead">Discord-auto-upload logs</p>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm">
|
||||
<button type="button" onClick="debug=1; get_logs();" class="btn btn-primary">all logs</button>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<button type="button" onClick="debug=0; get_logs();" class="btn btn-primary">no debug</button>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<button type="button" id="scroll-button" onClick="toggle_scroll();" class="btn btn-primary">disable auto-scroll</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<pre id="logs" class="text-left pre-scrollable">
|
||||
</pre>
|
||||
</main>
|
||||
|
||||
{{ end }}
|
||||
|
||||
{{ define "js" }}
|
||||
|
||||
<script>
|
||||
var debug = 0;
|
||||
var scrl = true;
|
||||
$(document).ready(function() {
|
||||
get_logs();
|
||||
setInterval(function() { get_logs(); }, 1000);
|
||||
});
|
||||
|
||||
function toggle_scroll() {
|
||||
scrl = !scrl;
|
||||
if (scrl) {
|
||||
$('#scroll-button').text('disable auto-scroll');
|
||||
}
|
||||
else {
|
||||
$('#scroll-button').text('auto-scroll');
|
||||
}
|
||||
}
|
||||
|
||||
function get_logs() {
|
||||
$.ajax({ method: 'get', url: '/rest/logs', data: { debug : debug }})
|
||||
.done(function(data) {
|
||||
$('#logs').text(data);
|
||||
console.log('scrl is ', scrl);
|
||||
if (scrl) {
|
||||
$('#logs').scrollTop(10000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
{{ end }}
|
||||
45
web/data/uploads.html
Normal file
45
web/data/uploads.html
Normal file
@@ -0,0 +1,45 @@
|
||||
{{ define "content" }}
|
||||
|
||||
<main role="main" class="inner DAU">
|
||||
<h1 class="DAU-heading">Uploads</h1>
|
||||
<p class="lead">Discord-auto-upload uploads</p>
|
||||
|
||||
<table class="table table-condensed table-dark">
|
||||
<thead>
|
||||
<tr><th>uploaded</th><th>dt</th><th>thumb</th></tr>
|
||||
</thead>
|
||||
<tbody id="uploads">
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</main>
|
||||
|
||||
{{ end }}
|
||||
|
||||
{{ define "js" }}
|
||||
<script>
|
||||
|
||||
$(document).ready(function() {
|
||||
get_uploads();
|
||||
});
|
||||
|
||||
function get_uploads() {
|
||||
$.ajax({ method: 'get', url: '/rest/uploads'})
|
||||
.done(function(data) {
|
||||
console.log(data);
|
||||
$('#uploads').empty();
|
||||
if (! data) { return }
|
||||
data.forEach(i => {
|
||||
// {uploaded: true, uploaded_at: "2021-06-08T21:59:52.855936+09:30", url: "https://cdn.discordapp.com/attachments/849615269706203171/851800197046468628/dau736004285.png", width: 640, height: 640}
|
||||
console.log(i);
|
||||
row = $('<tr>');
|
||||
row.append($('<td>').text(i.uploaded ? 'yes' : 'no'));
|
||||
row.append($('<td>').text(i.uploaded_at));
|
||||
row.append($('<td>').html($('<img>', { width : i.width/10, height : i.height/10, src : i.url })));
|
||||
$('#uploads').prepend(row);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
{{ end }}
|
||||
66
web/data/wrapper.tmpl
Normal file
66
web/data/wrapper.tmpl
Normal file
@@ -0,0 +1,66 @@
|
||||
{{ define "layout" }}
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous">
|
||||
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-Piv4xVNRyMGpqkS2by6br4gNJ7DXjqk09RmUpJ8jgGtD7zP9yug3goQfGII0yAns" crossorigin="anonymous"></script>
|
||||
|
||||
|
||||
<style>
|
||||
.bd-placeholder-img {
|
||||
font-size: 1.125rem;
|
||||
text-anchor: middle;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.bd-placeholder-img-lg {
|
||||
font-size: 3.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Custom styles for this template -->
|
||||
<link href="/dau.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body class="text-center">
|
||||
|
||||
<div class="DAU-container d-flex w-100 h-100 p-3 mx-auto flex-column">
|
||||
<header class="masthead mb-auto">
|
||||
<div class="inner">
|
||||
<h3 class="masthead-brand">discord-auto-upload ({{.Version}})</h3>
|
||||
<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 "uploads.html"}} active {{ end }}" href="/uploads.html">Uploads</a>
|
||||
<a class="nav-link {{ if eq .Path "logs.html"}} active {{ end }}" href="/logs.html">Logs</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{{ template "content" . }}
|
||||
|
||||
|
||||
<footer class="mastfoot mt-auto">
|
||||
<div class="inner">
|
||||
<!-- <p>DAU template for <a href="https://getbootstrap.com/">Bootstrap</a>, by <a href="https://twitter.com/mdo">@mdo</a>.</p> -->
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
|
||||
</body>
|
||||
{{ template "js" . }}
|
||||
</html>
|
||||
|
||||
{{ end }}
|
||||
@@ -1,24 +1,27 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"log"
|
||||
"mime"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"text/template"
|
||||
"strings"
|
||||
|
||||
"github.com/tardisx/discord-auto-upload/assets"
|
||||
"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"
|
||||
)
|
||||
|
||||
//go:embed data
|
||||
var webFS embed.FS
|
||||
|
||||
// DAUWebServer - stuff for the web server
|
||||
type DAUWebServer struct {
|
||||
ConfigChange chan int
|
||||
@@ -40,44 +43,49 @@ type errorResponse struct {
|
||||
}
|
||||
|
||||
func getStatic(w http.ResponseWriter, r *http.Request) {
|
||||
// haha this is dumb and I should change it
|
||||
re := regexp.MustCompile(`[^a-zA-Z0-9\.]`)
|
||||
path := r.URL.Path[1:]
|
||||
sanitized_path := re.ReplaceAll([]byte(path), []byte("_"))
|
||||
|
||||
if string(sanitized_path) == "" {
|
||||
sanitized_path = []byte("index.html")
|
||||
path := r.URL.Path
|
||||
path = strings.TrimLeft(path, "/")
|
||||
if path == "" {
|
||||
path = "index.html"
|
||||
}
|
||||
|
||||
data, err := assets.Asset(string(sanitized_path))
|
||||
if err != nil {
|
||||
// Asset was not found.
|
||||
fmt.Fprintln(w, err)
|
||||
}
|
||||
extension := filepath.Ext(string(path))
|
||||
|
||||
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)))
|
||||
|
||||
t, err := template.ParseFS(webFS, "data/wrapper.tmpl", "data/"+path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
log.Printf("req: %s", r.URL.Path)
|
||||
|
||||
var b struct {
|
||||
Body string
|
||||
Path string
|
||||
Version string
|
||||
}
|
||||
b.Body = string(data)
|
||||
b.Path = string(sanitized_path)
|
||||
b.Path = path
|
||||
b.Version = version.CurrentVersion
|
||||
t.Execute(w, b)
|
||||
|
||||
err = t.ExecuteTemplate(w, "layout", b)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
} else {
|
||||
otherStatic, err := webFS.ReadFile("data/" + path)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("problem with '%s': %v", path, err)
|
||||
}
|
||||
w.Header().Set("Content-Type", mime.TypeByExtension(extension))
|
||||
|
||||
w.Write(otherStatic)
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user