- commit
- 6710e0c
- parent
- 50f4110
- author
- Eric Bower
- date
- 2025-03-14 10:55:24 -0400 EDT
chore(auth): better pico+ rss feed items
4 files changed,
+85,
-23
1@@ -101,12 +101,12 @@ successfully added pico+ user
2 <name>team pico</name>
3 </author>
4 <entry>
5- <title>pico+ membership activated on 2021-08-15 14:30:45</title>
6+ <title>pico+ membership activated on 2021-08-15T14:30:45Z</title>
7 <updated>2021-08-15T14:30:45Z</updated>
8 <id>pico-plus-activated-1629037845</id>
9- <content type="html">Thanks for joining pico+! You now have access to all our premium services for exactly one year. We will send you pico+ expiration notifications through this RSS feed. Go to <a href="https://pico.sh/getting-started#next-steps">pico.sh/getting-started#next-steps</a> to start using our services.</content>
10+ <content type="html">
<html>
	<head>
		<title>pico+ activated</title>
		<style>
			code {
				background-color: #ddd;
				border-radius: 5px;
				padding: 1px 3px;
			}
		</style>
	</head>
	<body>
		<h1>Thanks for joining <code>pico+</code>!</h1>
<p>
	You now have access to all our premium services until <strong>2021-08-16</strong>.
</p>
<p>
	We will send you <code>pico+</code> expiration notifications through this RSS feed.
	Go to <a href="https://pico.sh/getting-started#next-steps">pico.sh/getting-started#next-steps</a>
	to start using our services.
</p>
<p>
	If you have any questions, please do not hesitate to <a href="https://pico.sh/contact">contact us</a>.
</p>
	</body>
</html>
</content>
11 <link href="https://pico.sh" rel="alternate"></link>
12- <summary type="html">Thanks for joining pico+! You now have access to all our premium services for exactly one year. We will send you pico+ expiration notifications through this RSS feed. Go to <a href="https://pico.sh/getting-started#next-steps">pico.sh/getting-started#next-steps</a> to start using our services.</summary>
13+ <summary type="html">
<html>
	<head>
		<title>pico+ activated</title>
		<style>
			code {
				background-color: #ddd;
				border-radius: 5px;
				padding: 1px 3px;
			}
		</style>
	</head>
	<body>
		<h1>Thanks for joining <code>pico+</code>!</h1>
<p>
	You now have access to all our premium services until <strong>2021-08-16</strong>.
</p>
<p>
	We will send you <code>pico+</code> expiration notifications through this RSS feed.
	Go to <a href="https://pico.sh/getting-started#next-steps">pico.sh/getting-started#next-steps</a>
	to start using our services.
</p>
<p>
	If you have any questions, please do not hesitate to <a href="https://pico.sh/contact">contact us</a>.
</p>
	</body>
</html>
</summary>
14 <author>
15 <name>team pico</name>
16 </author>
17@@ -115,9 +115,9 @@ successfully added pico+ user
18 <title>pico+ 1-month expiration notice</title>
19 <updated>2021-07-16T14:30:45Z</updated>
20 <id>1626445845</id>
21- <content type="html">Your pico+ membership is going to expire on 2021-08-16 14:30:45</content>
22+ <content type="html">
<html>
	<head>
		<title>pico+ 1-month expiration notification!</title>
		<style>
			code {
				background-color: #ddd;
				border-radius: 5px;
				padding: 1px 3px;
			}
		</style>
	</head>
	<body>
		<h1>pico+ 1-month expiration notification!</h1>
<p>
	Your <code>pico+</code> membership will expire on <strong>2021-08-16</strong>.
</p>
<p>
	If your pico+ membership expires then we will:

	<ul>
		<li>revoke access to <a href="https">https://tuns.sh</a></li>
		<li>reject new sites being created for <a href="https://pgs.sh">pgs.sh</a></li>
		<li>revoke access to our IRC bouncer</li>
	</ul>
</p>
<p>
	In order to continue using our premium services, you need to purchase another year:
	<a href="https://auth.pico.sh/checkout/user-a">purchase pico+</a>
</p>
<p>
	If you have any questions, please do not hesitate to <a href="https://pico.sh/contact">contact us</a>.
</p>
	</body>
</html>
</content>
23 <link href="https://pico.sh" rel="alternate"></link>
24- <summary type="html">Your pico+ membership is going to expire on 2021-08-16 14:30:45</summary>
25+ <summary type="html">
<html>
	<head>
		<title>pico+ 1-month expiration notification!</title>
		<style>
			code {
				background-color: #ddd;
				border-radius: 5px;
				padding: 1px 3px;
			}
		</style>
	</head>
	<body>
		<h1>pico+ 1-month expiration notification!</h1>
