repos / pico

pico services - prose.sh, pastes.sh, imgs.sh, feeds.sh, pgs.sh
git clone https://github.com/picosh/pico.git

commit
e1aaa8f
parent
d09a5d8
author
Antonio Mika
date
2022-09-01 01:18:36 +0000 UTC
Add the ability to download images and fix sftp uploads
7 files changed,  +114, -20
M go.mod
M go.sum
M filehandlers/imgs/handler.go
+69, -2
 1@@ -7,6 +7,7 @@ import (
 2 	"net/http"
 3 	"os"
 4 	"path"
 5+	"strings"
 6 	"time"
 7 
 8 	"git.sr.ht/~erock/pico/db"
 9@@ -64,11 +65,77 @@ func (h *UploadImgHandler) removePost(data *PostMetaData) error {
10 }
11 
12 func (h *UploadImgHandler) Read(s ssh.Session, filename string) (os.FileInfo, io.ReaderAt, error) {
13-	return nil, nil, nil
14+	cleanFilename := strings.ReplaceAll(filename, "/", "")
15+
16+	if cleanFilename == "" || cleanFilename == "." {
17+		return nil, nil, os.ErrNotExist
18+	}
19+
20+	post, err := h.DBPool.FindPostWithFilename(cleanFilename, h.User.ID, h.Cfg.Space)
21+	if err != nil {
22+		return nil, nil, err
23+	}
24+
25+	fileInfo := &utils.VirtualFile{
26+		FName:    post.Filename,
27+		FIsDir:   false,
28+		FSize:    int64(post.FileSize),
29+		FModTime: *post.UpdatedAt,
30+	}
31+
32+	bucket, err := h.Storage.GetBucket(h.User.ID)
33+	if err != nil {
34+		return nil, nil, err
35+	}
36+
37+	contents, err := h.Storage.GetFile(bucket, post.Filename)
38+	if err != nil {
39+		return nil, nil, err
40+	}
41+
42+	return fileInfo, contents, nil
43 }
44 
45 func (h *UploadImgHandler) List(s ssh.Session, filename string) ([]os.FileInfo, error) {
46-	return nil, nil
47+	var fileList []os.FileInfo
48+	cleanFilename := strings.ReplaceAll(filename, "/", "")
49+
50+	var err error
51+	var post *db.Post
52+	var posts []*db.Post
53+
54+	if cleanFilename == "" || cleanFilename == "." {
55+		name := cleanFilename
56+		if name == "" {
57+			name = "/"
58+		}
59+
60+		fileList = append(fileList, &utils.VirtualFile{
61+			FName:  name,
62+			FIsDir: true,
63+		})
64+
65+		posts, err = h.DBPool.FindAllPostsForUser(h.User.ID, h.Cfg.Space)
66+	} else {
67+		post, err = h.DBPool.FindPostWithFilename(cleanFilename, h.User.ID, h.Cfg.Space)
68+
69+		posts = append(posts, post)
70+	}
71+
72+	if err != nil {
73+		return nil, err
74+	}
75+
76+	for _, post := range posts {
77+		fileList = append(fileList, &utils.VirtualFile{
78+			FName:    post.Filename,
79+			FIsDir:   false,
80+			FSize:    int64(post.FileSize),
81+			FModTime: *post.UpdatedAt,
82+		})
83+	}
84+
85+	return fileList, nil
86 }
87 
88 func (h *UploadImgHandler) Validate(s ssh.Session) error {
M filehandlers/imgs/img.go
+2, -2
 1@@ -3,10 +3,10 @@ package uploadimgs
 2 import (
 3 	"bytes"
 4 	"fmt"
 5-	"io"
 6 	"strings"
 7 
 8 	"git.sr.ht/~erock/pico/db"
 9+	"git.sr.ht/~erock/pico/imgs/storage"
10 	"git.sr.ht/~erock/pico/shared"
11 )
12 
13@@ -42,7 +42,7 @@ func (h *UploadImgHandler) metaImg(data *PostMetaData) error {
14 	if err != nil {
15 		return err
16 	}
17-	fname, err := h.Storage.PutFile(bucket, data.Filename, io.NopCloser(bytes.NewReader([]byte(data.Text))))
18+	fname, err := h.Storage.PutFile(bucket, data.Filename, storage.NopReaderAtCloser(bytes.NewReader([]byte(data.Text))))
19 	if err != nil {
20 		return err
21 	}
M go.mod
+3, -2
 1@@ -7,13 +7,14 @@ go 1.19
 2 
 3 require (
 4 	github.com/alecthomas/chroma v0.10.0
 5-	github.com/antoniomika/go-rsync-receiver v0.0.0-20220825051444-e2df2a87b439
 6+	github.com/antoniomika/go-rsync-receiver v0.0.0-20220901010427-e6494124f0c8
 7 	github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de
 8 	github.com/charmbracelet/bubbles v0.13.0
 9 	github.com/charmbracelet/bubbletea v0.22.1
10 	github.com/charmbracelet/lipgloss v0.5.0
11 	github.com/charmbracelet/promwish v0.2.0
12 	github.com/charmbracelet/wish v0.5.0
13+	github.com/disintegration/imaging v1.6.2
14 	github.com/gliderlabs/ssh v0.3.4
15 	github.com/gorilla/feeds v1.1.1
16 	github.com/kolesa-team/go-webp v1.0.1
17@@ -22,7 +23,6 @@ require (
18 	github.com/microcosm-cc/bluemonday v1.0.19
19 	github.com/minio/minio-go/v7 v7.0.35
20 	github.com/muesli/reflow v0.3.0
21-	github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
22 	github.com/pkg/sftp v1.13.5
23 	github.com/scottleedavis/go-exif-remove v0.0.0-20190908021517-58bdbaac8636
24 	github.com/yuin/goldmark v1.4.13
25@@ -88,6 +88,7 @@ require (
26 	github.com/sirupsen/logrus v1.9.0 // indirect
27 	go.uber.org/atomic v1.10.0 // indirect
28 	go.uber.org/multierr v1.8.0 // indirect
29+	golang.org/x/image v0.0.0-20220722155232-062f8c9fd539 // indirect
30 	golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b // indirect
31 	golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 // indirect
32 	golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 // indirect
M go.sum
+7, -5
 1@@ -44,8 +44,8 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
 2 github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
 3 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
 4 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
 5-github.com/antoniomika/go-rsync-receiver v0.0.0-20220825051444-e2df2a87b439 h1:5AjhKkEyKSn81jZXXSX/Mob3hLNUfP4Dyo49vyITQQI=
 6-github.com/antoniomika/go-rsync-receiver v0.0.0-20220825051444-e2df2a87b439/go.mod h1:zmqePVIo1hp+WEKxERLLGHJBDOr8/z/T4eFqXgWIw1w=
 7+github.com/antoniomika/go-rsync-receiver v0.0.0-20220901010427-e6494124f0c8 h1:gR27C6N8s5b+ciBRymi0zhUx8TylKFO755z6yrBuMiI=
 8+github.com/antoniomika/go-rsync-receiver v0.0.0-20220901010427-e6494124f0c8/go.mod h1:zmqePVIo1hp+WEKxERLLGHJBDOr8/z/T4eFqXgWIw1w=
 9 github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhPwqqXc4/vE0f7GvRjuAsbW+HOIe8KnA=
10 github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw=
11 github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
12@@ -88,6 +88,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
13 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
14 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
15 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
16+github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
17+github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
18 github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
19 github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo=
20 github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
21@@ -302,8 +304,6 @@ github.com/muesli/termenv v0.12.0 h1:KuQRUE3PgxRFWhq4gHvZtPSLCGDqM5q/cYr1pZ39ytc
22 github.com/muesli/termenv v0.12.0/go.mod h1:WCCv32tusQ/EEZ5S8oUIIrC/nIuBcxCVqlN4Xfkv+7A=
23 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
24 github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
25-github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
26-github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
27 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
28 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
29 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
30@@ -409,8 +409,10 @@ golang.org/x/exp v0.0.0-20220827204233-334a2380cb91 h1:tnebWN09GYg9OLPss1KXj8txw
31 golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
32 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
33 golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
34-golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d h1:RNPAfi2nHY7C2srAV8A49jpsYr0ADedCk1wq6fTMTvs=
35+golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
36 golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
37+golang.org/x/image v0.0.0-20220722155232-062f8c9fd539 h1:/eM0PCrQI2xd471rI+snWuu251/+/jpBpZqir2mPdnU=
38+golang.org/x/image v0.0.0-20220722155232-062f8c9fd539/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
39 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
40 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
41 golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
M imgs/api.go
+2, -2
 1@@ -21,10 +21,10 @@ import (
 2 	"git.sr.ht/~erock/pico/db/postgres"
 3 	"git.sr.ht/~erock/pico/imgs/storage"
 4 	"git.sr.ht/~erock/pico/shared"
 5+	"github.com/disintegration/imaging"
 6 	"github.com/gorilla/feeds"
 7 	"github.com/kolesa-team/go-webp/encoder"
 8 	"github.com/kolesa-team/go-webp/webp"
 9-	"github.com/nfnt/resize"
10 	"go.uber.org/zap"
11 	"golang.org/x/exp/slices"
12 )
13@@ -290,7 +290,7 @@ func (h *ImgOptimizer) Process(contents io.Reader, writer io.Writer, mimeType st
14 
15 	nextImg := img
16 	if h.Height > 0 || h.Width > 0 {
17-		nextImg = resize.Resize(h.Width, h.Height, img, resize.Bicubic)
18+		nextImg = imaging.Resize(img, int(h.Width), int(h.Height), imaging.MitchellNetravali)
19 	}
20 
21 	options, err := encoder.NewLossyEncoderOptions(
M imgs/storage/minio.go
+7, -3
 1@@ -4,7 +4,6 @@ import (
 2 	"context"
 3 	"errors"
 4 	"fmt"
 5-	"io"
 6 	"net/url"
 7 
 8 	"github.com/minio/minio-go/v7"
 9@@ -66,16 +65,21 @@ func (s *StorageMinio) UpsertBucket(name string) (Bucket, error) {
10 	return bucket, nil
11 }
12 
13-func (s *StorageMinio) GetFile(bucket Bucket, fname string) (io.ReadCloser, error) {
14+func (s *StorageMinio) GetFile(bucket Bucket, fname string) (ReaderAtCloser, error) {
15 	obj, err := s.Client.GetObject(context.TODO(), bucket.Name, fname, minio.GetObjectOptions{})
16 	if err != nil {
17 		return nil, err
18 	}
19 
20+	_, err = obj.Stat()
21+	if err != nil {
22+		return nil, err
23+	}
24+
25 	return obj, nil
26 }
27 
28-func (s *StorageMinio) PutFile(bucket Bucket, fname string, contents io.ReadCloser) (string, error) {
29+func (s *StorageMinio) PutFile(bucket Bucket, fname string, contents ReaderAtCloser) (string, error) {
30 	info, err := s.Client.PutObject(context.TODO(), bucket.Name, fname, contents, -1, minio.PutObjectOptions{})
31 	if err != nil {
32 		return "", err
M imgs/storage/storage.go
+24, -4
 1@@ -12,12 +12,32 @@ type Bucket struct {
 2 	Path string
 3 }
 4 
 5+type ReadAndReaderAt interface {
 6+	io.ReaderAt
 7+	io.Reader
 8+}
 9+
10+type ReaderAtCloser interface {
11+	io.ReaderAt
12+	io.ReadCloser
13+}
14+
15+func NopReaderAtCloser(r ReadAndReaderAt) ReaderAtCloser {
16+	return nopReaderAtCloser{r}
17+}
18+
19+type nopReaderAtCloser struct {
20+	ReadAndReaderAt
21+}
22+
23+func (nopReaderAtCloser) Close() error { return nil }
24+
25 type ObjectStorage interface {
26 	GetBucket(name string) (Bucket, error)
27 	UpsertBucket(name string) (Bucket, error)
28 
29-	GetFile(bucket Bucket, fname string) (io.ReadCloser, error)
30-	PutFile(bucket Bucket, fname string, contents io.ReadCloser) (string, error)
31+	GetFile(bucket Bucket, fname string) (ReaderAtCloser, error)
32+	PutFile(bucket Bucket, fname string, contents ReaderAtCloser) (string, error)
33 	DeleteFile(bucket Bucket, fname string) error
34 }
35 
36@@ -68,7 +88,7 @@ func (s *StorageFS) UpsertBucket(name string) (Bucket, error) {
37 	return bucket, nil
38 }
39 
40-func (s *StorageFS) GetFile(bucket Bucket, fname string) (io.ReadCloser, error) {
41+func (s *StorageFS) GetFile(bucket Bucket, fname string) (ReaderAtCloser, error) {
42 	dat, err := os.Open(path.Join(bucket.Path, fname))
43 	if err != nil {
44 		return nil, err
45@@ -77,7 +97,7 @@ func (s *StorageFS) GetFile(bucket Bucket, fname string) (io.ReadCloser, error)
46 	return dat, nil
47 }
48 
49-func (s *StorageFS) PutFile(bucket Bucket, fname string, contents io.ReadCloser) (string, error) {
50+func (s *StorageFS) PutFile(bucket Bucket, fname string, contents ReaderAtCloser) (string, error) {
51 	loc := path.Join(bucket.Path, fname)
52 	f, err := os.OpenFile(loc, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
53 	if err != nil {