1
0
Fork 0
mirror of https://github.com/binwiederhier/ntfy.git synced 2025-11-28 19:32:14 +01:00

Make it easy to build without Stripe

This commit is contained in:
binwiederhier 2025-08-07 16:41:39 +02:00
parent 32fa8d43c1
commit ea338ae4fa
11 changed files with 89 additions and 41 deletions

View file

@ -16,10 +16,10 @@ import (
"syscall"
"time"
"github.com/stripe/stripe-go/v74"
"github.com/urfave/cli/v2"
"github.com/urfave/cli/v2/altsrc"
"heckel.io/ntfy/v2/log"
"heckel.io/ntfy/v2/payments"
"heckel.io/ntfy/v2/server"
"heckel.io/ntfy/v2/user"
"heckel.io/ntfy/v2/util"
@ -320,6 +320,8 @@ func execServe(c *cli.Context) error {
return errors.New("cannot set enable-signup, enable-login, enable-reserve-topics, or stripe-secret-key if auth-file is not set")
} else if enableSignup && !enableLogin {
return errors.New("cannot set enable-signup without also setting enable-login")
} else if !payments.Available && (stripeSecretKey != "" || stripeWebhookKey != "") {
return errors.New("cannot set stripe-secret-key or stripe-webhook-key, support for payments is not available in this build (nopayments)")
} else if stripeSecretKey != "" && (stripeWebhookKey == "" || baseURL == "") {
return errors.New("if stripe-secret-key is set, stripe-webhook-key and base-url must also be set")
} else if twilioAccount != "" && (twilioAuthToken == "" || twilioPhoneNumber == "" || twilioVerifyService == "" || baseURL == "" || authFile == "") {
@ -396,8 +398,7 @@ func execServe(c *cli.Context) error {
// Stripe things
if stripeSecretKey != "" {
stripe.EnableTelemetry = false // Whoa!
stripe.Key = stripeSecretKey
payments.Setup(stripeSecretKey)
}
// Add default forbidden topics

33
main.go
View file

@ -3,9 +3,11 @@ package main
import (
"fmt"
"github.com/urfave/cli/v2"
"go/build"
"heckel.io/ntfy/v2/cmd"
"os"
"runtime"
"strings"
)
var (
@ -15,16 +17,7 @@ var (
)
func main() {
cli.AppHelpTemplate += fmt.Sprintf(`
Try 'ntfy COMMAND --help' or https://ntfy.sh/docs/ for more information.
To report a bug, open an issue on GitHub: https://github.com/binwiederhier/ntfy/issues.
If you want to chat, simply join the Discord server (https://discord.gg/cT7ECsZj9w), or
the Matrix room (https://matrix.to/#/#ntfy:matrix.org).
ntfy %s (%s), runtime %s, built at %s
Copyright (C) Philipp C. Heckel, licensed under Apache License 2.0 & GPLv2
`, version, commit[:7], runtime.Version(), date)
cli.AppHelpTemplate += buildHelp()
app := cmd.New()
app.Version = version
@ -34,3 +27,23 @@ Copyright (C) Philipp C. Heckel, licensed under Apache License 2.0 & GPLv2
os.Exit(1)
}
}
func buildHelp() string {
if len(commit) > 7 {
commit = commit[:7]
}
var tags string
if len(build.Default.BuildTags) > 0 {
tags = ", with tags " + strings.Join(build.Default.BuildTags, ", ")
}
return fmt.Sprintf(`
Try 'ntfy COMMAND --help' or https://ntfy.sh/docs/ for more information.
To report a bug, open an issue on GitHub: https://github.com/binwiederhier/ntfy/issues.
If you want to chat, simply join the Discord server (https://discord.gg/cT7ECsZj9w), or
the Matrix room (https://matrix.to/#/#ntfy:matrix.org).
ntfy %s (%s), runtime %s, built at %s%s
Copyright (C) Philipp C. Heckel, licensed under Apache License 2.0 & GPLv2
`, version, commit, runtime.Version(), date, tags)
}

16
payments/payments.go Normal file
View file

@ -0,0 +1,16 @@
//go:build !nopayments
package payments
import "github.com/stripe/stripe-go/v74"
const Available = true
type SubscriptionStatus stripe.SubscriptionStatus
type PriceRecurringInterval stripe.PriceRecurringInterval
func Setup(stripeSecretKey string) {
stripe.EnableTelemetry = false // Whoa!
stripe.Key = stripeSecretKey
}

View file

@ -0,0 +1,13 @@
//go:build nopayments
package payments
const Available = false
type SubscriptionStatus string
type PriceRecurringInterval string
func Setup(stripeSecretKey string) {
// Nothing to see here
}

View file

@ -10,6 +10,7 @@ import (
"errors"
"fmt"
"gopkg.in/yaml.v2"
"heckel.io/ntfy/v2/payments"
"io"
"net"
"net/http"
@ -165,7 +166,7 @@ func New(conf *Config) (*Server, error) {
mailer = &smtpSender{config: conf}
}
var stripe stripeAPI
if hasStripe && conf.StripeSecretKey != "" {
if payments.Available && conf.StripeSecretKey != "" {
stripe = newStripeAPI()
}
messageCache, err := createMessageCache(conf)

View file

@ -14,6 +14,7 @@ import (
"github.com/stripe/stripe-go/v74/subscription"
"github.com/stripe/stripe-go/v74/webhook"
"heckel.io/ntfy/v2/log"
"heckel.io/ntfy/v2/payments"
"heckel.io/ntfy/v2/user"
"heckel.io/ntfy/v2/util"
"io"
@ -44,8 +45,6 @@ import (
// This is used to keep the local user database fields up to date. Stripe is the source of truth.
// What Stripe says is mirrored and not questioned.
const hasStripe = true
var (
errNotAPaidTier = errors.New("tier does not have billing price identifier")
errMultipleBillingSubscriptions = errors.New("cannot have multiple billing subscriptions")
@ -468,8 +467,8 @@ func (s *Server) updateSubscriptionAndTier(r *http.Request, v *visitor, u *user.
billing := &user.Billing{
StripeCustomerID: customerID,
StripeSubscriptionID: subscriptionID,
StripeSubscriptionStatus: stripe.SubscriptionStatus(status),
StripeSubscriptionInterval: stripe.PriceRecurringInterval(interval),
StripeSubscriptionStatus: payments.SubscriptionStatus(status),
StripeSubscriptionInterval: payments.PriceRecurringInterval(interval),
StripeSubscriptionPaidUntil: time.Unix(paidUntil, 0),
StripeSubscriptionCancelAt: time.Unix(cancelAt, 0),
}

View file

@ -2,7 +2,21 @@
package server
const hasStripe = false
import (
"net/http"
)
type stripeAPI interface {
CancelSubscription(id string) (string, error)
}
func newStripeAPI() stripeAPI {
return nil
}
func (s *Server) fetchStripePrices() (map[string]int64, error) {
return nil, errHTTPNotFound
}
func (s *Server) handleBillingTiersGet(w http.ResponseWriter, _ *http.Request, _ *visitor) error {
return errHTTPNotFound
@ -31,11 +45,3 @@ func (s *Server) handleAccountBillingPortalSessionCreate(w http.ResponseWriter,
func (s *Server) handleAccountBillingWebhook(_ http.ResponseWriter, r *http.Request, v *visitor) error {
return errHTTPNotFound
}
func (s *Server) handleAccountBillingWebhookSubscriptionUpdated(r *http.Request, v *visitor, event stripe.Event) error {
return errHTTPNotFound
}
func (s *Server) handleAccountBillingWebhookSubscriptionDeleted(r *http.Request, v *visitor, event stripe.Event) error {
return errHTTPNotFound
}

View file

@ -1 +0,0 @@
package stripe

View file

@ -7,9 +7,9 @@ import (
"errors"
"fmt"
"github.com/mattn/go-sqlite3"
"github.com/stripe/stripe-go/v74"
"golang.org/x/crypto/bcrypt"
"heckel.io/ntfy/v2/log"
"heckel.io/ntfy/v2/payments"
"heckel.io/ntfy/v2/util"
"net/netip"
"path/filepath"
@ -1242,12 +1242,12 @@ func (a *Manager) readUser(rows *sql.Rows) (*User, error) {
Calls: calls,
},
Billing: &Billing{
StripeCustomerID: stripeCustomerID.String, // May be empty
StripeSubscriptionID: stripeSubscriptionID.String, // May be empty
StripeSubscriptionStatus: stripe.SubscriptionStatus(stripeSubscriptionStatus.String), // May be empty
StripeSubscriptionInterval: stripe.PriceRecurringInterval(stripeSubscriptionInterval.String), // May be empty
StripeSubscriptionPaidUntil: time.Unix(stripeSubscriptionPaidUntil.Int64, 0), // May be zero
StripeSubscriptionCancelAt: time.Unix(stripeSubscriptionCancelAt.Int64, 0), // May be zero
StripeCustomerID: stripeCustomerID.String, // May be empty
StripeSubscriptionID: stripeSubscriptionID.String, // May be empty
StripeSubscriptionStatus: payments.SubscriptionStatus(stripeSubscriptionStatus.String), // May be empty
StripeSubscriptionInterval: payments.PriceRecurringInterval(stripeSubscriptionInterval.String), // May be empty
StripeSubscriptionPaidUntil: time.Unix(stripeSubscriptionPaidUntil.Int64, 0), // May be zero
StripeSubscriptionCancelAt: time.Unix(stripeSubscriptionCancelAt.Int64, 0), // May be zero
},
Deleted: deleted.Valid,
}

View file

@ -4,8 +4,8 @@ import (
"database/sql"
"fmt"
"github.com/stretchr/testify/require"
"github.com/stripe/stripe-go/v74"
"golang.org/x/crypto/bcrypt"
"heckel.io/ntfy/v2/payments"
"heckel.io/ntfy/v2/util"
"net/netip"
"path/filepath"
@ -164,8 +164,8 @@ func TestManager_AddUser_And_Query(t *testing.T) {
require.Nil(t, a.ChangeBilling("user", &Billing{
StripeCustomerID: "acct_123",
StripeSubscriptionID: "sub_123",
StripeSubscriptionStatus: stripe.SubscriptionStatusActive,
StripeSubscriptionInterval: stripe.PriceRecurringIntervalMonth,
StripeSubscriptionStatus: payments.SubscriptionStatusActive,
StripeSubscriptionInterval: payments.PriceRecurringIntervalMonth,
StripeSubscriptionPaidUntil: time.Now().Add(time.Hour),
StripeSubscriptionCancelAt: time.Unix(0, 0),
}))

View file

@ -2,8 +2,8 @@ package user
import (
"errors"
"github.com/stripe/stripe-go/v74"
"heckel.io/ntfy/v2/log"
"heckel.io/ntfy/v2/payments"
"net/netip"
"strings"
"time"
@ -140,8 +140,8 @@ type Stats struct {
type Billing struct {
StripeCustomerID string
StripeSubscriptionID string
StripeSubscriptionStatus stripe.SubscriptionStatus
StripeSubscriptionInterval stripe.PriceRecurringInterval
StripeSubscriptionStatus payments.SubscriptionStatus
StripeSubscriptionInterval payments.PriceRecurringInterval
StripeSubscriptionPaidUntil time.Time
StripeSubscriptionCancelAt time.Time
}