~netlandish/links-dev

links: Added support to specify which Sendy list-id to integrate with depending on the situation. v1 APPLIED

Peter Sanchez: 1
 Added support to specify which Sendy list-id to integrate with depending on the situation.

 6 files changed, 36 insertions(+), 16 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.code.netlandish.com/~netlandish/links-dev/patches/91/mbox | git am -3
Learn more about email & git

[PATCH links] Added support to specify which Sendy list-id to integrate with depending on the situation. Export this patch

Changelog-added: Specify Sendy list-id when integrating per situation
---
Also includes some misc cleanup done while working on this.

 accounts/processors.go        | 11 +++++++----
 accounts/userfetch.go         |  6 +++---
 api/graph/schema.resolvers.go | 17 +++++++++--------
 billing/processors.go         | 14 ++++++++++++++
 billing/routes_test.go        |  3 ++-
 config.example.ini            |  1 +
 6 files changed, 36 insertions(+), 16 deletions(-)

diff --git a/accounts/processors.go b/accounts/processors.go
index 8aa0fa4..b78e3ee 100644
--- a/accounts/processors.go
+++ b/accounts/processors.go
@@ -99,12 +99,12 @@ func AddWelcomeLinkTask(user gobwebs.User, gctx *server.Context) *work.Task {
	})
}

