Continue changes to allow uploads to be "pending" so a decision can be made to either upload or skip them (and ultimately, edit as well).
This commit is contained in:
parent
e1f18b104f
commit
42fb7a2003
1
go.mod
1
go.mod
@ -5,6 +5,7 @@ go 1.16
|
|||||||
require (
|
require (
|
||||||
github.com/fogleman/gg v1.3.0
|
github.com/fogleman/gg v1.3.0
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||||
|
github.com/gorilla/mux v1.8.0 // indirect
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
golang.org/x/image v0.0.0-20210504121937-7319ad40d33e
|
golang.org/x/image v0.0.0-20210504121937-7319ad40d33e
|
||||||
golang.org/x/mod v0.4.2
|
golang.org/x/mod v0.4.2
|
||||||
|
2
go.sum
2
go.sum
@ -2,6 +2,8 @@ github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
|
|||||||
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||||
|
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||||
|
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
@ -15,6 +15,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fogleman/gg"
|
"github.com/fogleman/gg"
|
||||||
@ -26,13 +27,16 @@ import (
|
|||||||
type State string
|
type State string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
StatePending State = "Pending"
|
StatePending State = "Pending" // waiting for decision to upload (could be edited)
|
||||||
StateQueued State = "Queued"
|
StateQueued State = "Queued" // ready for upload
|
||||||
StateUploading State = "Uploading"
|
StateUploading State = "Uploading" // uploading
|
||||||
StateComplete State = "Complete"
|
StateComplete State = "Complete" // finished successfully
|
||||||
StateFailed State = "Failed"
|
StateFailed State = "Failed" // failed
|
||||||
|
StateSkipped State = "Skipped" // user did not want to upload
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var currentId int32
|
||||||
|
|
||||||
type HTTPClient interface {
|
type HTTPClient interface {
|
||||||
Do(req *http.Request) (*http.Response, error)
|
Do(req *http.Request) (*http.Response, error)
|
||||||
}
|
}
|
||||||
@ -42,10 +46,11 @@ type Uploader struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Upload struct {
|
type Upload struct {
|
||||||
|
Id int32 `json:"id"`
|
||||||
UploadedAt time.Time `json:"uploaded_at"`
|
UploadedAt time.Time `json:"uploaded_at"`
|
||||||
|
|
||||||
originalFilename string // path on the local disk
|
OriginalFilename string `json:"original_file"` // path on the local disk
|
||||||
filenameToUpload string // post-watermark, or just original if unwatermarked
|
TemporaryFileToUpload string // post-watermark, or just original if unwatermarked
|
||||||
|
|
||||||
webhookURL string
|
webhookURL string
|
||||||
|
|
||||||
@ -71,8 +76,10 @@ func NewUploader() *Uploader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *Uploader) AddFile(file string, conf config.Watcher) {
|
func (u *Uploader) AddFile(file string, conf config.Watcher) {
|
||||||
|
atomic.AddInt32(¤tId, 1)
|
||||||
thisUpload := Upload{
|
thisUpload := Upload{
|
||||||
originalFilename: file,
|
Id: currentId,
|
||||||
|
OriginalFilename: file,
|
||||||
watermark: !conf.NoWatermark,
|
watermark: !conf.NoWatermark,
|
||||||
webhookURL: conf.WebHookURL,
|
webhookURL: conf.WebHookURL,
|
||||||
usernameOverride: conf.Username,
|
usernameOverride: conf.Username,
|
||||||
@ -92,7 +99,7 @@ func (u *Uploader) Upload() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *Upload) processUpload() error {
|
func (u *Upload) processUpload() error {
|
||||||
daulog.SendLog(fmt.Sprintf("Uploading: %s", u.originalFilename), daulog.LogTypeInfo)
|
daulog.SendLog(fmt.Sprintf("Uploading: %s", u.OriginalFilename), daulog.LogTypeInfo)
|
||||||
|
|
||||||
if u.webhookURL == "" {
|
if u.webhookURL == "" {
|
||||||
daulog.SendLog("WebHookURL is not configured - cannot upload!", daulog.LogTypeError)
|
daulog.SendLog("WebHookURL is not configured - cannot upload!", daulog.LogTypeError)
|
||||||
@ -103,7 +110,7 @@ func (u *Upload) processUpload() error {
|
|||||||
daulog.SendLog("Watermarking image", daulog.LogTypeInfo)
|
daulog.SendLog("Watermarking image", daulog.LogTypeInfo)
|
||||||
u.applyWatermark()
|
u.applyWatermark()
|
||||||
} else {
|
} else {
|
||||||
u.filenameToUpload = u.originalFilename
|
u.TemporaryFileToUpload = u.OriginalFilename
|
||||||
}
|
}
|
||||||
|
|
||||||
extraParams := map[string]string{}
|
extraParams := map[string]string{}
|
||||||
@ -130,7 +137,7 @@ func (u *Upload) processUpload() error {
|
|||||||
var retriesRemaining = 5
|
var retriesRemaining = 5
|
||||||
for retriesRemaining > 0 {
|
for retriesRemaining > 0 {
|
||||||
|
|
||||||
request, err := newfileUploadRequest(u.webhookURL, extraParams, "file", u.filenameToUpload)
|
request, err := newfileUploadRequest(u.webhookURL, extraParams, "file", u.TemporaryFileToUpload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("error creating upload request: %s", err)
|
log.Printf("error creating upload request: %s", err)
|
||||||
return fmt.Errorf("could not create upload request: %s", err)
|
return fmt.Errorf("could not create upload request: %s", err)
|
||||||
@ -216,8 +223,8 @@ func (u *Upload) processUpload() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if u.watermark {
|
if u.watermark {
|
||||||
daulog.SendLog(fmt.Sprintf("Removing temporary file: %s", u.filenameToUpload), daulog.LogTypeDebug)
|
daulog.SendLog(fmt.Sprintf("Removing temporary file: %s", u.TemporaryFileToUpload), daulog.LogTypeDebug)
|
||||||
os.Remove(u.filenameToUpload)
|
os.Remove(u.TemporaryFileToUpload)
|
||||||
}
|
}
|
||||||
|
|
||||||
if retriesRemaining == 0 {
|
if retriesRemaining == 0 {
|
||||||
@ -261,7 +268,7 @@ func newfileUploadRequest(uri string, params map[string]string, paramName, path
|
|||||||
|
|
||||||
func (u *Upload) applyWatermark() {
|
func (u *Upload) applyWatermark() {
|
||||||
|
|
||||||
reader, err := os.Open(u.originalFilename)
|
reader, err := os.Open(u.OriginalFilename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -271,7 +278,7 @@ func (u *Upload) applyWatermark() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
daulog.SendLog(fmt.Sprintf("Cannot decode image: %v - skipping watermarking", err), daulog.LogTypeError)
|
daulog.SendLog(fmt.Sprintf("Cannot decode image: %v - skipping watermarking", err), daulog.LogTypeError)
|
||||||
u.watermark = false
|
u.watermark = false
|
||||||
u.filenameToUpload = u.originalFilename
|
u.TemporaryFileToUpload = u.OriginalFilename
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
bounds := im.Bounds()
|
bounds := im.Bounds()
|
||||||
@ -302,7 +309,7 @@ func (u *Upload) applyWatermark() {
|
|||||||
actualName := tempfile.Name() + ".png"
|
actualName := tempfile.Name() + ".png"
|
||||||
|
|
||||||
dc.SavePNG(actualName)
|
dc.SavePNG(actualName)
|
||||||
u.filenameToUpload = actualName
|
u.TemporaryFileToUpload = actualName
|
||||||
}
|
}
|
||||||
|
|
||||||
func sleepForRetries(retry int) {
|
func sleepForRetries(retry int) {
|
||||||
|
@ -43,7 +43,7 @@ func TestSuccessfulUpload(t *testing.T) {
|
|||||||
// we will not really be uploading it here
|
// we will not really be uploading it here
|
||||||
f, _ := os.CreateTemp("", "dautest-upload-*")
|
f, _ := os.CreateTemp("", "dautest-upload-*")
|
||||||
defer os.Remove(f.Name())
|
defer os.Remove(f.Name())
|
||||||
u := Upload{webhookURL: "https://127.0.0.1/", originalFilename: f.Name()}
|
u := Upload{webhookURL: "https://127.0.0.1/", OriginalFilename: f.Name()}
|
||||||
u.Client = &MockClient{DoFunc: DoGoodUpload}
|
u.Client = &MockClient{DoFunc: DoGoodUpload}
|
||||||
err := u.processUpload()
|
err := u.processUpload()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -62,7 +62,7 @@ func TestTooBigUpload(t *testing.T) {
|
|||||||
// we will not really be uploading it here
|
// we will not really be uploading it here
|
||||||
f, _ := os.CreateTemp("", "dautest-upload-*")
|
f, _ := os.CreateTemp("", "dautest-upload-*")
|
||||||
defer os.Remove(f.Name())
|
defer os.Remove(f.Name())
|
||||||
u := Upload{webhookURL: "https://127.0.0.1/", originalFilename: f.Name()}
|
u := Upload{webhookURL: "https://127.0.0.1/", OriginalFilename: f.Name()}
|
||||||
u.Client = &MockClient{DoFunc: DoTooBigUpload}
|
u.Client = &MockClient{DoFunc: DoTooBigUpload}
|
||||||
err := u.processUpload()
|
err := u.processUpload()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -160,7 +160,6 @@
|
|||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
{{ define "js" }}
|
{{ define "js" }}
|
||||||
<script src="//unpkg.com/alpinejs" defer></script>
|
|
||||||
<script>
|
<script>
|
||||||
function configuration() {
|
function configuration() {
|
||||||
return {
|
return {
|
||||||
|
@ -1,45 +1,129 @@
|
|||||||
{{ define "content" }}
|
{{ define "content" }}
|
||||||
|
|
||||||
<main role="main" class="inner DAU">
|
<main role="main" x-data="uploads()" x-init="get_uploads();" class="inner DAU">
|
||||||
<h1 class="DAU-heading">Uploads</h1>
|
<h1 class="DAU-heading">Uploads</h1>
|
||||||
<p class="lead">Discord-auto-upload uploads</p>
|
<p class="lead">Discord-auto-upload uploads</p>
|
||||||
|
|
||||||
|
<h2>Pending uploads</h2>
|
||||||
|
|
||||||
<table class="table table-condensed table-dark">
|
<table class="table table-condensed table-dark">
|
||||||
<thead>
|
<thead>
|
||||||
<tr><th>uploaded</th><th>dt</th><th>thumb</th></tr>
|
<tr>
|
||||||
|
<th>filename</th>
|
||||||
|
<th>actions</th>
|
||||||
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody id="uploads">
|
<tbody>
|
||||||
|
<template x-for="ul in pending">
|
||||||
|
<tr>
|
||||||
|
<td x-text="ul.original_file"></td>
|
||||||
|
<td>
|
||||||
|
<button @click="start_upload(ul.id)" type="button" class="btn btn-primary">upload</button>
|
||||||
|
<button @click="skip_upload(ul.id)" type="button" class="btn btn-primary">reject</button>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</template>
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<h2>Current uploads</h2>
|
||||||
|
|
||||||
|
<table class="table table-condensed table-dark">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>filename</th>
|
||||||
|
<th>actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
|
||||||
|
<template x-for="ul in uploads">
|
||||||
|
<tr>
|
||||||
|
<td x-text="ul.original_file"></td>
|
||||||
|
<td>
|
||||||
|
<button @click="start_upload(ul.id)" type="button" class="btn btn-primary">upload</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2>Completed uploads</h2>
|
||||||
|
|
||||||
|
<table class="table table-condensed table-dark">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>filename</th>
|
||||||
|
<th>state</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
|
||||||
|
<template x-for="ul in finished">
|
||||||
|
<tr>
|
||||||
|
<td x-text="ul.original_file"></td>
|
||||||
|
<td x-text="ul.state"></td>
|
||||||
|
</tr>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
{{ define "js" }}
|
{{ define "js" }}
|
||||||
<script>
|
<script>
|
||||||
|
function uploads() {
|
||||||
$(document).ready(function() {
|
return {
|
||||||
get_uploads();
|
pending: [], uploads: [], finished: [],
|
||||||
});
|
start_upload(id) {
|
||||||
|
console.log(id);
|
||||||
function get_uploads() {
|
fetch('/rest/upload/'+id+'/start', {method: 'POST'})
|
||||||
$.ajax({ method: 'get', url: '/rest/uploads'})
|
.then(response => response.json()) // convert to json
|
||||||
.done(function(data) {
|
.then(json => {
|
||||||
console.log(data);
|
console.log(json);
|
||||||
$('#uploads').empty();
|
})
|
||||||
if (! data) { return }
|
},
|
||||||
data.forEach(i => {
|
skip_upload(id) {
|
||||||
// {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(id);
|
||||||
console.log(i);
|
fetch('/rest/upload/'+id+'/skip', {method: 'POST'})
|
||||||
row = $('<tr>');
|
.then(response => response.json()) // convert to json
|
||||||
row.append($('<td>').text(i.uploaded ? 'yes' : 'no'));
|
.then(json => {
|
||||||
row.append($('<td>').text(i.uploaded_at));
|
console.log(json);
|
||||||
row.append($('<td>').html($('<img>', { width : i.width/10, height : i.height/10, src : i.url })));
|
})
|
||||||
$('#uploads').prepend(row);
|
},
|
||||||
|
get_uploads() {
|
||||||
|
fetch('/rest/uploads')
|
||||||
|
.then(response => response.json()) // convert to json
|
||||||
|
.then(json => {
|
||||||
|
this.pending = [];
|
||||||
|
this.uploads = [];
|
||||||
|
this.finished = [];
|
||||||
|
json.forEach(ul => {
|
||||||
|
if (ul.state == 'Pending') {
|
||||||
|
this.pending.push(ul);
|
||||||
|
}
|
||||||
|
else if (ul.state == 'Complete' || ul.state == 'Failed' || ul.state == 'Skipped') {
|
||||||
|
this.finished.push(ul)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.uploads.push(ul);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
this.config = json;
|
||||||
}
|
console.log(json);
|
||||||
|
let self = this;
|
||||||
|
setTimeout(function() { self.get_uploads(); } , 1000);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
<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">
|
<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://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>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-Piv4xVNRyMGpqkS2by6br4gNJ7DXjqk09RmUpJ8jgGtD7zP9yug3goQfGII0yAns" crossorigin="anonymous"></script>
|
||||||
|
<script src="//unpkg.com/alpinejs" defer></script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.bd-placeholder-img {
|
.bd-placeholder-img {
|
||||||
|
118
web/server.go
118
web/server.go
@ -10,8 +10,11 @@ import (
|
|||||||
"mime"
|
"mime"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gorilla/mux"
|
||||||
"github.com/tardisx/discord-auto-upload/config"
|
"github.com/tardisx/discord-auto-upload/config"
|
||||||
daulog "github.com/tardisx/discord-auto-upload/log"
|
daulog "github.com/tardisx/discord-auto-upload/log"
|
||||||
"github.com/tardisx/discord-auto-upload/upload"
|
"github.com/tardisx/discord-auto-upload/upload"
|
||||||
@ -23,6 +26,19 @@ type WebService struct {
|
|||||||
Uploader *upload.Uploader
|
Uploader *upload.Uploader
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ErrorResponse struct {
|
||||||
|
Error string `json:"error"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type StartUploadRequest struct {
|
||||||
|
Id int32 `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type StartUploadResponse struct {
|
||||||
|
Success bool `json:"success"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
//go:embed data
|
//go:embed data
|
||||||
var webFS embed.FS
|
var webFS embed.FS
|
||||||
|
|
||||||
@ -43,6 +59,7 @@ func (ws *WebService) getStatic(w http.ResponseWriter, r *http.Request) {
|
|||||||
extension := filepath.Ext(string(path))
|
extension := filepath.Ext(string(path))
|
||||||
|
|
||||||
if extension == ".html" { // html file
|
if extension == ".html" { // html file
|
||||||
|
|
||||||
t, err := template.ParseFS(webFS, "data/wrapper.tmpl", "data/"+path)
|
t, err := template.ParseFS(webFS, "data/wrapper.tmpl", "data/"+path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
daulog.SendLog(fmt.Sprintf("when fetching: %s got: %s", path, err), daulog.LogTypeError)
|
daulog.SendLog(fmt.Sprintf("when fetching: %s got: %s", path, err), daulog.LogTypeError)
|
||||||
@ -109,33 +126,23 @@ func (ws *WebService) getLogs(w http.ResponseWriter, r *http.Request) {
|
|||||||
func (ws *WebService) handleConfig(w http.ResponseWriter, r *http.Request) {
|
func (ws *WebService) handleConfig(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method == "POST" {
|
if r.Method == "POST" {
|
||||||
|
|
||||||
type ErrorResponse struct {
|
|
||||||
Error string `json:"error"`
|
|
||||||
}
|
|
||||||
|
|
||||||
newConfig := config.ConfigV2{}
|
newConfig := config.ConfigV2{}
|
||||||
|
|
||||||
defer r.Body.Close()
|
defer r.Body.Close()
|
||||||
b, err := ioutil.ReadAll(r.Body)
|
b, err := ioutil.ReadAll(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(400)
|
returnJSONError(w, "could not read body?")
|
||||||
w.Write([]byte("bad body"))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = json.Unmarshal(b, &newConfig)
|
err = json.Unmarshal(b, &newConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(400)
|
returnJSONError(w, "badly formed JSON")
|
||||||
j, _ := json.Marshal(ErrorResponse{Error: "badly formed JSON"})
|
|
||||||
w.Write(j)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ws.Config.Config = &newConfig
|
ws.Config.Config = &newConfig
|
||||||
err = ws.Config.Save()
|
err = ws.Config.Save()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(400)
|
returnJSONError(w, err.Error())
|
||||||
j, _ := json.Marshal(ErrorResponse{Error: err.Error()})
|
|
||||||
w.Write(j)
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// config has changed, so tell the world
|
// config has changed, so tell the world
|
||||||
@ -155,27 +162,92 @@ func (ws *WebService) getUploads(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
text, err := json.Marshal(ups)
|
text, err := json.Marshal(ups)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
daulog.SendLog(fmt.Sprintf("err: %v", err), daulog.LogTypeError)
|
// not sure how this would happen, so we probably want to find out the hard way
|
||||||
w.Write([]byte("could not marshall uploads?"))
|
panic(err)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
w.Write([]byte(text))
|
w.Write([]byte(text))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ws *WebService) modifyUpload(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
if r.Method == "POST" {
|
||||||
|
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
change := vars["change"]
|
||||||
|
id, err := strconv.ParseInt(vars["id"], 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
returnJSONError(w, "bad id")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, anUpload := range ws.Uploader.Uploads {
|
||||||
|
if anUpload.Id == int32(id) {
|
||||||
|
if anUpload.State == upload.StatePending {
|
||||||
|
if change == "start" {
|
||||||
|
anUpload.State = upload.StateQueued
|
||||||
|
res := StartUploadResponse{Success: true, Message: "upload queued"}
|
||||||
|
resString, _ := json.Marshal(res)
|
||||||
|
w.Write(resString)
|
||||||
|
return
|
||||||
|
} else if change == "skip" {
|
||||||
|
anUpload.State = upload.StateSkipped
|
||||||
|
res := StartUploadResponse{Success: true, Message: "upload skipped"}
|
||||||
|
resString, _ := json.Marshal(res)
|
||||||
|
w.Write(resString)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
returnJSONError(w, "bad change type")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res := StartUploadResponse{Success: false, Message: "upload does not exist, or already queued"}
|
||||||
|
resString, _ := json.Marshal(res)
|
||||||
|
w.WriteHeader(400)
|
||||||
|
w.Write(resString)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
returnJSONError(w, "bad request")
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (ws *WebService) StartWebServer() {
|
func (ws *WebService) StartWebServer() {
|
||||||
|
|
||||||
http.HandleFunc("/", ws.getStatic)
|
r := mux.NewRouter()
|
||||||
|
|
||||||
http.HandleFunc("/rest/logs", ws.getLogs)
|
r.HandleFunc("/rest/logs", ws.getLogs)
|
||||||
http.HandleFunc("/rest/uploads", ws.getUploads)
|
r.HandleFunc("/rest/uploads", ws.getUploads)
|
||||||
http.HandleFunc("/rest/config", ws.handleConfig)
|
r.HandleFunc("/rest/upload/{id:[0-9]+}/{change}", ws.modifyUpload)
|
||||||
|
|
||||||
|
r.HandleFunc("/rest/config", ws.handleConfig)
|
||||||
|
r.PathPrefix("/").HandlerFunc(ws.getStatic)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
listen := fmt.Sprintf(":%d", ws.Config.Config.Port)
|
listen := fmt.Sprintf(":%d", ws.Config.Config.Port)
|
||||||
log.Printf("Starting web server on http://localhost%s", listen)
|
log.Printf("Starting web server on http://localhost%s", listen)
|
||||||
err := http.ListenAndServe(listen, nil) // set listen port
|
|
||||||
if err != nil {
|
srv := &http.Server{
|
||||||
log.Fatal("ListenAndServe: ", err)
|
Handler: r,
|
||||||
|
Addr: listen,
|
||||||
|
// Good practice: enforce timeouts for servers you create!
|
||||||
|
WriteTimeout: 15 * time.Second,
|
||||||
|
ReadTimeout: 15 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Fatal(srv.ListenAndServe())
|
||||||
|
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func returnJSONError(w http.ResponseWriter, errMessage string) {
|
||||||
|
w.WriteHeader(400)
|
||||||
|
errJSON := ErrorResponse{
|
||||||
|
Error: errMessage,
|
||||||
|
}
|
||||||
|
errString, _ := json.Marshal(errJSON)
|
||||||
|
w.Write(errString)
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user