repos / pico

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

commit
ccc0df5
parent
4294df9
author
Antonio Mika
date
2023-11-11 15:54:13 +0000 UTC
Add feature flag for advanced pastes management
9 files changed,  +90, -16
M .vscode/launch.json
+2, -1
 1@@ -10,7 +10,8 @@
 2             "request": "launch",
 3             "mode": "auto",
 4             "program": "${workspaceFolder}/cmd/${input:service}/${input:type}/main.go",
 5-            "envFile": "${workspaceFolder}/.env"
 6+            "envFile": "${workspaceFolder}/.env",
 7+            "cwd": "${workspaceFolder}"
 8         }
 9     ],
10     "inputs": [
M db/postgres/storage.go
+2, -1
 1@@ -242,7 +242,7 @@ const (
 2 	sqlUpdatePost = `
 3 	UPDATE posts
 4 	SET slug = $1, title = $2, text = $3, description = $4, updated_at = $5, publish_at = $6,
 5-		file_size = $7, shasum = $8, data = $9, hidden = $11
 6+		file_size = $7, shasum = $8, data = $9, hidden = $11, expires_at = $12
 7 	WHERE id = $10`
 8 	sqlUpdateUserName = `UPDATE app_users SET name = $1 WHERE id = $2`
 9 	sqlIncrementViews = `UPDATE posts SET views = views + 1 WHERE id = $1 RETURNING views`
10@@ -753,6 +753,7 @@ func (me *PsqlDB) UpdatePost(post *db.Post) (*db.Post, error) {
11 		post.Data,
12 		post.ID,
13 		post.Hidden,
14+		post.ExpiresAt,
15 	)
16 	if err != nil {
17 		return nil, err
M feeds/scp_hooks.go
+3, -2
 1@@ -7,6 +7,7 @@ import (
 2 
 3 	"slices"
 4 
 5+	"github.com/charmbracelet/ssh"
 6 	"github.com/picosh/pico/db"
 7 	"github.com/picosh/pico/filehandlers"
 8 	"github.com/picosh/pico/imgs"
 9@@ -18,7 +19,7 @@ type FeedHooks struct {
10 	Db  db.DB
11 }
12 
13-func (p *FeedHooks) FileValidate(data *filehandlers.PostMetaData) (bool, error) {
14+func (p *FeedHooks) FileValidate(s ssh.Session, data *filehandlers.PostMetaData) (bool, error) {
15 	if !shared.IsTextFile(string(data.Text)) {
16 		err := fmt.Errorf(
17 			"WARNING: (%s) invalid file must be plain text (utf-8), skipping",
18@@ -40,7 +41,7 @@ func (p *FeedHooks) FileValidate(data *filehandlers.PostMetaData) (bool, error)
19 	return true, nil
20 }
21 
22-func (p *FeedHooks) FileMeta(data *filehandlers.PostMetaData) error {
23+func (p *FeedHooks) FileMeta(s ssh.Session, data *filehandlers.PostMetaData) error {
24 	linkify := imgs.NewImgsLinkify(data.Username)
25 	parsedText := shared.ListParseText(string(data.Text), linkify)
26 
M filehandlers/post_handler.go
+5, -4
 1@@ -40,8 +40,8 @@ type PostMetaData struct {
 2 }
 3 
 4 type ScpFileHooks interface {
 5-	FileValidate(data *PostMetaData) (bool, error)
 6-	FileMeta(data *PostMetaData) error
 7+	FileValidate(s ssh.Session, data *PostMetaData) (bool, error)
 8+	FileMeta(s ssh.Session, data *PostMetaData) error
 9 }
10 
11 type ScpUploadHandler struct {
12@@ -209,7 +209,7 @@ func (h *ScpUploadHandler) Write(s ssh.Session, entry *utils.FileEntry) (string,
13 		FileEntry: entry,
14 	}
15 
16-	valid, err := h.Hooks.FileValidate(&metadata)
17+	valid, err := h.Hooks.FileValidate(s, &metadata)
18 	if !valid {
19 		logger.Error(err)
20 		return "", err
21@@ -226,7 +226,7 @@ func (h *ScpUploadHandler) Write(s ssh.Session, entry *utils.FileEntry) (string,
22 		metadata.Post.PublishAt = post.PublishAt
23 	}
24 
25-	err = h.Hooks.FileMeta(&metadata)
26+	err = h.Hooks.FileMeta(s, &metadata)
27 	if err != nil {
28 		logger.Error(err)
29 		return "", err
30@@ -318,6 +318,7 @@ func (h *ScpUploadHandler) Write(s ssh.Session, entry *utils.FileEntry) (string,
31 			Text:        metadata.Text,
32 			Title:       metadata.Title,
33 			Hidden:      metadata.Hidden,
34+			ExpiresAt:   metadata.ExpiresAt,
35 			UpdatedAt:   &modTime,
36 		}
37 		_, err = h.DBPool.UpdatePost(&updatePost)
M lists/scp_hooks.go
+3, -2
 1@@ -6,6 +6,7 @@ import (
 2 
 3 	"slices"
 4 
 5+	"github.com/charmbracelet/ssh"
 6 	"github.com/picosh/pico/db"
 7 	"github.com/picosh/pico/filehandlers"
 8 	"github.com/picosh/pico/imgs"
 9@@ -17,7 +18,7 @@ type ListHooks struct {
10 	Db  db.DB
11 }
12 
13-func (p *ListHooks) FileValidate(data *filehandlers.PostMetaData) (bool, error) {
14+func (p *ListHooks) FileValidate(s ssh.Session, data *filehandlers.PostMetaData) (bool, error) {
15 	if !shared.IsTextFile(string(data.Text)) {
16 		err := fmt.Errorf(
17 			"WARNING: (%s) invalid file must be plain text (utf-8), skipping",
18@@ -39,7 +40,7 @@ func (p *ListHooks) FileValidate(data *filehandlers.PostMetaData) (bool, error)
19 	return true, nil
20 }
21 
22-func (p *ListHooks) FileMeta(data *filehandlers.PostMetaData) error {
23+func (p *ListHooks) FileMeta(s ssh.Session, data *filehandlers.PostMetaData) error {
24 	linkify := imgs.NewImgsLinkify(data.Username)
25 	parsedText := shared.ListParseText(string(data.Text), linkify)
26 
M pastes/cron.go
+1, -1
1@@ -34,6 +34,6 @@ func CronDeleteExpiredPosts(cfg *shared.ConfigSite, dbpool db.DB) {
2 		if err != nil {
3 			cfg.Logger.Error(err)
4 		}
5-		time.Sleep(1 * time.Hour)
6+		time.Sleep(1 * time.Minute)
7 	}
8 }
M pastes/scp_hooks.go
+61, -2
 1@@ -2,8 +2,12 @@ package pastes
 2 
 3 import (
 4 	"fmt"
 5+	"strconv"
 6+	"strings"
 7 	"time"
 8 
 9+	"github.com/araddon/dateparse"
10+	"github.com/charmbracelet/ssh"
11 	"github.com/picosh/pico/db"
12 	"github.com/picosh/pico/filehandlers"
13 	"github.com/picosh/pico/shared"
14@@ -16,7 +20,7 @@ type FileHooks struct {
15 	Db  db.DB
16 }
17 
18-func (p *FileHooks) FileValidate(data *filehandlers.PostMetaData) (bool, error) {
19+func (p *FileHooks) FileValidate(s ssh.Session, data *filehandlers.PostMetaData) (bool, error) {
20 	if !shared.IsTextFile(string(data.Text)) {
21 		err := fmt.Errorf(
22 			"WARNING: (%s) invalid file must be plain text (utf-8), skipping",
23@@ -28,14 +32,69 @@ func (p *FileHooks) FileValidate(data *filehandlers.PostMetaData) (bool, error)
24 	return true, nil
25 }
26 
27-func (p *FileHooks) FileMeta(data *filehandlers.PostMetaData) error {
28+func (p *FileHooks) FileMeta(s ssh.Session, data *filehandlers.PostMetaData) error {
29 	data.Title = shared.ToUpper(data.Slug)
30 	// we want the slug to be the filename for pastes
31 	data.Slug = data.Filename
32+
33 	if data.Post.ExpiresAt == nil || data.Post.ExpiresAt.IsZero() {
34 		// mark posts for deletion a X days after creation
35 		expiresAt := time.Now().AddDate(0, 0, DEFAULT_EXPIRES_AT)
36 		data.ExpiresAt = &expiresAt
37 	}
38+
39+	if p.Db.HasFeatureForUser(data.User.ID, "pastes-advanced") {
40+		var hidden bool
41+		var expiresFound bool
42+		var expires *time.Time
43+
44+		cmd := s.Command()
45+
46+		for _, arg := range cmd {
47+			if strings.Contains(arg, "=") {
48+				splitArg := strings.Split(arg, "=")
49+				if len(splitArg) != 2 {
50+					continue
51+				}
52+
53+				switch splitArg[0] {
54+				case "hidden":
55+					val, err := strconv.ParseBool(splitArg[1])
56+					if err != nil {
57+						continue
58+					}
59+
60+					hidden = val
61+				case "expires":
62+					val, err := strconv.ParseBool(splitArg[1])
63+					if err == nil {
64+						expiresFound = !val
65+						continue
66+					}
67+
68+					duration, err := time.ParseDuration(splitArg[1])
69+					if err == nil {
70+						expiresFound = true
71+						expireTime := time.Now().Add(duration)
72+						expires = &expireTime
73+						continue
74+					}
75+
76+					expireTime, err := dateparse.ParseStrict(splitArg[1])
77+					if err == nil {
78+						expiresFound = true
79+						expires = &expireTime
80+					}
81+				}
82+			}
83+		}
84+
85+		data.Hidden = hidden
86+
87+		if expiresFound {
88+			data.ExpiresAt = expires
89+		}
90+	}
91+
92 	return nil
93 }
M prose/scp_hooks.go
+3, -2
 1@@ -6,6 +6,7 @@ import (
 2 
 3 	"slices"
 4 
 5+	"github.com/charmbracelet/ssh"
 6 	"github.com/picosh/pico/db"
 7 	"github.com/picosh/pico/filehandlers"
 8 	"github.com/picosh/pico/imgs"
 9@@ -17,7 +18,7 @@ type MarkdownHooks struct {
10 	Db  db.DB
11 }
12 
13-func (p *MarkdownHooks) FileValidate(data *filehandlers.PostMetaData) (bool, error) {
14+func (p *MarkdownHooks) FileValidate(s ssh.Session, data *filehandlers.PostMetaData) (bool, error) {
15 	if !shared.IsTextFile(data.Text) {
16 		err := fmt.Errorf(
17 			"WARNING: (%s) invalid file must be plain text (utf-8), skipping",
18@@ -46,7 +47,7 @@ func (p *MarkdownHooks) FileValidate(data *filehandlers.PostMetaData) (bool, err
19 	return true, nil
20 }
21 
22-func (p *MarkdownHooks) FileMeta(data *filehandlers.PostMetaData) error {
23+func (p *MarkdownHooks) FileMeta(s ssh.Session, data *filehandlers.PostMetaData) error {
24 	linkify := imgs.NewImgsLinkify("")
25 	parsedText, err := shared.ParseText(data.Text, linkify)
26 	// we return nil here because we don't want the file upload to fail
M wish/pipe/pipe.go
+10, -1
 1@@ -22,7 +22,16 @@ func Middleware(writeHandler utils.CopyFromClientHandler, ext string) wish.Middl
 2 				return
 3 			}
 4 
 5-			name := strings.TrimSpace(strings.Join(session.Command(), " "))
 6+			cmd := session.Command()
 7+
 8+			name := ""
 9+			if len(cmd) > 0 {
10+				name = strings.TrimSpace(cmd[0])
11+				if strings.Contains(name, "=") {
12+					name = ""
13+				}
14+			}
15+
16 			postTime := time.Now()
17 
18 			if name == "" {