<p>
	Your <code>pico+</code> membership will expire on <strong>2021-08-16</strong>.
</p>
<p>
	If your pico+ membership expires then we will:

	<ul>
		<li>revoke access to <a href="https">https://tuns.sh</a></li>
		<li>reject new sites being created for <a href="https://pgs.sh">pgs.sh</a></li>
		<li>revoke access to our IRC bouncer</li>
	</ul>
</p>
<p>
	In order to continue using our premium services, you need to purchase another year:
	<a href="https://auth.pico.sh/checkout/user-a">purchase pico+</a>
</p>
<p>
	If you have any questions, please do not hesitate to <a href="https://pico.sh/contact">contact us</a>.
</p>
	</body>
</html>
</summary>
26 <author>
27 <name>team pico</name>
28 </author>
29@@ -126,9 +126,9 @@ successfully added pico+ user
30 <title>pico+ 1-week expiration notice</title>
31 <updated>2021-08-09T14:30:45Z</updated>
32 <id>1628519445</id>
33- <content type="html">Your pico+ membership is going to expire on 2021-08-16 14:30:45</content>
34+ <content type="html">
<html>
	<head>
		<title>pico+ 1-week expiration notification!</title>
		<style>
			code {
				background-color: #ddd;
				border-radius: 5px;
				padding: 1px 3px;
			}
		</style>
	</head>
	<body>
		<h1>pico+ 1-week expiration notification!</h1>
<p>
	Your <code>pico+</code> membership will expire on <strong>2021-08-16</strong>.
</p>
<p>
	If your pico+ membership expires then we will:

	<ul>
		<li>revoke access to <a href="https">https://tuns.sh</a></li>
		<li>reject new sites being created for <a href="https://pgs.sh">pgs.sh</a></li>
		<li>revoke access to our IRC bouncer</li>
	</ul>
</p>
<p>
	In order to continue using our premium services, you need to purchase another year:
	<a href="https://auth.pico.sh/checkout/user-a">purchase pico+</a>
</p>
<p>
	If you have any questions, please do not hesitate to <a href="https://pico.sh/contact">contact us</a>.
</p>
	</body>
</html>
</content>
35 <link href="https://pico.sh" rel="alternate"></link>
36- <summary type="html">Your pico+ membership is going to expire on 2021-08-16 14:30:45</summary>
37+ <summary type="html">
<html>
	<head>
		<title>pico+ 1-week expiration notification!</title>
		<style>
			code {
				background-color: #ddd;
				border-radius: 5px;
				padding: 1px 3px;
			}
		</style>
	</head>
	<body>
		<h1>pico+ 1-week expiration notification!</h1>
<p>
	Your <code>pico+</code> membership will expire on <strong>2021-08-16</strong>.
</p>
<p>
	If your pico+ membership expires then we will:

	<ul>
		<li>revoke access to <a href="https">https://tuns.sh</a></li>
		<li>reject new sites being created for <a href="https://pgs.sh">pgs.sh</a></li>
		<li>revoke access to our IRC bouncer</li>
	</ul>
</p>
<p>
	In order to continue using our premium services, you need to purchase another year:
	<a href="https://auth.pico.sh/checkout/user-a">purchase pico+</a>
</p>
<p>
	If you have any questions, please do not hesitate to <a href="https://pico.sh/contact">contact us</a>.
</p>
	</body>
</html>
</summary>
38 <author>
39 <name>team pico</name>
40 </author>
41@@ -137,9 +137,9 @@ successfully added pico+ user
42 <title>pico+ 1-day expiration notice</title>
43 <updated>2021-08-14T14:30:45Z</updated>
44 <id>1628951445</id>
45- <content type="html">Your pico+ membership is going to expire on 2021-08-16 14:30:45</content>
46+ <content type="html">
<html>
	<head>
		<title>pico+ 1-day expiration notification!</title>
		<style>
			code {
				background-color: #ddd;
				border-radius: 5px;
				padding: 1px 3px;
			}
		</style>
	</head>
	<body>
		<h1>pico+ 1-day expiration notification!</h1>
<p>
	Your <code>pico+</code> membership will expire on <strong>2021-08-16</strong>.
