repos / pico

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

commit
ed582ae
parent
65ca2e2
author
Eric Bower
date
2024-02-29 19:37:20 +0000 UTC
chore: pico+ go script
4 files changed,  +120, -0
M Makefile
+4, -0
 1@@ -73,6 +73,10 @@ store-clean:
 2 	WRITE=$(WRITE) go run ./cmd/scripts/clean-object-store/clean.go
 3 .PHONY: store-clean
 4 
 5+pico-plus:
 6+	go run ./cmd/scripts/pico-plus/main.go $(USER) $(TXID)
 7+.PHONY: pico-plus
 8+
 9 scripts:
10 	# might need to set MINIO_URL
11 	docker run --rm -it --env-file .env -v $(shell pwd):/app -w /app golang:1.21 /bin/bash
A cmd/scripts/pico-plus/main.go
+32, -0
 1@@ -0,0 +1,32 @@
 2+package main
 3+
 4+import (
 5+	"log/slog"
 6+	"os"
 7+
 8+	"github.com/picosh/pico/db/postgres"
 9+)
10+
11+func main() {
12+	logger := slog.Default()
13+	DbURL := os.Getenv("DATABASE_URL")
14+	dbpool := postgres.NewDB(DbURL, logger)
15+
16+	args := os.Args
17+	username := args[1]
18+	txId := args[2]
19+
20+	logger.Info(
21+		"Upgrading user to pico+",
22+		"username", username,
23+		"txId", txId,
24+	)
25+
26+	err := dbpool.AddPicoPlusUser(username, txId)
27+	if err != nil {
28+		logger.Error("Failed to add pico+ user", "err", err)
29+		os.Exit(1)
30+	} else {
31+		logger.Info("Successfully added pico+ user")
32+	}
33+}
M db/db.go
+22, -0
 1@@ -235,6 +235,27 @@ func (p *FeatureFlagData) Scan(value interface{}) error {
 2 	return json.Unmarshal(b, &p)
 3 }
 4 
 5+type PaymentHistoryData struct {
 6+	Notes string `json:"notes"`
 7+	TxID  string `json:"tx_id"`
 8+}
 9+
10+// Make the Attrs struct implement the driver.Valuer interface. This method
11+// simply returns the JSON-encoded representation of the struct.
12+func (p PaymentHistoryData) Value() (driver.Value, error) {
13+	return json.Marshal(p)
14+}
15+
16+// Make the Attrs struct implement the sql.Scanner interface. This method
17+// simply decodes a JSON-encoded value into the struct fields.
18+func (p *PaymentHistoryData) Scan(value interface{}) error {
19+	b, ok := value.([]byte)
20+	if !ok {
21+		return errors.New("type assertion to []byte failed")
22+	}
23+	return json.Unmarshal(b, &p)
24+}
25+
26 type ErrMultiplePublicKeys struct{}
27 
28 func (m *ErrMultiplePublicKeys) Error() string {
29@@ -303,6 +324,7 @@ type DB interface {
30 
31 	AddViewCount(postID string) (int, error)
32 
33+	AddPicoPlusUser(username string, txId string) error
34 	FindFeatureForUser(userID string, feature string) (*FeatureFlag, error)
35 	HasFeatureForUser(userID string, feature string) bool
36 	FindTotalSizeForUser(userID string) (int, error)
M db/postgres/storage.go
+62, -0
 1@@ -1540,3 +1540,65 @@ func (me *PsqlDB) FindTokensForUser(userID string) ([]*db.Token, error) {
 2 	}
 3 	return keys, nil
 4 }
 5+
 6+func (me *PsqlDB) AddPicoPlusUser(username, txId string) error {
 7+	user, err := me.FindUserForName(username)
 8+	if err != nil {
 9+		return err
10+	}
11+
12+	ctx := context.Background()
13+	tx, err := me.Db.BeginTx(ctx, nil)
14+	if err != nil {
15+		return err
16+	}
17+	defer func() {
18+		err = tx.Rollback()
19+	}()
20+
21+	if txId != "" {
22+		data := db.PaymentHistoryData{
23+			Notes: "",
24+			TxID:  txId,
25+		}
26+		_, err := tx.Exec(
27+			`INSERT INTO payment_history (user_id, payment_type, amount, data) VALUES ($1, 'stripe', 20 * 1000000, $2);`,
28+			user.ID,
29+			data,
30+		)
31+		if err != nil {
32+			fmt.Println(err)
33+			return err
34+		}
35+	}
36+
37+	pgsQuery := `INSERT INTO feature_flags (user_id, name, data, expires_at)
38+	VALUES ($1, 'pgs', '{"storage_max":10000000000, "file_max":50000000}'::jsonb, now() + '1 year'::interval);`
39+	_, err = tx.Exec(pgsQuery, user.ID)
40+	if err != nil {
41+		return err
42+	}
43+
44+	imgsQuery := `INSERT INTO feature_flags (user_id, name, data, expires_at)
45+	VALUES ($1, 'imgs', '{"storage_max":2000000000}'::jsonb, now() + '1 year'::interval);`
46+	_, err = tx.Exec(imgsQuery, user.ID)
47+	if err != nil {
48+		return err
49+	}
50+
51+	proseQuery := `INSERT INTO feature_flags (user_id, name, data, expires_at)
52+	VALUES ($1, 'prose', '{"storage_max":1000000000, "file_max":50000000}'::jsonb, now() + '1 year'::interval);`
53+	_, err = tx.Exec(proseQuery, user.ID)
54+	if err != nil {
55+		return err
56+	}
57+
58+	tunsQuery := `INSERT INTO feature_flags (user_id, name, expires_at)
59+	VALUES ($1, 'tuns', now() + '1 year'::interval);`
60+	_, err = tx.Exec(tunsQuery, user.ID)
61+	if err != nil {
62+		return err
63+	}
64+
65+	return tx.Commit()
66+}