repos / pico

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

commit
f13ddd4
parent
36b9540
author
Eric Bower
date
2023-11-12 18:33:07 +0000 UTC
feat(pastes): set custom expiration and set paste to unlisted (#52)

5 files changed,  +82, -45
M pastes/api.go
+7, -0
 1@@ -55,6 +55,7 @@ type PostPageData struct {
 2 	Contents     template.HTML
 3 	PublishAtISO string
 4 	PublishAt    string
 5+	ExpiresAt    string
 6 }
 7 
 8 type TransparencyPageData struct {
 9@@ -185,6 +186,10 @@ func postHandler(w http.ResponseWriter, r *http.Request) {
10 		if err != nil {
11 			logger.Error(err)
12 		}
13+		expiresAt := "never"
14+		if post.ExpiresAt != nil {
15+			expiresAt = post.ExpiresAt.Format("02 Jan, 2006")
16+		}
17 
18 		data = PostPageData{
19 			Site:         *cfg.GetSiteData(),
20@@ -199,6 +204,7 @@ func postHandler(w http.ResponseWriter, r *http.Request) {
21 			Username:     username,
22 			BlogName:     blogName,
23 			Contents:     template.HTML(parsedText),
24+			ExpiresAt:    expiresAt,
25 		}
26 	} else {
27 		logger.Infof("post not found %s/%s", username, slug)
28@@ -213,6 +219,7 @@ func postHandler(w http.ResponseWriter, r *http.Request) {
29 			Username:     username,
30 			BlogName:     blogName,
31 			Contents:     "oops!  we can't seem to find this post.",
32+			ExpiresAt:    "",
33 		}
34 	}
35 
M pastes/html/help.page.tmpl
+31, -2
 1@@ -109,8 +109,8 @@ scp ./delete.txt {{.Site.Domain}}:/</pre>
 2 
 3     <section id="pipe">
 4         <h2 class="text-xl">
 5-            <a href="#pipe" rel="nofollow noopener">#</a>
 6-            Can I pipe my paste?
 7+          <a href="#pipe" rel="nofollow noopener">#</a>
 8+          Can I pipe my paste?
 9         </h2>
10         <p>
11            Yes!
12@@ -120,6 +120,35 @@ scp ./delete.txt {{.Site.Domain}}:/</pre>
13         <pre># if the tty warning annoys you
14 echo "foobar" | ssh -T pastes.sh</pre>
15     </section>
16+
17+    <section id="expires">
18+        <h2 class="text-xl">
19+          <a href="#expires" rel="nofollow noopener">#</a>
20+          Can I set the expiration date to a paste?
21+        </h2>
22+        <p>
23+          Yes.  The default expiration date for a paste is 90 days.
24+          We do allow the user to set the paste to never expire.
25+          We also allow custom <a href="https://pkg.go.dev/time#ParseDuration">duration</a>
26+          or <a href="https://pkg.go.dev/github.com/araddon/dateparse#ParseStrict">timestamp</a>.
27+        </p>
28+        <pre>echo "foobar" | ssh pastes.sh FILENAME expires=false</pre>
29+        <pre>echo "foobar" | ssh pastes.sh FILENAME expires=2023-12-12</pre>
30+        <pre>echo "foobar" | ssh pastes.sh FILENAME expires=1h</pre>
31+    </section>
32+
33+    <section id="unlisted">
34+        <h2 class="text-xl">
35+          <a href="#unlisted" rel="nofollow noopener">#</a>
36+          Can I hide pastes from my landing page?
37+        </h2>
38+        <p>
39+          Yes.  Unlisted in this context means it does not show up on
40+          your user landing page where we show all of your pastes.
41+          In this case, yes, you can "hide" it using a pipe command.
42+        </p>
43+        <pre>echo "foobar" | ssh pastes.sh FILENAME hidden=true</pre>
44+    </section>
45 </main>
46 {{template "marketing-footer" .}}
47 {{end}}
M pastes/html/marketing.page.tmpl
+4, -2
 1@@ -85,7 +85,9 @@ echo "foobar" | ssh -T pastes.sh</pre>
 2     <section>
 3         <h2 class="text-lg font-bold">Features</h2>
 4         <ul>
 5-            <li>Pastes last 90 days</li>
 6+            <li>Pastes last <strong>90 days</strong> by default</li>
 7+            <li><a href="/help#expires">Ability to set custom expiration</a></li>
 8+            <li><a href="/help#unlisted">Ability to "hide" pastes</a></li>
 9             <li>Bring your own editor</li>
10             <li>Terminal workflow with no installation</li>
11             <li>Public-key based authentication</li>
12@@ -106,7 +108,7 @@ echo "foobar" | ssh -T pastes.sh</pre>
13     <section>
14         <h2 class="text-lg font-bold">Roadmap</h2>
15         <ol>
16-          <li>Ability to customize expiration</li>
17+          <li>Mobile support?</li>
18         </ol>
19     </section>
20 </main>
M pastes/html/post.page.tmpl
+1, -0
1@@ -33,6 +33,7 @@
2         <span> | </span>
3         <a href="{{.RawURL}}">raw</a>
4     </p>
5+    <p class="font-bold m-0">expires: {{.ExpiresAt}}</p>
6 </header>
7 <main>
8     <article>
M pastes/scp_hooks.go
+39, -41
 1@@ -43,57 +43,55 @@ func (p *FileHooks) FileMeta(s ssh.Session, data *filehandlers.PostMetaData) err
 2 		data.ExpiresAt = &expiresAt
 3 	}
 4 
 5-	if p.Db.HasFeatureForUser(data.User.ID, "pastes-advanced") {
 6-		var hidden bool
 7-		var expiresFound bool
 8-		var expires *time.Time
 9+	var hidden bool
10+	var expiresFound bool
11+	var expires *time.Time
12 
13-		cmd := s.Command()
14+	cmd := s.Command()
15 
16-		for _, arg := range cmd {
17-			if strings.Contains(arg, "=") {
18-				splitArg := strings.Split(arg, "=")
19-				if len(splitArg) != 2 {
20+	for _, arg := range cmd {
21+		if strings.Contains(arg, "=") {
22+			splitArg := strings.Split(arg, "=")
23+			if len(splitArg) != 2 {
24+				continue
25+			}
26+
27+			switch splitArg[0] {
28+			case "hidden":
29+				val, err := strconv.ParseBool(splitArg[1])
30+				if err != nil {
31+					continue
32+				}
33+
34+				hidden = val
35+			case "expires":
36+				val, err := strconv.ParseBool(splitArg[1])
37+				if err == nil {
38+					expiresFound = !val
39 					continue
40 				}
41 
42-				switch splitArg[0] {
43-				case "hidden":
44-					val, err := strconv.ParseBool(splitArg[1])
45-					if err != nil {
46-						continue
47-					}
48-
49-					hidden = val
50-				case "expires":
51-					val, err := strconv.ParseBool(splitArg[1])
52-					if err == nil {
53-						expiresFound = !val
54-						continue
55-					}
56-
57-					duration, err := time.ParseDuration(splitArg[1])
58-					if err == nil {
59-						expiresFound = true
60-						expireTime := time.Now().Add(duration)
61-						expires = &expireTime
62-						continue
63-					}
64-
65-					expireTime, err := dateparse.ParseStrict(splitArg[1])
66-					if err == nil {
67-						expiresFound = true
68-						expires = &expireTime
69-					}
70+				duration, err := time.ParseDuration(splitArg[1])
71+				if err == nil {
72+					expiresFound = true
73+					expireTime := time.Now().Add(duration)
74+					expires = &expireTime
75+					continue
76+				}
77+
78+				expireTime, err := dateparse.ParseStrict(splitArg[1])
79+				if err == nil {
80+					expiresFound = true
81+					expires = &expireTime
82 				}
83 			}
84 		}
85+	}
86 
87-		data.Hidden = hidden
88+	data.Hidden = hidden
89 
90-		if expiresFound {
91-			data.ExpiresAt = expires
92-		}
93+	if expiresFound {
94+		data.ExpiresAt = expires
95 	}
96 
97 	return nil