func sendSendySubscribe(ctx context.Context, user gobwebs.User, gctx *server.Context) error {
func sendSendySubscribe(ctx context.Context, user gobwebs.User, gctx *server.Context, listid string) error {
	u := user.(*models.User)
	file := gctx.Server.Config.File
	key, ok1 := file.Get("sendy", "api-key")
	url, ok2 := file.Get("sendy", "api-url")
	list, ok3 := file.Get("sendy", "list-id")
	list, ok3 := file.Get("sendy", listid)
	if !ok1 || !ok2 || !ok3 {
		gctx.Server.Logger().Printf("No Sendy config present. Failing silently")
		return nil
@@ -124,9 +124,12 @@ func sendSendySubscribe(ctx context.Context, user gobwebs.User, gctx *server.Con
	return nil
}

func SendySubscribeTask(user gobwebs.User, gctx *server.Context) *work.Task {
func SendySubscribeTask(user gobwebs.User, gctx *server.Context, listid string) *work.Task {
	return work.NewTask(func(ctx context.Context) error {
		return sendSendySubscribe(ctx, user, gctx)
		if listid == "" {
			listid = "list-id"
		}
		return sendSendySubscribe(ctx, user, gctx, listid)
	}).Retries(3).Before(func(ctx context.Context, task *work.Task) {
		gobwebs.TaskIDWork(task)
		gctx.Server.Logger().Printf(
diff --git a/accounts/userfetch.go b/accounts/userfetch.go
index c368bfd..6b8bba4 100644
--- a/accounts/userfetch.go
+++ b/accounts/userfetch.go
@@ -176,7 +176,7 @@ func (u *UserFetch) ProcessSuccessfulEmailConfirmation(c echo.Context) error {
	}

	// Sendy
	err = gctx.Server.QueueTask("general", SendySubscribeTask(user, gctx))
	err = gctx.Server.QueueTask("general", SendySubscribeTask(user, gctx, ""))
	if err != nil {
		gctx.Server.Logger().Printf("Error queueing SendySubscribeTask: %v", err)
	}
@@ -219,9 +219,9 @@ func (u *UserFetch) ProcessLogin(c echo.Context, user gobwebs.User) error {
		if err != nil {
			return err
		}
		return fmt.Errorf(lt.Translate("You must verify your email address before logging in"))
		return fmt.Errorf("%s", lt.Translate("You must verify your email address before logging in"))
	} else if linkUser.IsLocked {
		return fmt.Errorf(lt.Translate("This account is currently unable to access the system."))
		return fmt.Errorf("%s", lt.Translate("This account is currently unable to access the system."))
	}
	return nil
}
diff --git a/api/graph/schema.resolvers.go b/api/graph/schema.resolvers.go
index 2a3a255..9f02533 100644
--- a/api/graph/schema.resolvers.go
+++ b/api/graph/schema.resolvers.go
@@ -1286,7 +1286,7 @@ func (r *mutationResolver) Register(ctx context.Context, input *model.RegisterIn
		// Sendy users list. Log on error
		srv := server.ForContext(ctx)
		gctx := c.(*server.Context)
		err = srv.QueueTask("general", accounts.SendySubscribeTask(user, gctx))
		err = srv.QueueTask("general", accounts.SendySubscribeTask(user, gctx, ""))
		if err != nil {
			gctx.Server.Logger().Printf("Error queueing sendSendySubscribeTask: %v", err)
		}
@@ -1477,7 +1477,7 @@ func (r *mutationResolver) CompleteRegister(ctx context.Context, input *model.Co
	srv := server.ForContext(ctx)
	c := server.EchoForContext(ctx)
	gctx := c.(*server.Context)
	err = srv.QueueTask("general", accounts.SendySubscribeTask(user, gctx))
	err = srv.QueueTask("general", accounts.SendySubscribeTask(user, gctx, ""))
	if err != nil {
		gctx.Server.Logger().Printf("Error queueing sendSendySubscribeTask: %v", err)
	}
@@ -6238,6 +6238,13 @@ func (r *queryResolver) GetUsers(ctx context.Context, input *model.GetUserInput)
		return nil, nil

	}

	if input.After != nil && input.Before != nil {
		validator.Error("%s", lt.Translate("You can not send both after and before cursors")).
			WithCode(valid.ErrValidationGlobalCode)
		return nil, nil
	}

	opts := &database.FilterOptions{
		Filter: sq.And{
			sq.Eq{"o.org_type": models.OrgTypeUser},
@@ -6256,12 +6263,6 @@ func (r *queryResolver) GetUsers(ctx context.Context, input *model.GetUserInput)

	}

	if input.After != nil && input.Before != nil {
		validator.Error("%s", lt.Translate("You can not send both after and before cursors")).
			WithCode(valid.ErrValidationGlobalCode)
		return nil, nil
	}

	numElements := model.PaginationDefault
	var hasPrevPage bool
	var hasNextPage bool
diff --git a/billing/processors.go b/billing/processors.go
index bdc18f8..c75448c 100644
--- a/billing/processors.go
@@ -4,6 +4,7 @@ import (
	"context"
	"fmt"
	"links"
	"links/accounts"
	"links/internal/localizer"
	"links/models"
	"strings"
@@ -37,6 +38,7 @@ func ProcessCheckoutSessionCompletedTask(ctx context.Context, conf *config.Confi
	}
	org := orgs[0]

	srv := server.ForContext(ctx)
	stripeClient, err := GetStripeClient(conf)
	if err != nil {
		return err
@@ -135,6 +137,17 @@ func ProcessCheckoutSessionCompletedTask(ctx context.Context, conf *config.Confi
		return err
	}

	// Fetch user and add their email to Sendy paid user list. Ignore error fetching user
	user, err := models.GetUser(ctx, org.OwnerID, false)
	if err == nil {
		gctx := &server.Context{
			Server: srv,
			User:   user,
		}
		// Again, ignore errors here.
		srv.QueueTask("general", accounts.SendySubscribeTask(user, gctx, "paid-list-id"))
	}

	return nil
}

@@ -142,6 +155,7 @@ func CheckoutSessionCompletedTask(srv *server.Server, data map[string]any) *work
	return work.NewTask(func(ctx context.Context) error {
		ctx = database.Context(ctx, srv.DB)
		ctx = timezone.Context(ctx, "UTC")
		ctx = server.ServerContext(ctx, srv)
		return ProcessCheckoutSessionCompletedTask(ctx, srv.Config, data)
	}).Retries(3).Before(func(ctx context.Context, task *work.Task) {
		gobwebs.TaskIDWork(task)
diff --git a/billing/routes_test.go b/billing/routes_test.go
index 70d73d6..3082be4 100644
--- a/billing/routes_test.go
@@ -286,7 +286,8 @@ func TestWebhooks(t *testing.T) {
		httpmock.RegisterResponder("GET", "https://api.stripe.com/v1/subscriptions/stripe_subscription_id_test",
			httpmock.NewStringResponder(200, string(subscriptionsBody)))

		err = billing.ProcessCheckoutSessionCompletedTask(dbCtx, srv.Config, dataMap)
		srvCtx := server.ServerContext(dbCtx, srv)
		err = billing.ProcessCheckoutSessionCompletedTask(srvCtx, srv.Config, dataMap)
		c.NoError(err)

		opts := &database.FilterOptions{
diff --git a/config.example.ini b/config.example.ini
index caa93e7..7d56af8 100644
--- a/config.example.ini
+++ b/config.example.ini
@@ -222,3 +222,4 @@ enabled=true
api-key=API Key for Sendy
api-url=https://yoursendydomain.com
list-id=Sendy List ID
paid-list-id=Sendy Paid User List ID
-- 
2.47.2
Thanks!

To git@git.code.netlandish.com:~netlandish/links
   fad7b6a..b30ddca  master -> master