Compare commits
10 Commits
refactor-a
...
v0.13.0-al
| Author | SHA1 | Date | |
|---|---|---|---|
| 529bea0a97 | |||
| 76dbbacd98 | |||
| ba31f52ee2 | |||
| 779f9e1992 | |||
| 553337bfab | |||
| 73c74cd37e | |||
| 2bd62a95a4 | |||
| 3497bfd194 | |||
| ada43b176b | |||
| 326807b395 |
45
.goreleaser.yaml
Normal file
45
.goreleaser.yaml
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
before:
|
||||||
|
hooks:
|
||||||
|
# clean up/install modules
|
||||||
|
- go mod tidy
|
||||||
|
- "go run tools/windows_metadata/release.go v{{- .Version }}"
|
||||||
|
builds:
|
||||||
|
- main:
|
||||||
|
hooks:
|
||||||
|
pre:
|
||||||
|
- "rm -f resource.syso"
|
||||||
|
- "go generate"
|
||||||
|
ignore:
|
||||||
|
- goos: windows
|
||||||
|
goarch: arm64
|
||||||
|
ldflags:
|
||||||
|
- '{{ if eq .Os "windows" }}-H=windowsgui{{ end }}'
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
- windows
|
||||||
|
- darwin
|
||||||
|
archives:
|
||||||
|
- replacements:
|
||||||
|
darwin: Darwin
|
||||||
|
linux: Linux
|
||||||
|
windows: Windows
|
||||||
|
386: i386
|
||||||
|
amd64: x86_64
|
||||||
|
format_overrides:
|
||||||
|
- goos: windows
|
||||||
|
format: zip
|
||||||
|
checksum:
|
||||||
|
name_template: 'checksums.txt'
|
||||||
|
snapshot:
|
||||||
|
name_template: "{{ incpatch .Version }}-next"
|
||||||
|
changelog:
|
||||||
|
sort: asc
|
||||||
|
filters:
|
||||||
|
exclude:
|
||||||
|
- '^Merge:'
|
||||||
|
- '^docs:'
|
||||||
|
- '^test:'
|
||||||
|
- '^[Bb]ump'
|
||||||
|
- '^[Cc]lean'
|
||||||
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@@ -3,6 +3,8 @@
|
|||||||
"daulog",
|
"daulog",
|
||||||
"Debugf",
|
"Debugf",
|
||||||
"inconsolata",
|
"inconsolata",
|
||||||
|
"Infof",
|
||||||
|
"Markedup",
|
||||||
"skratchdot"
|
"skratchdot"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file.
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [v0.13.0] - 2022-11-01
|
||||||
|
|
||||||
|
- Resize images if needed to fit in discord 8Mb upload limits
|
||||||
|
|
||||||
|
|
||||||
|
## [v0.12.4] - 2022-09-15
|
||||||
|
|
||||||
|
- Document that watcher intervals are in seconds
|
||||||
|
|
||||||
## [v0.12.3] - 2022-05-09
|
## [v0.12.3] - 2022-05-09
|
||||||
|
|
||||||
- Fix a race condition occasionally causing multiple duplicate uploads
|
- Fix a race condition occasionally causing multiple duplicate uploads
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ no changes will take effect until the "Save All Configuration" button has been p
|
|||||||
### Global options
|
### Global options
|
||||||
|
|
||||||
* Server port - the port number the web server listens on. Requires restart
|
* Server port - the port number the web server listens on. Requires restart
|
||||||
* Watch interval - how often each watcher will check the directory for new files
|
* Watch interval - how often each watcher will check the directory for new files, in seconds
|
||||||
|
|
||||||
### Watcher configuration
|
### Watcher configuration
|
||||||
|
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
#!/usr/bin/env perl
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use warnings;
|
|
||||||
use Mojo::JSON qw/encode_json decode_json/;
|
|
||||||
use Mojo::File;
|
|
||||||
|
|
||||||
open my $fh, "<", "version/version.go" || die $!;
|
|
||||||
|
|
||||||
my $version;
|
|
||||||
while (<$fh>) {
|
|
||||||
$version = $1 if /^const\s+CurrentVersion.*?"v([\d\.]+)"/;
|
|
||||||
}
|
|
||||||
close $fh;
|
|
||||||
die "no version?" unless defined $version;
|
|
||||||
|
|
||||||
my @version_parts = split /\./, $version;
|
|
||||||
die "bad version?" unless defined $version_parts[2];
|
|
||||||
|
|
||||||
foreach (@version_parts) {
|
|
||||||
$_ = 0 + $_;
|
|
||||||
}
|
|
||||||
|
|
||||||
$version = "v$version";
|
|
||||||
|
|
||||||
# quit if tests fail
|
|
||||||
system("go test ./...") && die "not building release with failing tests";
|
|
||||||
|
|
||||||
# so lazy
|
|
||||||
system "rm", "-rf", "release", "dist";
|
|
||||||
system "mkdir", "release";
|
|
||||||
system "mkdir", "dist";
|
|
||||||
|
|
||||||
my %build = (
|
|
||||||
win => { env => { GOOS => 'windows', GOARCH => 'amd64' }, filename => 'dau.exe' },
|
|
||||||
linux => { env => { GOOS => 'linux', GOARCH => 'amd64' }, filename => 'dau' },
|
|
||||||
mac => { env => { GOOS => 'darwin', GOARCH => 'amd64' }, filename => 'dau' },
|
|
||||||
);
|
|
||||||
|
|
||||||
foreach my $type (keys %build) {
|
|
||||||
mkdir "release/$type";
|
|
||||||
}
|
|
||||||
|
|
||||||
add_extras();
|
|
||||||
|
|
||||||
foreach my $type (keys %build) {
|
|
||||||
print "building for $type\n";
|
|
||||||
local $ENV{GOOS} = $build{$type}->{env}->{GOOS};
|
|
||||||
local $ENV{GOARCH} = $build{$type}->{env}->{GOARCH};
|
|
||||||
|
|
||||||
unlink "resource.syso";
|
|
||||||
|
|
||||||
my @ldflags = ();
|
|
||||||
if ($type eq "win") {
|
|
||||||
# create the versioninfo.json based on the current version
|
|
||||||
my $tmp = Mojo::File->new("versioninfo.json-template")->slurp();
|
|
||||||
my $vdata = decode_json($tmp);
|
|
||||||
$vdata->{FixedFileInfo}->{FileVersion}->{Major} = $version_parts[0] ;
|
|
||||||
$vdata->{FixedFileInfo}->{FileVersion}->{Minor} = $version_parts[1] ;
|
|
||||||
$vdata->{FixedFileInfo}->{FileVersion}->{Patch} = $version_parts[2] ;
|
|
||||||
$vdata->{FixedFileInfo}->{ProductVersion}->{Major} = $version_parts[0] ;
|
|
||||||
$vdata->{FixedFileInfo}->{ProductVersion}->{Minor} = $version_parts[1] ;
|
|
||||||
$vdata->{FixedFileInfo}->{ProductVersion}->{Patch} = $version_parts[2] ;
|
|
||||||
|
|
||||||
$vdata->{StringFileInfo}->{ProductVersion} = $version;
|
|
||||||
|
|
||||||
Mojo::File->new("versioninfo.json")->spurt(encode_json($vdata));
|
|
||||||
|
|
||||||
@ldflags = (qw/ -ldflags -H=windowsgui/);
|
|
||||||
system "go", "generate";
|
|
||||||
}
|
|
||||||
warn join(' ', "go", "build", @ldflags, "-o", "release/$type/" . $build{$type}->{filename});
|
|
||||||
system "go", "build", @ldflags, "-o", "release/$type/" . $build{$type}->{filename};
|
|
||||||
system "zip", "-j", "dist/dau-$type-$version.zip", ( glob "release/$type/*" );
|
|
||||||
}
|
|
||||||
|
|
||||||
sub add_extras {
|
|
||||||
# we used to have a .bat file here, but no longer needed
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
//go:build !windows
|
//go:build darwin || linux
|
||||||
|
// +build darwin linux
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
|||||||
@@ -10,12 +10,10 @@ import (
|
|||||||
"github.com/tardisx/discord-auto-upload/version"
|
"github.com/tardisx/discord-auto-upload/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed dau.ico
|
|
||||||
var appIcon []byte
|
|
||||||
|
|
||||||
//go:generate goversioninfo
|
//go:generate goversioninfo
|
||||||
|
|
||||||
// -manifest=testdata/resource/goversioninfo.exe.manifest
|
//go:embed dau.ico
|
||||||
|
var appIcon []byte
|
||||||
|
|
||||||
func mainloop(c *config.ConfigService) {
|
func mainloop(c *config.ConfigService) {
|
||||||
systray.Run(func() { onReady(c) }, onExit)
|
systray.Run(func() { onReady(c) }, onExit)
|
||||||
|
|||||||
26
go.mod
26
go.mod
@@ -1,15 +1,27 @@
|
|||||||
module github.com/tardisx/discord-auto-upload
|
module github.com/tardisx/discord-auto-upload
|
||||||
|
|
||||||
go 1.16
|
go 1.22
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/fogleman/gg v1.3.0
|
github.com/fogleman/gg v1.3.0
|
||||||
github.com/getlantern/systray v1.2.1
|
github.com/getlantern/systray v1.2.2
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
github.com/gorilla/mux v1.8.1
|
||||||
github.com/gorilla/mux v1.8.0
|
|
||||||
github.com/josephspurrier/goversioninfo v1.4.0 // indirect
|
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
|
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
|
||||||
golang.org/x/image v0.0.0-20210504121937-7319ad40d33e
|
golang.org/x/image v0.15.0
|
||||||
golang.org/x/mod v0.4.2
|
golang.org/x/mod v0.17.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/getlantern/context v0.0.0-20190109183933-c447772a6520 // indirect
|
||||||
|
github.com/getlantern/errors v0.0.0-20190325191628-abdb3e3e36f7 // indirect
|
||||||
|
github.com/getlantern/golog v0.0.0-20190830074920-4ef2e798c2d7 // indirect
|
||||||
|
github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7 // indirect
|
||||||
|
github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55 // indirect
|
||||||
|
github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f // indirect
|
||||||
|
github.com/go-stack/stack v1.8.0 // indirect
|
||||||
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||||
|
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c // indirect
|
||||||
|
github.com/stretchr/testify v1.9.0 // indirect
|
||||||
|
golang.org/x/sys v0.1.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
51
go.sum
51
go.sum
@@ -1,7 +1,6 @@
|
|||||||
github.com/akavel/rsrc v0.10.2 h1:Zxm8V5eI1hW4gGaYsJQUhxpjkENuG91ki8B4zCrvEsw=
|
|
||||||
github.com/akavel/rsrc v0.10.2/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
|
|
||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
|
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/getlantern/context v0.0.0-20190109183933-c447772a6520 h1:NRUJuo3v3WGC/g5YiyF790gut6oQr5f3FBI88Wv0dx4=
|
github.com/getlantern/context v0.0.0-20190109183933-c447772a6520 h1:NRUJuo3v3WGC/g5YiyF790gut6oQr5f3FBI88Wv0dx4=
|
||||||
@@ -16,16 +15,16 @@ github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55 h1:XYzSdCbkzOC0F
|
|||||||
github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55/go.mod h1:6mmzY2kW1TOOrVy+r41Za2MxXM+hhqTtY3oBKd2AgFA=
|
github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55/go.mod h1:6mmzY2kW1TOOrVy+r41Za2MxXM+hhqTtY3oBKd2AgFA=
|
||||||
github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f h1:wrYrQttPS8FHIRSlsrcuKazukx/xqO/PpLZzZXsF+EA=
|
github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f h1:wrYrQttPS8FHIRSlsrcuKazukx/xqO/PpLZzZXsF+EA=
|
||||||
github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f/go.mod h1:D5ao98qkA6pxftxoqzibIBBrLSUli+kYnJqrgBf9cIA=
|
github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f/go.mod h1:D5ao98qkA6pxftxoqzibIBBrLSUli+kYnJqrgBf9cIA=
|
||||||
github.com/getlantern/systray v1.2.1 h1:udsC2k98v2hN359VTFShuQW6GGprRprw6kD6539JikI=
|
github.com/getlantern/systray v1.2.2 h1:dCEHtfmvkJG7HZ8lS/sLklTH4RKUcIsKrAD9sThoEBE=
|
||||||
github.com/getlantern/systray v1.2.1/go.mod h1:AecygODWIsBquJCJFop8MEQcJbWFfw/1yWbVabNgpCM=
|
github.com/getlantern/systray v1.2.2/go.mod h1:pXFOI1wwqwYXEhLPm9ZGjS2u/vVELeIgNMY5HvhHhcE=
|
||||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
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.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||||
github.com/josephspurrier/goversioninfo v1.4.0 h1:Puhl12NSHUSALHSuzYwPYQkqa2E1+7SrtAPJorKK0C8=
|
github.com/lxn/walk v0.0.0-20210112085537-c389da54e794/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ=
|
||||||
github.com/josephspurrier/goversioninfo v1.4.0/go.mod h1:JWzv5rKQr+MmW+LvM412ToT/IkYDZjaclF2pKDss8IY=
|
github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk=
|
||||||
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=
|
||||||
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
|
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
|
||||||
@@ -35,26 +34,16 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
|||||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA=
|
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA=
|
||||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
|
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
|
||||||
golang.org/x/image v0.0.0-20210504121937-7319ad40d33e h1:PzJMNfFQx+QO9hrC1GwZ4BoPGeNGhfeQEgcQFArEjPk=
|
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||||
golang.org/x/image v0.0.0-20210504121937-7319ad40d33e/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
|
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
gopkg.in/Knetic/govaluate.v3 v3.0.0/go.mod h1:csKLBORsPbafmSCGTEh3U7Ozmsuq8ZSIlKk1bcqph0E=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9 h1:YTzHMGlqJu67/uEo1lBv0n3wBXhXNeUbB1XfN2vmTm0=
|
|
||||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
|
|||||||
188
image/image.go
Normal file
188
image/image.go
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
// Package image is responsible for thumbnailing, resizing and watermarking
|
||||||
|
// images.
|
||||||
|
package image
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
i "image"
|
||||||
|
"image/jpeg"
|
||||||
|
"image/png"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
daulog "github.com/tardisx/discord-auto-upload/log"
|
||||||
|
|
||||||
|
"golang.org/x/image/draw"
|
||||||
|
)
|
||||||
|
|
||||||
|
// the filenames below are ordered in a specific way
|
||||||
|
// In the simplest case we only need the original filename.
|
||||||
|
// In more complex cases, we might have other files, created
|
||||||
|
// temporarily. These all need to be cleaned up.
|
||||||
|
// We upload the "final" file, depending on what actions have
|
||||||
|
// been taken.
|
||||||
|
|
||||||
|
type Store struct {
|
||||||
|
OriginalFilename string
|
||||||
|
OriginalFormat string // jpeg, png
|
||||||
|
ModifiedFilename string // if the user applied modifications
|
||||||
|
ResizedFilename string // if the file had to be resized to be uploaded
|
||||||
|
WatermarkedFilename string
|
||||||
|
MaxBytes int
|
||||||
|
Watermark bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadCloser returns an io.ReadCloser providing the imagedata
|
||||||
|
// with the manglings that have been requested
|
||||||
|
func (s *Store) ReadCloser() (io.ReadCloser, error) {
|
||||||
|
// determine format
|
||||||
|
s.determineFormat()
|
||||||
|
|
||||||
|
// check if we will fit the number of bytes, resize if necessary
|
||||||
|
err := s.resizeToUnder(int64(s.MaxBytes))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// the conundrum here is that the watermarking could modify the file size again, maybe going over
|
||||||
|
// the MaxBytes size. That would mostly be about jpeg compression levels I guess...
|
||||||
|
if s.Watermark {
|
||||||
|
s.applyWatermark()
|
||||||
|
}
|
||||||
|
|
||||||
|
// return the reader
|
||||||
|
f, err := os.Open(s.uploadSourceFilename())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Store) determineFormat() error {
|
||||||
|
file, err := os.Open(s.OriginalFilename)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("could not open file: %s", err))
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
_, format, err := i.Decode(file)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("could not decode file: %s", err))
|
||||||
|
}
|
||||||
|
s.OriginalFormat = format
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// resizeToUnder resizes the image, if necessary
|
||||||
|
func (s *Store) resizeToUnder(size int64) error {
|
||||||
|
fileToResize := s.uploadSourceFilename()
|
||||||
|
fi, err := os.Stat(s.uploadSourceFilename())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
currentSize := fi.Size()
|
||||||
|
if currentSize <= size {
|
||||||
|
return nil // nothing needs to be done
|
||||||
|
}
|
||||||
|
|
||||||
|
daulog.Infof("%s is %d bytes, need to resize to fit in %d", fileToResize, currentSize, size)
|
||||||
|
|
||||||
|
file, err := os.Open(fileToResize)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("could not open file: %s", err))
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
im, _, err := i.Decode(file)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("could not decode file: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the size is 10% too big, we reduce X and Y by 10% - this is overkill but should
|
||||||
|
// get us across the line in most cases
|
||||||
|
fraction := float64(currentSize) / float64(size) // say 1.1 for 10%
|
||||||
|
newXY := i.Point{
|
||||||
|
X: int(float64(im.Bounds().Max.X) / fraction),
|
||||||
|
Y: int(float64(im.Bounds().Max.Y) / fraction),
|
||||||
|
}
|
||||||
|
|
||||||
|
daulog.Infof("fraction is %f, will resize to %dx%d", fraction, newXY.X, newXY.Y)
|
||||||
|
|
||||||
|
dst := i.NewRGBA(i.Rect(0, 0, newXY.X, newXY.Y))
|
||||||
|
draw.BiLinear.Scale(dst, dst.Rect, im, im.Bounds(), draw.Over, nil)
|
||||||
|
|
||||||
|
resizedFile, err := os.CreateTemp("", "dau_resize_file_*")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.OriginalFormat == "png" {
|
||||||
|
err = png.Encode(resizedFile, dst)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if s.OriginalFormat == "jpeg" {
|
||||||
|
err = jpeg.Encode(resizedFile, dst, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
panic("unknown format " + s.OriginalFormat)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.ResizedFilename = resizedFile.Name()
|
||||||
|
resizedFile.Close()
|
||||||
|
|
||||||
|
fi, err = os.Stat(s.uploadSourceFilename())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
newSize := fi.Size()
|
||||||
|
if newSize <= size {
|
||||||
|
daulog.Infof("File resized, now %d", newSize)
|
||||||
|
return nil // nothing needs to be done
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("failed to resize: was %d, now %d, needed %d", currentSize, newSize, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// uploadSourceFilename gives us the filename, which might be a watermarked, resized
|
||||||
|
// or markedup version, depending on what has happened to this file.
|
||||||
|
func (s Store) uploadSourceFilename() string {
|
||||||
|
if s.WatermarkedFilename != "" {
|
||||||
|
return s.WatermarkedFilename
|
||||||
|
}
|
||||||
|
if s.ResizedFilename != "" {
|
||||||
|
return s.ResizedFilename
|
||||||
|
}
|
||||||
|
if s.ModifiedFilename != "" {
|
||||||
|
return s.ModifiedFilename
|
||||||
|
}
|
||||||
|
return s.OriginalFilename
|
||||||
|
}
|
||||||
|
|
||||||
|
// UploadFilename provides a name to be assigned to the upload on Discord
|
||||||
|
func (s Store) UploadFilename() string {
|
||||||
|
return "image." + s.OriginalFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup removes all the temporary files that we might have created
|
||||||
|
func (s Store) Cleanup() {
|
||||||
|
daulog.Infof("cleaning temporary files %#v", s)
|
||||||
|
|
||||||
|
if s.ModifiedFilename != "" {
|
||||||
|
daulog.Infof("removing %s", s.ModifiedFilename)
|
||||||
|
os.Remove(s.ModifiedFilename)
|
||||||
|
}
|
||||||
|
if s.ResizedFilename != "" {
|
||||||
|
daulog.Infof("removing %s", s.ResizedFilename)
|
||||||
|
os.Remove(s.ResizedFilename)
|
||||||
|
}
|
||||||
|
if s.WatermarkedFilename != "" {
|
||||||
|
daulog.Infof("removing %s", s.WatermarkedFilename)
|
||||||
|
os.Remove(s.WatermarkedFilename)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
package imageprocess
|
package image
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
i "image"
|
||||||
"image/png"
|
"image/png"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/tardisx/discord-auto-upload/upload"
|
|
||||||
"golang.org/x/image/draw"
|
"golang.org/x/image/draw"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -17,15 +16,21 @@ const (
|
|||||||
thumbnailMaxY = 128
|
thumbnailMaxY = 128
|
||||||
)
|
)
|
||||||
|
|
||||||
func (ip *Processor) ThumbPNG(ul *upload.Upload, which string, w io.Writer) error {
|
type ThumbType = string
|
||||||
|
|
||||||
|
const ThumbTypeOriginal = "orig"
|
||||||
|
const ThumbTypeMarkedUp = "markedup"
|
||||||
|
|
||||||
|
// ThumbPNG writes a thumbnail out to an io.Writer
|
||||||
|
func (ip *Store) ThumbPNG(t ThumbType, w io.Writer) error {
|
||||||
|
|
||||||
var filename string
|
var filename string
|
||||||
if which == "orig" {
|
if t == ThumbTypeOriginal {
|
||||||
filename = ul.OriginalFilename
|
filename = ip.OriginalFilename
|
||||||
} else if which == "markedup" {
|
} else if t == ThumbTypeMarkedUp {
|
||||||
filename = ul.MarkedUpFilename
|
filename = ip.ModifiedFilename
|
||||||
} else {
|
} else {
|
||||||
log.Fatal("was passed incorrect 'which' arg")
|
log.Fatal("was passed incorrect 'type' arg")
|
||||||
}
|
}
|
||||||
|
|
||||||
file, err := os.Open(filename)
|
file, err := os.Open(filename)
|
||||||
@@ -33,12 +38,12 @@ func (ip *Processor) ThumbPNG(ul *upload.Upload, which string, w io.Writer) erro
|
|||||||
return fmt.Errorf("could not open file: %s", err)
|
return fmt.Errorf("could not open file: %s", err)
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
im, _, err := image.Decode(file)
|
im, _, err := i.Decode(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not decode file: %s", err)
|
return fmt.Errorf("could not decode file: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
newXY := image.Point{}
|
newXY := i.Point{}
|
||||||
if im.Bounds().Max.X/thumbnailMaxX > im.Bounds().Max.Y/thumbnailMaxY {
|
if im.Bounds().Max.X/thumbnailMaxX > im.Bounds().Max.Y/thumbnailMaxY {
|
||||||
newXY.X = thumbnailMaxX
|
newXY.X = thumbnailMaxX
|
||||||
newXY.Y = im.Bounds().Max.Y / (im.Bounds().Max.X / thumbnailMaxX)
|
newXY.Y = im.Bounds().Max.Y / (im.Bounds().Max.X / thumbnailMaxX)
|
||||||
@@ -47,7 +52,7 @@ func (ip *Processor) ThumbPNG(ul *upload.Upload, which string, w io.Writer) erro
|
|||||||
newXY.X = im.Bounds().Max.X / (im.Bounds().Max.Y / thumbnailMaxY)
|
newXY.X = im.Bounds().Max.X / (im.Bounds().Max.Y / thumbnailMaxY)
|
||||||
}
|
}
|
||||||
|
|
||||||
dst := image.NewRGBA(image.Rect(0, 0, newXY.X, newXY.Y))
|
dst := i.NewRGBA(i.Rect(0, 0, newXY.X, newXY.Y))
|
||||||
draw.BiLinear.Scale(dst, dst.Rect, im, im.Bounds(), draw.Over, nil)
|
draw.BiLinear.Scale(dst, dst.Rect, im, im.Bounds(), draw.Over, nil)
|
||||||
|
|
||||||
png.Encode(w, dst)
|
png.Encode(w, dst)
|
||||||
64
image/watermark.go
Normal file
64
image/watermark.go
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package image
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
i "image"
|
||||||
|
"image/jpeg"
|
||||||
|
"image/png"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
daulog "github.com/tardisx/discord-auto-upload/log"
|
||||||
|
|
||||||
|
"github.com/fogleman/gg"
|
||||||
|
"golang.org/x/image/font/inconsolata"
|
||||||
|
)
|
||||||
|
|
||||||
|
// applyWatermark applies the watermark to the image
|
||||||
|
func (s *Store) applyWatermark() error {
|
||||||
|
|
||||||
|
in, err := os.Open(s.uploadSourceFilename())
|
||||||
|
|
||||||
|
defer in.Close()
|
||||||
|
|
||||||
|
im, _, err := i.Decode(in)
|
||||||
|
if err != nil {
|
||||||
|
daulog.Errorf("Cannot decode image: %v - skipping watermarking", err)
|
||||||
|
return fmt.Errorf("cannot decode image: %w", err)
|
||||||
|
}
|
||||||
|
bounds := im.Bounds()
|
||||||
|
// var S float64 = float64(bounds.Max.X)
|
||||||
|
|
||||||
|
dc := gg.NewContext(bounds.Max.X, bounds.Max.Y)
|
||||||
|
dc.Clear()
|
||||||
|
dc.SetRGB(0, 0, 0)
|
||||||
|
|
||||||
|
dc.SetFontFace(inconsolata.Regular8x16)
|
||||||
|
|
||||||
|
dc.DrawImage(im, 0, 0)
|
||||||
|
|
||||||
|
dc.DrawRoundedRectangle(0, float64(bounds.Max.Y-18.0), 320, float64(bounds.Max.Y), 0)
|
||||||
|
dc.SetRGB(0, 0, 0)
|
||||||
|
dc.Fill()
|
||||||
|
|
||||||
|
dc.SetRGB(1, 1, 1)
|
||||||
|
|
||||||
|
dc.DrawString("github.com/tardisx/discord-auto-upload", 5.0, float64(bounds.Max.Y)-5.0)
|
||||||
|
|
||||||
|
waterMarkedFile, err := os.CreateTemp("", "dau_watermark_file_*")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer waterMarkedFile.Close()
|
||||||
|
|
||||||
|
if s.OriginalFormat == "png" {
|
||||||
|
png.Encode(waterMarkedFile, dc.Image())
|
||||||
|
} else if s.OriginalFormat == "jpeg" {
|
||||||
|
jpeg.Encode(waterMarkedFile, dc.Image(), nil)
|
||||||
|
} else {
|
||||||
|
panic("Cannot handle " + s.OriginalFormat)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.WatermarkedFilename = waterMarkedFile.Name()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
package imageprocess
|
|
||||||
|
|
||||||
type Processor struct {
|
|
||||||
}
|
|
||||||
84
tools/windows_metadata/release.go
Normal file
84
tools/windows_metadata/release.go
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/mod/semver"
|
||||||
|
)
|
||||||
|
|
||||||
|
const versionInfoTemplate = `
|
||||||
|
{
|
||||||
|
"FixedFileInfo": {
|
||||||
|
"FileVersion": {
|
||||||
|
"Major": MAJOR,
|
||||||
|
"Minor": MINOR,
|
||||||
|
"Patch": PATCH,
|
||||||
|
"Build": 0
|
||||||
|
},
|
||||||
|
"ProductVersion": {
|
||||||
|
"Major": MAJOR,
|
||||||
|
"Minor": MINOR,
|
||||||
|
"Patch": PATCH,
|
||||||
|
"Build": 0
|
||||||
|
},
|
||||||
|
"FileFlagsMask": "3f",
|
||||||
|
"FileFlags ": "00",
|
||||||
|
"FileOS": "040004",
|
||||||
|
"FileType": "01",
|
||||||
|
"FileSubType": "00"
|
||||||
|
},
|
||||||
|
"StringFileInfo": {
|
||||||
|
"Comments": "",
|
||||||
|
"CompanyName": "tardisx@github",
|
||||||
|
"FileDescription": "https://github.com/tardisx/discord-auto-upload",
|
||||||
|
"FileVersion": "",
|
||||||
|
"InternalName": "",
|
||||||
|
"LegalCopyright": "https://github.com/tardisx/discord-auto-upload/blob/master/LICENSE",
|
||||||
|
"LegalTrademarks": "",
|
||||||
|
"OriginalFilename": "",
|
||||||
|
"PrivateBuild": "",
|
||||||
|
"ProductName": "discord-auto-upload",
|
||||||
|
"ProductVersion": "VERSION",
|
||||||
|
"SpecialBuild": ""
|
||||||
|
},
|
||||||
|
"VarFileInfo": {
|
||||||
|
"Translation": {
|
||||||
|
"LangID": "0409",
|
||||||
|
"CharsetID": "04B0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IconPath": "dau.ico",
|
||||||
|
"ManifestPath": ""
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
var nonAlphanumericRegex = regexp.MustCompile(`[^0-9]+`)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
version := os.Args[1]
|
||||||
|
if !semver.IsValid(version) {
|
||||||
|
panic("bad version" + version)
|
||||||
|
}
|
||||||
|
parts := strings.Split(version, ".")
|
||||||
|
if len(parts) < 3 {
|
||||||
|
log.Fatalf("bad version: %s", version)
|
||||||
|
}
|
||||||
|
|
||||||
|
parts[0] = nonAlphanumericRegex.ReplaceAllString(parts[0], "")
|
||||||
|
parts[1] = nonAlphanumericRegex.ReplaceAllString(parts[1], "")
|
||||||
|
parts[2] = nonAlphanumericRegex.ReplaceAllString(parts[2], "")
|
||||||
|
|
||||||
|
out := versionInfoTemplate
|
||||||
|
out = strings.Replace(out, "MAJOR", parts[0], -1)
|
||||||
|
out = strings.Replace(out, "MINOR", parts[1], -1)
|
||||||
|
out = strings.Replace(out, "PATCH", parts[2], -1)
|
||||||
|
out = strings.Replace(out, "VERSION", version, -1)
|
||||||
|
|
||||||
|
f, _ := os.Create("versioninfo.json")
|
||||||
|
f.Write([]byte(out))
|
||||||
|
f.Close()
|
||||||
|
|
||||||
|
}
|
||||||
123
upload/upload.go
123
upload/upload.go
@@ -7,33 +7,31 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fogleman/gg"
|
|
||||||
"github.com/tardisx/discord-auto-upload/config"
|
"github.com/tardisx/discord-auto-upload/config"
|
||||||
|
"github.com/tardisx/discord-auto-upload/image"
|
||||||
|
|
||||||
daulog "github.com/tardisx/discord-auto-upload/log"
|
daulog "github.com/tardisx/discord-auto-upload/log"
|
||||||
"golang.org/x/image/font/inconsolata"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type State string
|
type State string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
StatePending State = "Pending" // waiting for decision to upload (could be edited)
|
StatePending State = "Pending" // waiting for decision to upload (could be edited)
|
||||||
StateQueued State = "Queued" // ready for upload
|
StateQueued State = "Queued" // ready for upload
|
||||||
StateUploading State = "Uploading" // uploading
|
StateWatermarking State = "Adding Watermark" // thumbnail generation
|
||||||
StateComplete State = "Complete" // finished successfully
|
StateUploading State = "Uploading" // uploading
|
||||||
StateFailed State = "Failed" // failed
|
StateComplete State = "Complete" // finished successfully
|
||||||
StateSkipped State = "Skipped" // user did not want to upload
|
StateFailed State = "Failed" // failed
|
||||||
|
StateSkipped State = "Skipped" // user did not want to upload
|
||||||
)
|
)
|
||||||
|
|
||||||
var currentId int32
|
var currentId int32
|
||||||
@@ -51,13 +49,10 @@ type Upload struct {
|
|||||||
Id int32 `json:"id"`
|
Id int32 `json:"id"`
|
||||||
UploadedAt time.Time `json:"uploaded_at"`
|
UploadedAt time.Time `json:"uploaded_at"`
|
||||||
|
|
||||||
OriginalFilename string `json:"original_file"` // path on the local disk
|
Image *image.Store
|
||||||
MarkedUpFilename string `json:"markedup_file"` // a temporary file, if the user did some markup
|
|
||||||
|
|
||||||
webhookURL string
|
webhookURL string
|
||||||
|
|
||||||
watermark bool // should watermark
|
|
||||||
|
|
||||||
usernameOverride string
|
usernameOverride string
|
||||||
|
|
||||||
Url string `json:"url"` // url on the discord CDN
|
Url string `json:"url"` // url on the discord CDN
|
||||||
@@ -65,7 +60,8 @@ type Upload struct {
|
|||||||
Width int `json:"width"`
|
Width int `json:"width"`
|
||||||
Height int `json:"height"`
|
Height int `json:"height"`
|
||||||
|
|
||||||
State State `json:"state"`
|
State State `json:"state"`
|
||||||
|
StateReason string `json:"state_reason"`
|
||||||
|
|
||||||
Client HTTPClient `json:"-"`
|
Client HTTPClient `json:"-"`
|
||||||
}
|
}
|
||||||
@@ -82,16 +78,19 @@ func (u *Uploader) AddFile(file string, conf config.Watcher) {
|
|||||||
atomic.AddInt32(¤tId, 1)
|
atomic.AddInt32(¤tId, 1)
|
||||||
thisUpload := Upload{
|
thisUpload := Upload{
|
||||||
Id: currentId,
|
Id: currentId,
|
||||||
OriginalFilename: file,
|
UploadedAt: time.Time{},
|
||||||
watermark: !conf.NoWatermark,
|
Image: &image.Store{OriginalFilename: file, Watermark: !conf.NoWatermark, MaxBytes: 8_000_000},
|
||||||
webhookURL: conf.WebHookURL,
|
webhookURL: conf.WebHookURL,
|
||||||
usernameOverride: conf.Username,
|
usernameOverride: conf.Username,
|
||||||
|
Url: "",
|
||||||
State: StateQueued,
|
State: StateQueued,
|
||||||
|
Client: nil,
|
||||||
}
|
}
|
||||||
// if the user wants uploads to be held for editing etc,
|
// if the user wants uploads to be held for editing etc,
|
||||||
// set it to Pending instead
|
// set it to Pending instead
|
||||||
if conf.HoldUploads {
|
if conf.HoldUploads {
|
||||||
thisUpload.State = StatePending
|
thisUpload.State = StatePending
|
||||||
|
thisUpload.StateReason = ""
|
||||||
}
|
}
|
||||||
u.Uploads = append(u.Uploads, &thisUpload)
|
u.Uploads = append(u.Uploads, &thisUpload)
|
||||||
u.Lock.Unlock()
|
u.Lock.Unlock()
|
||||||
@@ -123,16 +122,8 @@ func (u *Uploader) UploadById(id int32) *Upload {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *Upload) RemoveMarkupTempFile() {
|
|
||||||
if len(u.MarkedUpFilename) > 0 {
|
|
||||||
os.Remove(u.MarkedUpFilename)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *Upload) processUpload() error {
|
func (u *Upload) processUpload() error {
|
||||||
daulog.Infof("Uploading: %s", u.OriginalFilename)
|
daulog.Infof("Uploading: %s", u.Image.OriginalFilename)
|
||||||
|
|
||||||
baseFilename := filepath.Base(u.OriginalFilename)
|
|
||||||
|
|
||||||
if u.webhookURL == "" {
|
if u.webhookURL == "" {
|
||||||
daulog.Error("WebHookURL is not configured - cannot upload!")
|
daulog.Error("WebHookURL is not configured - cannot upload!")
|
||||||
@@ -164,41 +155,14 @@ func (u *Upload) processUpload() error {
|
|||||||
for retriesRemaining > 0 {
|
for retriesRemaining > 0 {
|
||||||
|
|
||||||
// open an io.ReadCloser for the file we intend to upload
|
// open an io.ReadCloser for the file we intend to upload
|
||||||
var filedata *os.File
|
|
||||||
var err error
|
var err error
|
||||||
if len(u.MarkedUpFilename) > 0 {
|
|
||||||
filedata, err = os.Open(u.MarkedUpFilename)
|
imageData, err := u.Image.ReadCloser()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
daulog.Errorf("Error opening marked up file: %s", err)
|
panic(err)
|
||||||
retriesRemaining--
|
|
||||||
sleepForRetries(retriesRemaining)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
filedata, err = os.Open(u.OriginalFilename)
|
|
||||||
if err != nil {
|
|
||||||
daulog.Errorf("Error opening original file: %s", err)
|
|
||||||
retriesRemaining--
|
|
||||||
sleepForRetries(retriesRemaining)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var imageData io.Reader
|
request, err := newfileUploadRequest(u.webhookURL, extraParams, "file", u.Image.UploadFilename(), imageData)
|
||||||
if u.watermark {
|
|
||||||
daulog.Info("Watermarking image")
|
|
||||||
imageData, err = u.applyWatermark(filedata)
|
|
||||||
if err != nil {
|
|
||||||
daulog.Errorf("Error watermarking: %s", err)
|
|
||||||
retriesRemaining--
|
|
||||||
sleepForRetries(retriesRemaining)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
imageData = filedata
|
|
||||||
}
|
|
||||||
|
|
||||||
request, err := newfileUploadRequest(u.webhookURL, extraParams, "file", baseFilename, imageData)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
daulog.Errorf("error creating upload request: %s", err)
|
daulog.Errorf("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)
|
||||||
@@ -222,6 +186,7 @@ func (u *Upload) processUpload() error {
|
|||||||
// just fail immediately, we know this means the file was too big
|
// just fail immediately, we know this means the file was too big
|
||||||
daulog.Error("413 received - file too large")
|
daulog.Error("413 received - file too large")
|
||||||
u.State = StateFailed
|
u.State = StateFailed
|
||||||
|
u.StateReason = "discord API said file too large"
|
||||||
return errors.New("received 413 - file too large")
|
return errors.New("received 413 - file too large")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,6 +239,7 @@ func (u *Upload) processUpload() error {
|
|||||||
|
|
||||||
u.Url = a.URL
|
u.Url = a.URL
|
||||||
u.State = StateComplete
|
u.State = StateComplete
|
||||||
|
u.StateReason = ""
|
||||||
u.Width = a.Width
|
u.Width = a.Width
|
||||||
u.Height = a.Height
|
u.Height = a.Height
|
||||||
u.UploadedAt = time.Now()
|
u.UploadedAt = time.Now()
|
||||||
@@ -282,12 +248,13 @@ func (u *Upload) processUpload() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove any marked up file
|
// remove any temporary files
|
||||||
u.RemoveMarkupTempFile()
|
u.Image.Cleanup()
|
||||||
|
|
||||||
if retriesRemaining == 0 {
|
if retriesRemaining == 0 {
|
||||||
daulog.Error("Failed to upload, even after all retries")
|
daulog.Error("Failed to upload, even after all retries")
|
||||||
u.State = StateFailed
|
u.State = StateFailed
|
||||||
|
u.StateReason = "could not upload after all retries"
|
||||||
return errors.New("could not upload after all retries")
|
return errors.New("could not upload after all retries")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,40 +287,6 @@ func newfileUploadRequest(uri string, params map[string]string, paramName string
|
|||||||
return req, err
|
return req, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// applyWatermark applies the watermark to the image
|
|
||||||
func (u *Upload) applyWatermark(in *os.File) (io.Reader, error) {
|
|
||||||
|
|
||||||
defer in.Close()
|
|
||||||
|
|
||||||
im, _, err := image.Decode(in)
|
|
||||||
if err != nil {
|
|
||||||
daulog.Errorf("Cannot decode image: %v - skipping watermarking", err)
|
|
||||||
return nil, errors.New("cannot decode image")
|
|
||||||
}
|
|
||||||
bounds := im.Bounds()
|
|
||||||
// var S float64 = float64(bounds.Max.X)
|
|
||||||
|
|
||||||
dc := gg.NewContext(bounds.Max.X, bounds.Max.Y)
|
|
||||||
dc.Clear()
|
|
||||||
dc.SetRGB(0, 0, 0)
|
|
||||||
|
|
||||||
dc.SetFontFace(inconsolata.Regular8x16)
|
|
||||||
|
|
||||||
dc.DrawImage(im, 0, 0)
|
|
||||||
|
|
||||||
dc.DrawRoundedRectangle(0, float64(bounds.Max.Y-18.0), 320, float64(bounds.Max.Y), 0)
|
|
||||||
dc.SetRGB(0, 0, 0)
|
|
||||||
dc.Fill()
|
|
||||||
|
|
||||||
dc.SetRGB(1, 1, 1)
|
|
||||||
|
|
||||||
dc.DrawString("github.com/tardisx/discord-auto-upload", 5.0, float64(bounds.Max.Y)-5.0)
|
|
||||||
|
|
||||||
b := bytes.Buffer{}
|
|
||||||
dc.EncodePNG(&b)
|
|
||||||
return &b, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func sleepForRetries(retry int) {
|
func sleepForRetries(retry int) {
|
||||||
if retry == 0 {
|
if retry == 0 {
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -2,15 +2,13 @@ package upload
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"image"
|
i "image"
|
||||||
"image/color"
|
"image/color"
|
||||||
"image/png"
|
"image/png"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
|
||||||
// "github.com/tardisx/discord-auto-upload/config"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// https://www.thegreatcodeadventure.com/mocking-http-requests-in-golang/
|
// https://www.thegreatcodeadventure.com/mocking-http-requests-in-golang/
|
||||||
@@ -38,52 +36,50 @@ func DoTooBigUpload(req *http.Request) (*http.Response, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSuccessfulUpload(t *testing.T) {
|
// func TestSuccessfulUpload(t *testing.T) {
|
||||||
// create temporary file, processUpload requires that it exists, even though
|
// // create temporary file, processUpload requires that it exists, even though
|
||||||
// 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/", Image: &image.Store{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 {
|
||||||
t.Errorf("error occured: %s", err)
|
// t.Errorf("error occured: %s", err)
|
||||||
}
|
// }
|
||||||
if u.Width != 640 || u.Height != 640 {
|
|
||||||
t.Error("dimensions wrong")
|
|
||||||
}
|
|
||||||
if u.Url != "https://cdn.discordapp.com/attachments/849615269706203171/851092588332449812/dau480457962.png" {
|
|
||||||
t.Error("URL wrong")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTooBigUpload(t *testing.T) {
|
// if u.Url != "https://cdn.discordapp.com/attachments/849615269706203171/851092588332449812/dau480457962.png" {
|
||||||
// create temporary file, processUpload requires that it exists, even though
|
// t.Error("URL wrong")
|
||||||
// we will not really be uploading it here
|
// }
|
||||||
f, _ := os.CreateTemp("", "dautest-upload-*")
|
// }
|
||||||
defer os.Remove(f.Name())
|
|
||||||
u := Upload{webhookURL: "https://127.0.0.1/", OriginalFilename: f.Name()}
|
// func TestTooBigUpload(t *testing.T) {
|
||||||
u.Client = &MockClient{DoFunc: DoTooBigUpload}
|
// // create temporary file, processUpload requires that it exists, even though
|
||||||
err := u.processUpload()
|
// // we will not really be uploading it here
|
||||||
if err == nil {
|
// f, _ := os.CreateTemp("", "dautest-upload-*")
|
||||||
t.Error("error did not occur?")
|
// defer os.Remove(f.Name())
|
||||||
} else if err.Error() != "received 413 - file too large" {
|
// u := Upload{webhookURL: "https://127.0.0.1/", Image: &image.Store{OriginalFilename: f.Name()}}
|
||||||
t.Errorf("wrong error occurred: %s", err.Error())
|
// u.Client = &MockClient{DoFunc: DoTooBigUpload}
|
||||||
}
|
// err := u.processUpload()
|
||||||
if u.State != StateFailed {
|
// if err == nil {
|
||||||
t.Error("upload should have been marked failed")
|
// t.Error("error did not occur?")
|
||||||
}
|
// } else if err.Error() != "received 413 - file too large" {
|
||||||
}
|
// t.Errorf("wrong error occurred: %s", err.Error())
|
||||||
|
// }
|
||||||
|
// if u.State != StateFailed {
|
||||||
|
// t.Error("upload should have been marked failed")
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
func tempImageGt8Mb() {
|
func tempImageGt8Mb() {
|
||||||
// about 12Mb
|
// about 12Mb
|
||||||
width := 2000
|
width := 2000
|
||||||
height := 2000
|
height := 2000
|
||||||
|
|
||||||
upLeft := image.Point{0, 0}
|
upLeft := i.Point{0, 0}
|
||||||
lowRight := image.Point{width, height}
|
lowRight := i.Point{width, height}
|
||||||
|
|
||||||
img := image.NewRGBA(image.Rectangle{upLeft, lowRight})
|
img := i.NewRGBA(i.Rectangle{upLeft, lowRight})
|
||||||
|
|
||||||
// Colors are defined by Red, Green, Blue, Alpha uint8 values.
|
// Colors are defined by Red, Green, Blue, Alpha uint8 values.
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
"golang.org/x/mod/semver"
|
"golang.org/x/mod/semver"
|
||||||
)
|
)
|
||||||
|
|
||||||
const CurrentVersion string = "v0.12.3"
|
const CurrentVersion string = "v0.13.0-alpha.2"
|
||||||
|
|
||||||
type GithubRelease struct {
|
type GithubRelease struct {
|
||||||
HTMLURL string `json:"html_url"`
|
HTMLURL string `json:"html_url"`
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ import (
|
|||||||
|
|
||||||
func TestVersioningUpdate(t *testing.T) {
|
func TestVersioningUpdate(t *testing.T) {
|
||||||
// pretend there is a new version
|
// pretend there is a new version
|
||||||
LatestVersion = "v0.13.0"
|
LatestVersion = "v0.13.9"
|
||||||
if !UpdateAvailable() {
|
if !UpdateAvailable() {
|
||||||
t.Error("should be a version newer than " + CurrentVersion)
|
t.Error("should be a version newer than " + CurrentVersion)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVersioningNoUpdate(t *testing.T) {
|
func TestVersioningNoUpdate(t *testing.T) {
|
||||||
// pretend there is a new version
|
// pretend there is not a new version
|
||||||
LatestVersion = "v0.12.1"
|
LatestVersion = "v0.12.1"
|
||||||
if UpdateAvailable() {
|
if UpdateAvailable() {
|
||||||
t.Error("should NOT be a version newer than " + CurrentVersion)
|
t.Error("should NOT be a version newer than " + CurrentVersion)
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
{
|
|
||||||
"FixedFileInfo": {
|
|
||||||
"FileVersion": {
|
|
||||||
"Major": 0,
|
|
||||||
"Minor": 0,
|
|
||||||
"Patch": 0,
|
|
||||||
"Build": 0
|
|
||||||
},
|
|
||||||
"ProductVersion": {
|
|
||||||
"Major": 0,
|
|
||||||
"Minor": 0,
|
|
||||||
"Patch": 0,
|
|
||||||
"Build": 0
|
|
||||||
},
|
|
||||||
"FileFlagsMask": "3f",
|
|
||||||
"FileFlags ": "00",
|
|
||||||
"FileOS": "040004",
|
|
||||||
"FileType": "01",
|
|
||||||
"FileSubType": "00"
|
|
||||||
},
|
|
||||||
"StringFileInfo": {
|
|
||||||
"Comments": "",
|
|
||||||
"CompanyName": "tardisx@github",
|
|
||||||
"FileDescription": "https://github.com/tardisx/discord-auto-upload",
|
|
||||||
"FileVersion": "",
|
|
||||||
"InternalName": "",
|
|
||||||
"LegalCopyright": "https://github.com/tardisx/discord-auto-upload/blob/master/LICENSE",
|
|
||||||
"LegalTrademarks": "",
|
|
||||||
"OriginalFilename": "",
|
|
||||||
"PrivateBuild": "",
|
|
||||||
"ProductName": "discord-auto-upload",
|
|
||||||
"ProductVersion": "v0.0.0",
|
|
||||||
"SpecialBuild": ""
|
|
||||||
},
|
|
||||||
"VarFileInfo": {
|
|
||||||
"Translation": {
|
|
||||||
"LangID": "0409",
|
|
||||||
"CharsetID": "04B0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"IconPath": "dau.ico",
|
|
||||||
"ManifestPath": ""
|
|
||||||
}
|
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>The Watch Interval is how often new files will be discovered by your
|
<p>The Watch Interval is how often new files will be discovered by your
|
||||||
watchers (watchers are configured below).</p>
|
watchers in seconds (watchers are configured below).</p>
|
||||||
|
|
||||||
<div class="form-row align-items-center">
|
<div class="form-row align-items-center">
|
||||||
<div class="col-sm-6 my-1">
|
<div class="col-sm-6 my-1">
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>filename</th>
|
<th>filename</th>
|
||||||
<th>actions</th>
|
<th>state</th>
|
||||||
<th> </th>
|
<th> </th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@@ -47,9 +47,11 @@
|
|||||||
<template x-for="ul in uploads">
|
<template x-for="ul in uploads">
|
||||||
<tr>
|
<tr>
|
||||||
<td x-text="ul.original_file"></td>
|
<td x-text="ul.original_file"></td>
|
||||||
<td>
|
<td>
|
||||||
<button @click="start_upload(ul.id)" type="button" class="btn btn-primary">upload</button>
|
<span x-text="ul.state"></span>
|
||||||
</td>
|
<div x-if="ul.state_reason">(<span x-text="ul.state_reason"></span>)</div>
|
||||||
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<img :src="'/rest/image/'+ul.id+'/thumb'">
|
<img :src="'/rest/image/'+ul.id+'/thumb'">
|
||||||
</td>
|
</td>
|
||||||
@@ -74,7 +76,10 @@
|
|||||||
<template x-for="ul in finished">
|
<template x-for="ul in finished">
|
||||||
<tr>
|
<tr>
|
||||||
<td x-text="ul.original_file"></td>
|
<td x-text="ul.original_file"></td>
|
||||||
<td x-text="ul.state"></td>
|
<td>
|
||||||
|
<span x-text="ul.state"></span>
|
||||||
|
<div x-if="ul.state_reason">(<span x-text="ul.state_reason"></span>)</div>
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<img :src="'/rest/image/'+ul.id+'/thumb'">
|
<img :src="'/rest/image/'+ul.id+'/thumb'">
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import (
|
|||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/tardisx/discord-auto-upload/config"
|
"github.com/tardisx/discord-auto-upload/config"
|
||||||
"github.com/tardisx/discord-auto-upload/imageprocess"
|
"github.com/tardisx/discord-auto-upload/image"
|
||||||
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"
|
||||||
"github.com/tardisx/discord-auto-upload/version"
|
"github.com/tardisx/discord-auto-upload/version"
|
||||||
@@ -178,7 +178,6 @@ func (ws *WebService) getUploads(w http.ResponseWriter, r *http.Request) {
|
|||||||
func (ws *WebService) imageThumb(w http.ResponseWriter, r *http.Request) {
|
func (ws *WebService) imageThumb(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "image/png")
|
w.Header().Set("Content-Type", "image/png")
|
||||||
processor := imageprocess.Processor{}
|
|
||||||
|
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
id, err := strconv.ParseInt(vars["id"], 10, 32)
|
id, err := strconv.ParseInt(vars["id"], 10, 32)
|
||||||
@@ -192,7 +191,7 @@ func (ws *WebService) imageThumb(w http.ResponseWriter, r *http.Request) {
|
|||||||
returnJSONError(w, "bad id")
|
returnJSONError(w, "bad id")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = processor.ThumbPNG(ul, "orig", w)
|
err = ul.Image.ThumbPNG(image.ThumbTypeOriginal, w)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnJSONError(w, "could not create thumb")
|
returnJSONError(w, "could not create thumb")
|
||||||
return
|
return
|
||||||
@@ -202,7 +201,6 @@ func (ws *WebService) imageThumb(w http.ResponseWriter, r *http.Request) {
|
|||||||
func (ws *WebService) imageMarkedupThumb(w http.ResponseWriter, r *http.Request) {
|
func (ws *WebService) imageMarkedupThumb(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "image/png")
|
w.Header().Set("Content-Type", "image/png")
|
||||||
processor := imageprocess.Processor{}
|
|
||||||
|
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
id, err := strconv.ParseInt(vars["id"], 10, 32)
|
id, err := strconv.ParseInt(vars["id"], 10, 32)
|
||||||
@@ -216,7 +214,7 @@ func (ws *WebService) imageMarkedupThumb(w http.ResponseWriter, r *http.Request)
|
|||||||
returnJSONError(w, "bad id")
|
returnJSONError(w, "bad id")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = processor.ThumbPNG(ul, "markedup", w)
|
err = ul.Image.ThumbPNG(image.ThumbTypeMarkedUp, w)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnJSONError(w, "could not create thumb")
|
returnJSONError(w, "could not create thumb")
|
||||||
return
|
return
|
||||||
@@ -238,7 +236,7 @@ func (ws *WebService) image(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
img, err := os.Open(ul.OriginalFilename)
|
img, err := os.Open(ul.Image.OriginalFilename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnJSONError(w, "could not open image file")
|
returnJSONError(w, "could not open image file")
|
||||||
return
|
return
|
||||||
@@ -276,7 +274,7 @@ func (ws *WebService) modifyUpload(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
} else if change == "skip" {
|
} else if change == "skip" {
|
||||||
anUpload.State = upload.StateSkipped
|
anUpload.State = upload.StateSkipped
|
||||||
anUpload.RemoveMarkupTempFile()
|
anUpload.Image.Cleanup()
|
||||||
res := StartUploadResponse{Success: true, Message: "upload skipped"}
|
res := StartUploadResponse{Success: true, Message: "upload skipped"}
|
||||||
resString, _ := json.Marshal(res)
|
resString, _ := json.Marshal(res)
|
||||||
w.Write(resString)
|
w.Write(resString)
|
||||||
@@ -298,7 +296,7 @@ func (ws *WebService) modifyUpload(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// write to a temporary file
|
// write to a temporary file
|
||||||
tempfile, err := ioutil.TempFile("", "dau_markup")
|
tempfile, err := ioutil.TempFile("", "dau_markup-*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -311,7 +309,7 @@ func (ws *WebService) modifyUpload(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tempfile.Close()
|
tempfile.Close()
|
||||||
anUpload.MarkedUpFilename = tempfile.Name()
|
anUpload.Image.ModifiedFilename = tempfile.Name()
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
returnJSONError(w, "bad change type")
|
returnJSONError(w, "bad change type")
|
||||||
|
|||||||
Reference in New Issue
Block a user