aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/uploud/main.go218
-rw-r--r--flake.nix3
-rw-r--r--go.mod16
-rw-r--r--go.sum22
4 files changed, 254 insertions, 5 deletions
diff --git a/cmd/uploud/main.go b/cmd/uploud/main.go
new file mode 100644
index 0000000..f33208c
--- /dev/null
+++ b/cmd/uploud/main.go
@@ -0,0 +1,218 @@
+// Command uploud is an automated Backblaze B2 uploader for my infra.
+package main
+
+import (
+ "flag"
+ "image"
+ "image/jpeg"
+ "image/png"
+ "log"
+ "os"
+ "path/filepath"
+ "runtime"
+
+ "github.com/Kagami/go-avif"
+ "github.com/aws/aws-sdk-go/aws"
+ "github.com/aws/aws-sdk-go/aws/credentials"
+ "github.com/aws/aws-sdk-go/aws/session"
+ "github.com/aws/aws-sdk-go/service/s3"
+ "github.com/chai2010/webp"
+ "github.com/disintegration/imaging"
+)
+
+var (
+ b2Bucket = flag.String("b2-bucket", "christine-static", "Backblaze B2 bucket to dump things to")
+
+ avifQuality = flag.Int("avif-quality", 48, "AVIF quality (higher is worse quality)")
+ avifEncoderSpeed = flag.Int("avif-encoder-speed", 0, "AVIF encoder speed (higher is faster)")
+
+ jpegQuality = flag.Int("jpeg-quality", 85, "JPEG quality (lower means lower file size)")
+
+ webpQuality = flag.Int("webp-quality", 75, "WEBP quality (higher is worse quality)")
+)
+
+func doAVIF(src image.Image, dstPath string) error {
+ dst, err := os.Create(dstPath)
+ if err != nil {
+ log.Fatalf("Can't create destination file: %v", err)
+ }
+ defer dst.Close()
+
+ err = avif.Encode(dst, src, &avif.Options{
+ Threads: runtime.GOMAXPROCS(0),
+ Speed: *avifEncoderSpeed,
+ Quality: *avifQuality,
+ })
+ if err != nil {
+ return err
+ }
+
+ log.Printf("Encoded AVIF at %s", dstPath)
+
+ return nil
+}
+
+func doWEBP(src image.Image, dstPath string) error {
+ fout, err := os.Create(dstPath)
+ if err != nil {
+ return err
+ }
+ defer fout.Close()
+
+ err = webp.Encode(fout, src, &webp.Options{Quality: float32(*webpQuality)})
+ if err != nil {
+ return err
+ }
+
+ log.Printf("Encoded WEBP at %s", dstPath)
+
+ return nil
+}
+
+func fileNameWithoutExt(fileName string) string {
+ return filepath.Base(fileName[:len(fileName)-len(filepath.Ext(fileName))])
+}
+
+func doJPEG(src image.Image, dstPath string) error {
+ fout, err := os.Create(dstPath)
+ if err != nil {
+ return err
+ }
+ defer fout.Close()
+
+ if err := jpeg.Encode(fout, src, &jpeg.Options{Quality: *jpegQuality}); err != nil {
+ return err
+ }
+
+ log.Printf("Encoded JPEG at %s", dstPath)
+
+ return nil
+}
+
+func resizeSmol(src image.Image, dstPath string) error {
+ fout, err := os.Create(dstPath)
+ if err != nil {
+ return err
+ }
+ defer fout.Close()
+
+ dstImg := imaging.Resize(src, 800, 0, imaging.Lanczos)
+
+ enc := png.Encoder{
+ CompressionLevel: png.BestCompression,
+ }
+
+ if err := enc.Encode(fout, dstImg); err != nil {
+ return err
+ }
+
+ log.Printf("Encoded smol PNG at %s", dstPath)
+
+ return nil
+}
+
+func processImage(fname, tempDir string) error {
+ fnameBase := fileNameWithoutExt(fname)
+ fin, err := os.Open(fname)
+ if err != nil {
+ return err
+ }
+
+ src, _, err := image.Decode(fin)
+ if err != nil {
+ return err
+ }
+
+ if err := doAVIF(src, filepath.Join(tempDir, fnameBase+".avif")); err != nil {
+ log.Fatal(err)
+ return err
+ }
+
+ if err := doWEBP(src, filepath.Join(tempDir, fnameBase+".webp")); err != nil {
+ return err
+ }
+
+ if err := doJPEG(src, filepath.Join(tempDir, fnameBase+".jpg")); err != nil {
+ return err
+ }
+
+ if err := resizeSmol(src, filepath.Join(tempDir, fnameBase+"-smol.png")); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func main() {
+ flag.Parse()
+
+ if flag.NArg() != 2 {
+ log.Fatalf("usage: %s <filename/folder> <b2 path>", os.Args[0])
+ }
+
+ td, err := os.MkdirTemp("", "uploud")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer os.RemoveAll(td)
+
+ st, err := os.Stat(flag.Arg(0))
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if st.IsDir() {
+ files, err := os.ReadDir(flag.Arg(0))
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ for _, finfo := range files {
+ if err := processImage(filepath.Join(flag.Arg(0), finfo.Name()), td); err != nil {
+ log.Fatal(err)
+ }
+ }
+ } else {
+ if err := processImage(flag.Arg(0), td); err != nil {
+ log.Fatal(err)
+ }
+ }
+
+ files, err := os.ReadDir(td)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ s3c := mkS3Client()
+
+ for _, finfo := range files {
+ log.Printf("uploading %s", finfo.Name())
+ fin, err := os.Open(filepath.Join(td, finfo.Name()))
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer fin.Close()
+
+ _, err = s3c.PutObject(&s3.PutObjectInput{
+ Body: fin,
+ Bucket: b2Bucket,
+ Key: aws.String(flag.Arg(1) + "/" + finfo.Name()),
+ })
+ if err != nil {
+ log.Fatal(err)
+ }
+ }
+}
+
+func mkS3Client() *s3.S3 {
+ s3Config := &aws.Config{
+ Credentials: credentials.NewStaticCredentials(os.Getenv("B2_KEY_ID"), os.Getenv("B2_APPLICATION_KEY"), ""),
+ Endpoint: aws.String("https://s3.us-west-001.backblazeb2.com"),
+ Region: aws.String("us-west-001"),
+ S3ForcePathStyle: aws.Bool(true),
+ }
+ newSession := session.New(s3Config)
+
+ s3Client := s3.New(newSession)
+ return s3Client
+}
diff --git a/flake.nix b/flake.nix
index 0253abc..2535fd6 100644
--- a/flake.nix
+++ b/flake.nix
@@ -176,6 +176,9 @@
go-tools
gomod2nix.packages.${system}.default
python
+
+ pkg-config
+ libaom
];
};
});
diff --git a/go.mod b/go.mod
index 7d22e5e..f6fb52f 100644
--- a/go.mod
+++ b/go.mod
@@ -2,10 +2,12 @@ module within.website/x
require (
cirello.io/goherokuname v0.0.0-20190914093443-b436bae8c2c5
+ github.com/Kagami/go-avif v0.1.0
github.com/McKael/madon/v2 v2.0.0-20180929094633-c679abc985d6
github.com/Yawning/bulb v0.0.0-20170405033506-85d80d893c3d
github.com/birkelund/boltdbcache v1.0.0
github.com/bwmarrin/discordgo v0.25.0
+ github.com/chai2010/webp v1.1.1
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd
github.com/dgryski/go-failure v0.0.0-20151001134759-4963dbd58fd0
github.com/disintegration/imaging v1.6.1
@@ -29,6 +31,7 @@ require (
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2
github.com/pkg/errors v0.9.1
github.com/posener/complete v1.2.3
+ github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a
github.com/streamrail/concurrent-map v0.0.0-20160823150647-8bf1e9bacbf6
github.com/sycamoreone/orc v0.0.0-20150204213357-1627eaec2699
github.com/tmc/scp v0.0.0-20170824174625-f7b48647feef
@@ -41,6 +44,7 @@ require (
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4
golang.org/x/net v0.0.0-20220607020251-c690dde0001d
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5
+ gopkg.in/kothar/go-backblaze.v0 v0.0.0-20210124194846-35409b867216
gopkg.in/tucnak/telebot.v2 v2.0.0-20190415090633-8c1c512262f2
tailscale.com v1.30.0
tulpa.dev/cadey/jvozba v0.0.0-20200326200349-f0ebe310be06
@@ -54,7 +58,8 @@ require (
github.com/aclements/go-moremath v0.0.0-20190506201756-286cc0be6f75 // indirect
github.com/akutz/memconn v0.1.0 // indirect
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 // indirect
- github.com/aws/aws-sdk-go-v2 v1.11.2 // indirect
+ github.com/aws/aws-sdk-go v1.44.93 // indirect
+ github.com/aws/aws-sdk-go-v2 v1.16.14 // indirect
github.com/aws/aws-sdk-go-v2/config v1.11.0 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.6.4 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.8.2 // indirect
@@ -65,7 +70,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/ssm v1.17.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.6.2 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.11.1 // indirect
- github.com/aws/smithy-go v1.9.0 // indirect
+ github.com/aws/smithy-go v1.13.2 // indirect
github.com/coreos/go-iptables v0.6.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-onlinestats v0.0.0-20170612111826-1c7d19468768 // indirect
@@ -78,15 +83,18 @@ require (
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/godbus/dbus/v5 v5.0.6 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
+ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/google/go-cmp v0.5.8 // indirect
github.com/google/go-querystring v1.0.0 // indirect
+ github.com/google/readahead v0.0.0-20161222183148-eaceba169032 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 // indirect
+ github.com/ifo/b2 v0.0.0-20160508130746-6ff097c9b020 // indirect
github.com/insomniacslk/dhcp v0.0.0-20211209223715-7d93572ebe8e // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/josharian/native v1.0.0 // indirect
@@ -105,9 +113,9 @@ require (
github.com/mitchellh/go-ps v1.0.0 // indirect
github.com/mndrix/ps v0.0.0-20170330174427-18e65badd6ab // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
+ github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/rogpeppe/go-internal v1.8.1-0.20211023094830-115ce09fd6b4 // indirect
- github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a // indirect
github.com/sendgrid/rest v2.4.1+incompatible // indirect
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
github.com/tailscale/certstore v0.1.1-0.20220316223106-78d6e1c49d8d // indirect
@@ -128,7 +136,7 @@ require (
go4.org/mem v0.0.0-20210711025021-927187094b94 // indirect
go4.org/netipx v0.0.0-20220725152314-7e7bdc8411bf // indirect
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
- golang.org/x/image v0.0.0-20190802002840-cff245a6509b // indirect
+ golang.org/x/image v0.0.0-20211028202545-6944b10bf410 // indirect
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
diff --git a/go.sum b/go.sum
index 92cf4c9..9a6e577 100644
--- a/go.sum
+++ b/go.sum
@@ -39,6 +39,8 @@ filippo.io/mkcert v1.4.3 h1:axpnmtrZMM8u5Hf4N3UXxboGemMOV+Tn+e+pkHM6E3o=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
+github.com/Kagami/go-avif v0.1.0 h1:8GHAGLxCdFfhpd4Zg8j1EqO7rtcQNenxIDerC/uu68w=
+github.com/Kagami/go-avif v0.1.0/go.mod h1:OPmPqzNdQq3+sXm0HqaUJQ9W/4k+Elbc3RSfJUemDKA=
github.com/McKael/madon/v2 v2.0.0-20180929094633-c679abc985d6 h1:9cJcTOeILzInNo+DCYmXKME1QfAP07FYdo3M9/9jyc4=
github.com/McKael/madon/v2 v2.0.0-20180929094633-c679abc985d6/go.mod h1:mvlJhxZCchfiasx3XvN3hBu5RekGwTDm09dKlSM/dQQ=
github.com/Yawning/bulb v0.0.0-20170405033506-85d80d893c3d h1:ASfbc4vPGK69qbMO5qqRtGxfPvUmfbaK1ryEBv9WnQQ=
@@ -49,8 +51,12 @@ github.com/akutz/memconn v0.1.0 h1:NawI0TORU4hcOMsMr11g7vwlCdkYeLKXBcxWu2W/P8A=
github.com/akutz/memconn v0.1.0/go.mod h1:Jo8rI7m0NieZyLI5e2CDlRdRqRRB4S7Xp77ukDjH+Fw=
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA=
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
+github.com/aws/aws-sdk-go v1.44.93 h1:hAgd9fuaptBatSft27/5eBMdcA8+cIMqo96/tZ6rKl8=
+github.com/aws/aws-sdk-go v1.44.93/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/aws/aws-sdk-go-v2 v1.11.2 h1:SDiCYqxdIYi6HgQfAWRhgdZrdnOuGyLDJVRSWLeHWvs=
github.com/aws/aws-sdk-go-v2 v1.11.2/go.mod h1:SQfA+m2ltnu1cA0soUkj4dRSsmITiVQUJvBIZjzfPyQ=
+github.com/aws/aws-sdk-go-v2 v1.16.14 h1:db6GvO4Z2UqHt5gvT0lr6J5x5P+oQ7bdRzczVaRekMU=
+github.com/aws/aws-sdk-go-v2 v1.16.14/go.mod h1:s/G+UV29dECbF5rf+RNj1xhlmvoNurGSr+McVSRj59w=
github.com/aws/aws-sdk-go-v2/config v1.11.0 h1:Czlld5zBB61A3/aoegA9/buZulwL9mHHfizh/Oq+Kqs=
github.com/aws/aws-sdk-go-v2/config v1.11.0/go.mod h1:VrQDJGFBM5yZe+IOeenNZ/DWoErdny+k2MHEIpwDsEY=
github.com/aws/aws-sdk-go-v2/credentials v1.6.4 h1:2hvbUoHufns0lDIsaK8FVCMukT1WngtZPavN+W2FkSw=
@@ -73,11 +79,15 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.11.1 h1:QKR7wy5e650q70PFKMfGF9sTo0rZ
github.com/aws/aws-sdk-go-v2/service/sts v1.11.1/go.mod h1:UV2N5HaPfdbDpkgkz4sRzWCvQswZjdO1FfqCWl0t7RA=
github.com/aws/smithy-go v1.9.0 h1:c7FUdEqrQA1/UVKKCNDFQPNKGp4FQg3YW4Ck5SLTG58=
github.com/aws/smithy-go v1.9.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
+github.com/aws/smithy-go v1.13.2 h1:TBLKyeJfXTrTXRHmsv4qWt9IQGYyWThLYaJWSahTOGE=
+github.com/aws/smithy-go v1.13.2/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
github.com/birkelund/boltdbcache v1.0.0 h1:9DlhGw3Gp0DenvEQ7qNVYvz0b4Oi/zAJin+cR0ubpOA=
github.com/birkelund/boltdbcache v1.0.0/go.mod h1:WgJWF40tV+4K0Q7MxAPbWEIkgs4AVUB7EyKVds0EgfQ=
github.com/bwmarrin/discordgo v0.25.0 h1:NXhdfHRNxtwso6FPdzW2i3uBvvU7UIQTghmV2T4nqAs=
github.com/bwmarrin/discordgo v0.25.0/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/chai2010/webp v1.1.1 h1:jTRmEccAJ4MGrhFOrPMpNGIJ/eybIgwKpcACsrTEapk=
+github.com/chai2010/webp v1.1.1/go.mod h1:0XVwvZWdjjdxpUEIf7b9g9VkHFnInUSYujwqTLEuldU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
@@ -154,6 +164,7 @@ github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
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/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -215,6 +226,8 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/readahead v0.0.0-20161222183148-eaceba169032 h1:6Be3nkuJFyRfCgr6qTIzmRp8y9QwDIbqy/nYr9WDPos=
+github.com/google/readahead v0.0.0-20161222183148-eaceba169032/go.mod h1:qYysrqQXuV4tzsizt4oOQ6mrBZQ0xnQXP3ylXX8Jk5Y=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
@@ -242,6 +255,8 @@ github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Go
github.com/hullerob/go.farbfeld v0.0.0-20181222022525-3661193c725f h1:1LkiAnH6RhOEbQAcfcEcixM5IsegqFi6IH0Nz0ZGqYs=
github.com/hullerob/go.farbfeld v0.0.0-20181222022525-3661193c725f/go.mod h1:mQEoc766DxPTAwQ54neWTK/lFqIeSO7OU6bqZsceglw=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/ifo/b2 v0.0.0-20160508130746-6ff097c9b020 h1:vml5bOFtNbP56E/7wCHz87KYM7dznun2aO75NPg7VLo=
+github.com/ifo/b2 v0.0.0-20160508130746-6ff097c9b020/go.mod h1:/jHADo7KHjcki7Vm6gWP+PxWOjps0g7mxUtvl+qaZ20=
github.com/insomniacslk/dhcp v0.0.0-20211209223715-7d93572ebe8e h1:IQpunlq7T+NiJJMO7ODYV2YWBiv/KnObR3gofX0mWOo=
github.com/insomniacslk/dhcp v0.0.0-20211209223715-7d93572ebe8e/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E=
github.com/jaytaylor/html2text v0.0.0-20190408195923-01ec452cbe43 h1:jTkyeF7NZ5oIr0ESmcrpiDgAfoidCBF4F5kJhjtaRwE=
@@ -350,6 +365,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
+github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 h1:xoIK0ctDddBMnc74udxJYBqlo9Ylnsp1waqjLsnef20=
+github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
@@ -464,8 +481,9 @@ golang.org/x/exp/errors v0.0.0-20190510132918-efd6b22b2522/go.mod h1:YgqsNsAu4fT
golang.org/x/exp/typeparams v0.0.0-20220328175248-053ad81199eb h1:fP6C8Xutcp5AlakmT/SkQot0pMicROAsEX7OfNPuG10=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
-golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ=
+golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -756,6 +774,8 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/kothar/go-backblaze.v0 v0.0.0-20210124194846-35409b867216 h1:2TSTkQ8PMvGOD5eeqqRVv6Z9+BYI+bowK97RCr3W+9M=
+gopkg.in/kothar/go-backblaze.v0 v0.0.0-20210124194846-35409b867216/go.mod h1:zJ2QpyDCYo1KvLXlmdnFlQAyF/Qfth0fB8239Qg7BIE=
gopkg.in/tucnak/telebot.v2 v2.0.0-20190415090633-8c1c512262f2 h1:wGFU+pn16CuaCt4lc9gkdF1R/y4M8CRi4g6yj7pxpBE=
gopkg.in/tucnak/telebot.v2 v2.0.0-20190415090633-8c1c512262f2/go.mod h1:+//wyPtHTeW2kfyEBwB05Hqnxev7AGrsLIyylSH++KU=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=