</p>
<p>
	If your pico+ membership expires then we will:

	<ul>
		<li>revoke access to <a href="https">https://tuns.sh</a></li>
		<li>reject new sites being created for <a href="https://pgs.sh">pgs.sh</a></li>
		<li>revoke access to our IRC bouncer</li>
	</ul>
</p>
<p>
	In order to continue using our premium services, you need to purchase another year:
	<a href="https://auth.pico.sh/checkout/user-a">purchase pico+</a>
</p>
<p>
	If you have any questions, please do not hesitate to <a href="https://pico.sh/contact">contact us</a>.
</p>
	</body>
</html>
</content>
47 <link href="https://pico.sh" rel="alternate"></link>
48- <summary type="html">Your pico+ membership is going to expire on 2021-08-16 14:30:45</summary>
49+ <summary type="html">
<html>
	<head>
		<title>pico+ 1-day expiration notification!</title>
		<style>
			code {
				background-color: #ddd;
				border-radius: 5px;
				padding: 1px 3px;
			}
		</style>
	</head>
	<body>
		<h1>pico+ 1-day expiration notification!</h1>
<p>
	Your <code>pico+</code> membership will expire on <strong>2021-08-16</strong>.
</p>
<p>
	If your pico+ membership expires then we will:

	<ul>
		<li>revoke access to <a href="https">https://tuns.sh</a></li>
		<li>reject new sites being created for <a href="https://pgs.sh">pgs.sh</a></li>
		<li>revoke access to our IRC bouncer</li>
	</ul>
</p>
<p>
	In order to continue using our premium services, you need to purchase another year:
	<a href="https://auth.pico.sh/checkout/user-a">purchase pico+</a>
</p>
<p>
	If you have any questions, please do not hesitate to <a href="https://pico.sh/contact">contact us</a>.
</p>
	</body>
</html>
</summary>
50 <author>
51 <name>team pico</name>
52 </author>
+1,
-1
1@@ -340,7 +340,7 @@ func rssHandler(apiConfig *shared.ApiConfig) http.HandlerFunc {
2 return
3 }
4
5- feed, err := shared.UserFeed(apiConfig.Dbpool, user.ID, apiToken)
6+ feed, err := shared.UserFeed(apiConfig.Dbpool, user, apiToken)
7 if err != nil {
8 return
9 }
+1,
-1
1@@ -19,7 +19,7 @@ import (
2 )
3
4 func NewTabWriter(out io.Writer) *tabwriter.Writer {
5- return tabwriter.NewWriter(out, 0, 0, 1, ' ', tabwriter.TabIndent)
6+ return tabwriter.NewWriter(out, 0, 0, 2, ' ', tabwriter.TabIndent)
7 }
8
9 func projectTable(sesh io.Writer, projects []*db.Project) {
1@@ -8,10 +8,71 @@ import (
2 "github.com/picosh/pico/pkg/db"
3 )
4
5-func UserFeed(me db.DB, userID, token string) (*feeds.Feed, error) {
6+func genUserFeedTmpl(title, msg string) string {
7+ return fmt.Sprintf(`
8+<html>
9+ <head>
10+ <title>%s</title>
11+ <style>
12+ code {
13+ background-color: #ddd;
14+ border-radius: 5px;
15+ padding: 1px 3px;
16+ }
17+ </style>
18+ </head>
19+ <body>
20+ %s
21+ </body>
22+</html>
23+`, title, msg)
24+}
25+
26+func PicoPlusFeed(expiration time.Time) string {
27+ msg := fmt.Sprintf(`<h1>Thanks for joining <code>pico+</code>!</h1>
28+<p>
29+ You now have access to all our premium services until <strong>%s</strong>.
30+</p>
31+<p>
32+ We will send you <code>pico+</code> expiration notifications through this RSS feed.
33+ Go to <a href="https://pico.sh/getting-started#next-steps">pico.sh/getting-started#next-steps</a>
34+ to start using our services.
35+</p>
36+<p>
37+ If you have any questions, please do not hesitate to <a href="https://pico.sh/contact">contact us</a>.
38+</p>`, expiration.Format(time.DateOnly))
39+ return genUserFeedTmpl("pico+ activated", msg)
40+}
41+
42+func PicoPlusExpirationFeed(expiration time.Time, txt string, plusLink string) string {
43+ title := fmt.Sprintf("pico+ %s expiration notification!", txt)
44+ msg := fmt.Sprintf(`<h1>%s</h1>
45+<p>
46+ Your <code>pico+</code> membership will expire on <strong>%s</strong>.
47+</p>
48+<p>
49+ If your pico+ membership expires then we will:
50+
51+ <ul>
52+ <li>revoke access to <a href="https">https://tuns.sh</a></li>
53+ <li>reject new sites being created for <a href="https://pgs.sh">pgs.sh</a></li>
54+ <li>revoke access to our IRC bouncer</li>
55+ </ul>
56+</p>
57+<p>
58+ In order to continue using our premium services, you need to purchase another year:
59+ <a href="%s">purchase pico+</a>
60+</p>
61+<p>
62+ If you have any questions, please do not hesitate to <a href="https://pico.sh/contact">contact us</a>.
63+</p>`, title, expiration.Format(time.DateOnly), plusLink)
64+ return genUserFeedTmpl(title, msg)
65+}
66+
67+func UserFeed(me db.DB, user *db.User, token string) (*feeds.Feed, error) {
68 var err error
69 if token == "" {
70- token, err = me.UpsertToken(userID, "pico-rss")
71+ token, err = me.UpsertToken(user.ID, "pico-rss")
72 if err != nil {
73 return nil, err
74 }
75@@ -28,14 +89,14 @@ func UserFeed(me db.DB, userID, token string) (*feeds.Feed, error) {
76 var feedItems []*feeds.Item
77
78 now := time.Now()
79- ff, err := me.FindFeatureForUser(userID, "plus")
80+ ff, err := me.FindFeatureForUser(user.ID, "plus")
81 if err != nil {
82 // still want to send an empty feed
83 } else {
84 createdAt := ff.CreatedAt
85- createdAtStr := createdAt.Format("2006-01-02 15:04:05")
86+ createdAtStr := createdAt.Format(time.RFC3339)
87 id := fmt.Sprintf("pico-plus-activated-%d", createdAt.Unix())
88- content := `Thanks for joining pico+! You now have access to all our premium services for exactly one year. We will send you pico+ expiration notifications through this RSS feed. Go to <a href="https://pico.sh/getting-started#next-steps">pico.sh/getting-started#next-steps</a> to start using our services.`
89+ content := PicoPlusFeed(*ff.ExpiresAt)
90 plus := &feeds.Item{
91 Id: id,
92 Title: fmt.Sprintf("pico+ membership activated on %s", createdAtStr),
93@@ -49,19 +110,19 @@ func UserFeed(me db.DB, userID, token string) (*feeds.Feed, error) {
94 feedItems = append(feedItems, plus)
95
96 oneMonthWarning := ff.ExpiresAt.AddDate(0, -1, 0)
97- mo := genFeedItem(now, *ff.ExpiresAt, oneMonthWarning, "1-month")
98+ mo := genFeedItem(user.Name, now, *ff.ExpiresAt, oneMonthWarning, "1-month")
99 if mo != nil {
100 feedItems = append(feedItems, mo)
101 }
102
103 oneWeekWarning := ff.ExpiresAt.AddDate(0, 0, -7)
104- wk := genFeedItem(now, *ff.ExpiresAt, oneWeekWarning, "1-week")
105+ wk := genFeedItem(user.Name, now, *ff.ExpiresAt, oneWeekWarning, "1-week")
106 if wk != nil {
107 feedItems = append(feedItems, wk)
108 }
109
110 oneDayWarning := ff.ExpiresAt.AddDate(0, 0, -2)
111- day := genFeedItem(now, *ff.ExpiresAt, oneDayWarning, "1-day")
112+ day := genFeedItem(user.Name, now, *ff.ExpiresAt, oneDayWarning, "1-day")
113 if day != nil {
114 feedItems = append(feedItems, day)
115 }
116@@ -71,11 +132,12 @@ func UserFeed(me db.DB, userID, token string) (*feeds.Feed, error) {
117 return feed, nil
118 }
119
120-func genFeedItem(now time.Time, expiresAt time.Time, warning time.Time, txt string) *feeds.Item {
121+func genFeedItem(userName string, now time.Time, expiresAt time.Time, warning time.Time, txt string) *feeds.Item {
122 if now.After(warning) {
123- content := fmt.Sprintf(
124- "Your pico+ membership is going to expire on %s",
125- expiresAt.Format("2006-01-02 15:04:05"),
126+ content := PicoPlusExpirationFeed(
127+ expiresAt,
128+ txt,
129+ "https://auth.pico.sh/checkout/"+userName,
130 )
131 return &feeds.Item{
132 Id: fmt.Sprintf("%d", warning.Unix()),