Working payment with stripe
This commit is contained in:
parent
106dac39e6
commit
435149ad5e
52
Chat.go
52
Chat.go
@ -3,6 +3,8 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
@ -19,7 +21,20 @@ func ChatPageHandler(c *fiber.Ctx) error {
|
||||
edgeClient = edgeClient.WithGlobals(map[string]interface{}{"ext::auth::client_token": authCookie})
|
||||
}
|
||||
|
||||
return c.Render("chat", fiber.Map{"IsLogin": checkIfLogin(), "HaveKey": checkIfHaveKey(), "IsSubscribed": IsCurrentUserSubscribed(), "IsLimiteReached": IsCurrentUserLimiteReached()}, "layouts/main")
|
||||
var (
|
||||
isSub bool
|
||||
limitReach bool
|
||||
)
|
||||
|
||||
if !checkIfLogin() {
|
||||
isSub = false
|
||||
limitReach = false
|
||||
} else {
|
||||
isSub = IsCurrentUserSubscribed()
|
||||
limitReach = IsCurrentUserLimiteReached()
|
||||
}
|
||||
|
||||
return c.Render("chat", fiber.Map{"IsLogin": checkIfLogin(), "HaveKey": checkIfHaveKey(), "IsSubscribed": isSub, "IsLimiteReached": limitReach}, "layouts/main")
|
||||
}
|
||||
|
||||
func DeleteMessageHandler(c *fiber.Ctx) error {
|
||||
@ -276,9 +291,20 @@ func generateEnterKeyChatHTML() string {
|
||||
func generateLimitReachedChatHTML() string {
|
||||
welcomeMessage := `You have reached the maximum number of messages for a free account. Please upgrade your account to continue using JADE.`
|
||||
|
||||
var result User
|
||||
err := edgeClient.QuerySingle(edgeCtx, "SELECT global currentUser { stripe_id, email } LIMIT 1;", &result)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
clientSecretSession := CreateClientSecretSession()
|
||||
|
||||
// TODO Replace by live API call
|
||||
stripeTable := `
|
||||
<stripe-pricing-table pricing-table-id="prctbl_1PJAxDP2nW0okNQyY0Q3mbg4"
|
||||
publishable-key="pk_live_51OxXuWP2nW0okNQyme1qdwbL535jbMmM1uIUi6U5zcvEUUwKraktmpCzudXNdPSTxlHpw2FbCtxpwbyFFcasQ7aj000tJJGpWW">
|
||||
<stripe-pricing-table
|
||||
pricing-table-id="prctbl_1OxrazP2nW0okNQymYvskUk7"
|
||||
publishable-key="pk_test_51OxXuWP2nW0okNQy2jyS70vx7WHZzDskvQazsitSDJQ3ifVHPqAkMv7orCePwRGRTarNn8uMuaxbVqD2Zg80oRc600epN4ycQ4"
|
||||
customer-session-client-secret="` + clientSecretSession + `">
|
||||
</stripe-pricing-table>`
|
||||
|
||||
htmlString := "<div class='columns is-centered' id='chat-container'><div class='column is-12-mobile is-8-tablet is-6-desktop' id='chat-messages'>"
|
||||
@ -518,7 +544,7 @@ func GenerateModelPopoverHTML(refresh bool) string {
|
||||
openaiExists, anthropicExists, mistralExists, groqExists, gooseaiExists, googleExists := getExistingKeys()
|
||||
|
||||
var llms []LLM
|
||||
err := edgeClient.Query(context.Background(), `
|
||||
err := edgeClient.Query(edgeCtx, `
|
||||
SELECT LLM {
|
||||
id,
|
||||
name,
|
||||
@ -573,6 +599,23 @@ func LoadSettingsHandler(c *fiber.Ctx) error {
|
||||
return c.SendString("")
|
||||
}
|
||||
|
||||
var user User
|
||||
err := edgeClient.QuerySingle(edgeCtx, `
|
||||
SELECT User {
|
||||
email
|
||||
}
|
||||
FILTER .id = global currentUser.id
|
||||
`, &user)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Percent encoding of the email
|
||||
user.Email = url.QueryEscape(user.Email)
|
||||
|
||||
stripeSubLink := "https://billing.stripe.com/p/login/test_eVa5kC1q7dogaaIcMM?prefilled_email=" + user.Email
|
||||
fmt.Println(stripeSubLink)
|
||||
|
||||
openaiExists, anthropicExists, mistralExists, groqExists, gooseaiExists, googleExists := getExistingKeys()
|
||||
|
||||
out, err := pongo2.Must(pongo2.FromFile("views/partials/popover-settings.html")).Execute(pongo2.Context{
|
||||
@ -585,6 +628,7 @@ func LoadSettingsHandler(c *fiber.Ctx) error {
|
||||
"GoogleExists": googleExists,
|
||||
"AnyExists": openaiExists || anthropicExists || mistralExists || groqExists || gooseaiExists || googleExists,
|
||||
"IsSub": IsCurrentUserSubscribed(),
|
||||
"StripeSubLink": stripeSubLink,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
121
Stripe.go
121
Stripe.go
@ -1,8 +1,16 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/flosch/pongo2"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/stripe/stripe-go"
|
||||
"github.com/stripe/stripe-go/customer"
|
||||
)
|
||||
|
||||
func PricingTableHandler(c *fiber.Ctx) error {
|
||||
@ -10,9 +18,20 @@ func PricingTableHandler(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
func generatePricingTableChatHTML() string {
|
||||
var result User
|
||||
err := edgeClient.QuerySingle(edgeCtx, "SELECT global currentUser { stripe_id, email } LIMIT 1;", &result)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
clientSecretSession := CreateClientSecretSession()
|
||||
|
||||
// TODO Replace by live API call
|
||||
stripeTable := `
|
||||
<stripe-pricing-table pricing-table-id="prctbl_1PJAxDP2nW0okNQyY0Q3mbg4"
|
||||
publishable-key="pk_live_51OxXuWP2nW0okNQyme1qdwbL535jbMmM1uIUi6U5zcvEUUwKraktmpCzudXNdPSTxlHpw2FbCtxpwbyFFcasQ7aj000tJJGpWW">
|
||||
<stripe-pricing-table
|
||||
pricing-table-id="prctbl_1OxrazP2nW0okNQymYvskUk7"
|
||||
publishable-key="pk_test_51OxXuWP2nW0okNQy2jyS70vx7WHZzDskvQazsitSDJQ3ifVHPqAkMv7orCePwRGRTarNn8uMuaxbVqD2Zg80oRc600epN4ycQ4"
|
||||
customer-session-client-secret="` + clientSecretSession + `">
|
||||
</stripe-pricing-table>`
|
||||
|
||||
closeBtn := `
|
||||
@ -49,12 +68,102 @@ func generatePricingTableChatHTML() string {
|
||||
return htmlString
|
||||
}
|
||||
|
||||
func CreateNewStripeCustomer(name string, email string) string {
|
||||
params := &stripe.CustomerParams{
|
||||
Name: stripe.String(name),
|
||||
Email: stripe.String(email),
|
||||
}
|
||||
result, err := customer.New(params)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return result.ID
|
||||
}
|
||||
|
||||
func IsCurrentUserSubscribed() bool {
|
||||
// TODO Ask Stripe if user is subscribed
|
||||
return true
|
||||
var user User
|
||||
err := edgeClient.QuerySingle(edgeCtx, "SELECT global currentUser { stripe_id } LIMIT 1;", &user)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
result, err := customer.Get(user.StripeID, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if result.Subscriptions.TotalCount == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
return result.Subscriptions.Data[0].Plan.Product.ID == "prod_PnDjBBwvQN36cQ" && result.Subscriptions.Data[0].Plan.Active
|
||||
}
|
||||
|
||||
func IsCurrentUserLimiteReached() bool {
|
||||
// TODO Ask Stripe if user is subscribed
|
||||
return true
|
||||
// Count the number of Usage for the current user
|
||||
var count int64
|
||||
err := edgeClient.QuerySingle(edgeCtx, `
|
||||
WITH
|
||||
U := (
|
||||
SELECT Usage
|
||||
FILTER .user = global currentUser
|
||||
)
|
||||
SELECT count(U)
|
||||
`, &count)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return count >= 500
|
||||
}
|
||||
|
||||
func CreateClientSecretSession() string {
|
||||
var user User
|
||||
err := edgeClient.QuerySingle(edgeCtx, "SELECT global currentUser { stripe_id } LIMIT 1;", &user)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
url := "https://api.stripe.com/v1/customer_sessions"
|
||||
method := "POST"
|
||||
apiKey := stripe.Key
|
||||
|
||||
payload := []byte(fmt.Sprintf("customer=%s&components[pricing_table][enabled]=true", user.StripeID))
|
||||
|
||||
req, err := http.NewRequest(method, url, bytes.NewBuffer(payload))
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to create request: %v", err))
|
||||
}
|
||||
req.Header.Add("Authorization", "Bearer "+apiKey)
|
||||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to execute request: %v", err))
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
panic(fmt.Sprintf("failed to create customer session: status code %d, response: %s", resp.StatusCode, string(body)))
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to read response body: %v", err))
|
||||
}
|
||||
|
||||
type CustomerSessionResponse struct {
|
||||
ClientSecret string `json:"client_secret"`
|
||||
CustomerID string `json:"customer"`
|
||||
}
|
||||
|
||||
var customerSession CustomerSessionResponse
|
||||
if err := json.Unmarshal(body, &customerSession); err != nil {
|
||||
panic(fmt.Sprintf("failed to unmarshal response: %v", err))
|
||||
}
|
||||
|
||||
if user.StripeID != customerSession.CustomerID {
|
||||
panic(fmt.Sprintf("customer_id does not match: got %s, expected %s", customerSession.CustomerID, user.StripeID))
|
||||
}
|
||||
|
||||
return customerSession.ClientSecret
|
||||
}
|
||||
|
@ -18,6 +18,10 @@ type Identity struct {
|
||||
type User struct {
|
||||
ID edgedb.UUID `edgedb:"id"`
|
||||
Setting Setting `edgedb:"setting"`
|
||||
StripeID string `edgedb:"stripe_id"`
|
||||
Email string `edgedb:"email"`
|
||||
Name string `edgedb:"name"`
|
||||
Avatar string `edgedb:"avatar"`
|
||||
}
|
||||
|
||||
type Key struct {
|
||||
|
@ -10,6 +10,10 @@ module default {
|
||||
|
||||
type User {
|
||||
required setting: Setting;
|
||||
required stripe_id: str;
|
||||
required name: str;
|
||||
required email: str;
|
||||
required avatar: str;
|
||||
required identity: ext::auth::Identity {
|
||||
on source delete delete target;
|
||||
}
|
||||
@ -34,7 +38,7 @@ module default {
|
||||
type Conversation {
|
||||
required name: str;
|
||||
required user: User {
|
||||
on target delete allow;
|
||||
on target delete delete source;
|
||||
};
|
||||
required date: datetime {
|
||||
default := datetime_current();
|
||||
@ -66,7 +70,9 @@ module default {
|
||||
|
||||
type Usage {
|
||||
required model_id: str;
|
||||
user: User;
|
||||
user: User {
|
||||
on target delete allow
|
||||
};
|
||||
required input_cost: float32;
|
||||
required output_cost: float32;
|
||||
required input_token: int32;
|
||||
@ -84,10 +90,10 @@ module default {
|
||||
default := false;
|
||||
};
|
||||
required modelInfo: ModelInfo {
|
||||
on target delete allow;
|
||||
on target delete delete source;
|
||||
};
|
||||
required user: User {
|
||||
on target delete allow;
|
||||
on target delete delete source;
|
||||
};
|
||||
custom_endpoint: CustomEndpoint {
|
||||
on source delete delete target;
|
||||
|
9
dbschema/migrations/00036-m1dn7we.edgeql
Normal file
9
dbschema/migrations/00036-m1dn7we.edgeql
Normal file
@ -0,0 +1,9 @@
|
||||
CREATE MIGRATION m1dn7we4iusvjor3e2axkxlngw22cbxpmqairv6zyo2ufykzrpo6da
|
||||
ONTO m1e72ubyamp6762oufm57qqns7tkr4o25gc3l62iml7sltlytgx5lq
|
||||
{
|
||||
ALTER TYPE default::Usage {
|
||||
ALTER LINK user {
|
||||
ON TARGET DELETE ALLOW;
|
||||
};
|
||||
};
|
||||
};
|
9
dbschema/migrations/00037-m13buly.edgeql
Normal file
9
dbschema/migrations/00037-m13buly.edgeql
Normal file
@ -0,0 +1,9 @@
|
||||
CREATE MIGRATION m13bulyyzk4lgnxam33lxxez5etrcgyzn5ndnoyrylab2bmjw6jb7q
|
||||
ONTO m1dn7we4iusvjor3e2axkxlngw22cbxpmqairv6zyo2ufykzrpo6da
|
||||
{
|
||||
ALTER TYPE default::Conversation {
|
||||
ALTER LINK user {
|
||||
ON TARGET DELETE DELETE SOURCE;
|
||||
};
|
||||
};
|
||||
};
|
12
dbschema/migrations/00038-m1qbhq4.edgeql
Normal file
12
dbschema/migrations/00038-m1qbhq4.edgeql
Normal file
@ -0,0 +1,12 @@
|
||||
CREATE MIGRATION m1qbhq4cgpt5abjvffrrlwaldgec4bfmlai5izca3exry64rofflua
|
||||
ONTO m13bulyyzk4lgnxam33lxxez5etrcgyzn5ndnoyrylab2bmjw6jb7q
|
||||
{
|
||||
ALTER TYPE default::LLM {
|
||||
ALTER LINK modelInfo {
|
||||
ON TARGET DELETE DELETE SOURCE;
|
||||
};
|
||||
ALTER LINK user {
|
||||
ON TARGET DELETE DELETE SOURCE;
|
||||
};
|
||||
};
|
||||
};
|
9
dbschema/migrations/00039-m1oinxw.edgeql
Normal file
9
dbschema/migrations/00039-m1oinxw.edgeql
Normal file
@ -0,0 +1,9 @@
|
||||
CREATE MIGRATION m1oinxw74yh5kzyh63mbn2m3kdqpoapkeyo7jvhkp2gq5rjkkvdi3q
|
||||
ONTO m1qbhq4cgpt5abjvffrrlwaldgec4bfmlai5izca3exry64rofflua
|
||||
{
|
||||
ALTER TYPE default::User {
|
||||
CREATE REQUIRED PROPERTY stripe_id: std::str {
|
||||
SET REQUIRED USING (<std::str>{'Hello'});
|
||||
};
|
||||
};
|
||||
};
|
15
dbschema/migrations/00040-m1wlzna.edgeql
Normal file
15
dbschema/migrations/00040-m1wlzna.edgeql
Normal file
@ -0,0 +1,15 @@
|
||||
CREATE MIGRATION m1wlzna3nrrigx2urda3turnj6dcvcjgexeuxxqundupqet5jrkh7q
|
||||
ONTO m1oinxw74yh5kzyh63mbn2m3kdqpoapkeyo7jvhkp2gq5rjkkvdi3q
|
||||
{
|
||||
ALTER TYPE default::User {
|
||||
CREATE REQUIRED PROPERTY avatar: std::str {
|
||||
SET REQUIRED USING (<std::str>{''});
|
||||
};
|
||||
CREATE REQUIRED PROPERTY email: std::str {
|
||||
SET REQUIRED USING (<std::str>{''});
|
||||
};
|
||||
CREATE REQUIRED PROPERTY name: std::str {
|
||||
SET REQUIRED USING (<std::str>{''});
|
||||
};
|
||||
};
|
||||
};
|
50
go.mod
50
go.mod
@ -2,71 +2,41 @@ module github.com/MrBounty/JADE2.0
|
||||
|
||||
go 1.22.2
|
||||
|
||||
require (
|
||||
github.com/edgedb/edgedb-go v0.17.1
|
||||
github.com/flosch/pongo2 v0.0.0-20200913210552-0d938eb266f3
|
||||
github.com/gofiber/fiber/v2 v2.52.4
|
||||
github.com/gofiber/template/django/v3 v3.1.11
|
||||
github.com/stripe/stripe-go v70.15.0+incompatible
|
||||
github.com/yuin/goldmark v1.7.1
|
||||
github.com/yuin/goldmark-highlighting v0.0.0-20220208100518-594be1970594
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/alecthomas/chroma v0.10.0 // indirect
|
||||
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||
github.com/bytedance/sonic v1.11.5 // indirect
|
||||
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||
github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
|
||||
github.com/cloudwego/base64x v0.1.3 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/dlclark/regexp2 v1.4.0 // indirect
|
||||
github.com/edgedb/edgedb-go v0.17.1 // indirect
|
||||
github.com/flosch/pongo2 v0.0.0-20200913210552-0d938eb266f3 // indirect
|
||||
github.com/flosch/pongo2/v6 v6.0.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/gin-gonic/gin v1.9.1 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.19.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/gofiber/fiber/v2 v2.52.4 // indirect
|
||||
github.com/gofiber/template v1.8.3 // indirect
|
||||
github.com/gofiber/template/django/v3 v3.1.11 // indirect
|
||||
github.com/gofiber/template/html/v2 v2.1.1 // indirect
|
||||
github.com/gofiber/utils v1.1.0 // indirect
|
||||
github.com/golang/snappy v0.0.1 // indirect
|
||||
github.com/gomarkdown/markdown v0.0.0-20240419095408-642f0ee99ae2 // indirect
|
||||
github.com/google/uuid v1.5.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.17.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.1 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 // indirect
|
||||
github.com/stripe/stripe-go/v78 v78.7.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasthttp v1.51.0 // indirect
|
||||
github.com/valyala/tcplisten v1.0.0 // indirect
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||
github.com/xdg-go/scram v1.1.2 // indirect
|
||||
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||
github.com/xdg/scram v1.0.5 // indirect
|
||||
github.com/xdg/stringprep v1.0.3 // indirect
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
|
||||
github.com/yuin/goldmark v1.7.1 // indirect
|
||||
github.com/yuin/goldmark-highlighting v0.0.0-20220208100518-594be1970594 // indirect
|
||||
go.mongodb.org/mongo-driver v1.15.0 // indirect
|
||||
golang.org/x/arch v0.7.0 // indirect
|
||||
golang.org/x/crypto v0.22.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea // indirect
|
||||
golang.org/x/mod v0.10.0 // indirect
|
||||
golang.org/x/net v0.24.0 // indirect
|
||||
golang.org/x/sync v0.2.0 // indirect
|
||||
golang.org/x/sys v0.19.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/tools v0.9.3 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
129
go.sum
129
go.sum
@ -2,25 +2,10 @@ github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbf
|
||||
github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s=
|
||||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||
github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
|
||||
github.com/bytedance/sonic v1.11.5 h1:G00FYjjqll5iQ1PYXynbg/hyzqBqavH8Mo9/oTopd9k=
|
||||
github.com/bytedance/sonic v1.11.5/go.mod h1:X2PC2giUdj/Cv2lliWFLk6c/DUQok5rViJSemeB0wDw=
|
||||
github.com/bytedance/sonic/loader v0.1.0/go.mod h1:UmRT+IRTGKz/DAkzcEGzyVqQFJ7H9BqwBO3pm9H/+HY=
|
||||
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d h1:S2NE3iHSwP0XV47EEXL8mWmRdEfGscSJ+7EgePNgt0s=
|
||||
github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA=
|
||||
github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
|
||||
github.com/cloudwego/base64x v0.1.3 h1:b5J/l8xolB7dyDTTmhJP2oTs5LdrjyrUFuNxdfq5hAg=
|
||||
github.com/cloudwego/base64x v0.1.3/go.mod h1:1+1K5BUHIQzyapgpF7LwvOGAEDicKtt1umPV+aN8pi8=
|
||||
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
|
||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
@ -30,51 +15,24 @@ github.com/flosch/pongo2 v0.0.0-20200913210552-0d938eb266f3 h1:fmFk0Wt3bBxxwZnu4
|
||||
github.com/flosch/pongo2 v0.0.0-20200913210552-0d938eb266f3/go.mod h1:bJWSKrZyQvfTnb2OudyUjurSG4/edverV7n82+K3JiM=
|
||||
github.com/flosch/pongo2/v6 v6.0.0 h1:lsGru8IAzHgIAw6H2m4PCyleO58I40ow6apih0WprMU=
|
||||
github.com/flosch/pongo2/v6 v6.0.0/go.mod h1:CuDpFm47R0uGGE7z13/tTlt1Y6zdxvr2RLT5LJhsHEU=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4=
|
||||
github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/gofiber/fiber/v2 v2.52.4 h1:P+T+4iK7VaqUsq2PALYEfBBo6bJZ4q3FP8cZ84EggTM=
|
||||
github.com/gofiber/fiber/v2 v2.52.4/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ=
|
||||
github.com/gofiber/template v1.8.3 h1:hzHdvMwMo/T2kouz2pPCA0zGiLCeMnoGsQZBTSYgZxc=
|
||||
github.com/gofiber/template v1.8.3/go.mod h1:bs/2n0pSNPOkRa5VJ8zTIvedcI/lEYxzV3+YPXdBvq8=
|
||||
github.com/gofiber/template/django/v3 v3.1.11 h1:wE5k/wWNKGKxfeopaeB6IBijMiEVAxKHJVf1WMH5iNw=
|
||||
github.com/gofiber/template/django/v3 v3.1.11/go.mod h1:sEUp0cr1iCuFx4GEtHEA7yRXgJmRdAVXwGMR3Q5JnyI=
|
||||
github.com/gofiber/template/html/v2 v2.1.1 h1:QEy3O3EBkvwDthy5bXVGUseOyO6ldJoiDxlF4+MJiV8=
|
||||
github.com/gofiber/template/html/v2 v2.1.1/go.mod h1:2G0GHHOUx70C1LDncoBpe4T6maQbNa4x1CVNFW0wju0=
|
||||
github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM=
|
||||
github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/gomarkdown/markdown v0.0.0-20240419095408-642f0ee99ae2 h1:yEt5djSYb4iNtmV9iJGVday+i4e9u6Mrn5iP64HH5QM=
|
||||
github.com/gomarkdown/markdown v0.0.0-20240419095408-642f0ee99ae2/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
||||
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
|
||||
github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
@ -82,121 +40,56 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/pelletier/go-toml/v2 v2.2.1 h1:9TA9+T8+8CUCO2+WYnDLCgrYi9+omqKXyjDtosvtEhg=
|
||||
github.com/pelletier/go-toml/v2 v2.2.1/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 h1:aQKxg3+2p+IFXXg97McgDGT5zcMrQoi0EICZs8Pgchs=
|
||||
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3/go.mod h1:9/etS5gpQq9BJsJMWg1wpLbfuSnkm8dPF6FdW2JXVhA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stripe/stripe-go/v78 v78.7.0 h1:TdTkzBn0wB0ntgOI74YHpvsNyHPBijX83n4ljsjXh6o=
|
||||
github.com/stripe/stripe-go/v78 v78.7.0/go.mod h1:GjncxVLUc1xoIOidFqVwq+y3pYiG7JLVWiVQxTsLrvQ=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/stripe/stripe-go v70.15.0+incompatible h1:hNML7M1zx8RgtepEMlxyu/FpVPrP7KZm1gPFQquJQvM=
|
||||
github.com/stripe/stripe-go v70.15.0+incompatible/go.mod h1:A1dQZmO/QypXmsL0T8axYZkSN/uA/T/A64pfKdBAMiY=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA=
|
||||
github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g=
|
||||
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
|
||||
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
|
||||
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
|
||||
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
||||
github.com/xdg/scram v1.0.5 h1:TuS0RFmt5Is5qm9Tm2SoD89OPqe4IRiFtyFY4iwWXsw=
|
||||
github.com/xdg/scram v1.0.5/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
|
||||
github.com/xdg/stringprep v1.0.3 h1:cmL5Enob4W83ti/ZHuZLuKD/xqJfus4fVPwE+/BDm+4=
|
||||
github.com/xdg/stringprep v1.0.3/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||
github.com/yuin/goldmark v1.4.5/go.mod h1:rmuwmfZ0+bvzB24eSC//bk1R1Zp3hM0OXYv/G2LIilg=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.7.1 h1:3bajkSilaCbjdKVsKdZjZCLBNPL9pYzrCakKaf4U49U=
|
||||
github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||
github.com/yuin/goldmark-highlighting v0.0.0-20220208100518-594be1970594 h1:yHfZyN55+5dp1wG7wDKv8HQ044moxkyGq12KFFMFDxg=
|
||||
github.com/yuin/goldmark-highlighting v0.0.0-20220208100518-594be1970594/go.mod h1:U9ihbh+1ZN7fR5Se3daSPoz1CGF9IYtSvWwVQtnzGHU=
|
||||
go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc=
|
||||
go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc=
|
||||
golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea h1:vLCWI/yYrdEHyN2JzIzPO3aaQJHQdp89IZBA/+azVC4=
|
||||
golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
|
||||
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
|
||||
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=
|
||||
golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
|
68
login.go
68
login.go
@ -7,7 +7,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"github.com/edgedb/edgedb-go"
|
||||
@ -21,9 +20,19 @@ type DiscoveryDocument struct {
|
||||
type UserProfile struct {
|
||||
Email string `json:"email"`
|
||||
Name string `json:"name"`
|
||||
AvatarGitHub string `json:"avatar_url"`
|
||||
AvatarGoogle string `json:"picture"`
|
||||
}
|
||||
|
||||
func getGoogleUserProfile(providerToken string) (string, string) {
|
||||
type TokenResponse struct {
|
||||
AuthToken string `json:"auth_token"`
|
||||
IdentityID string `json:"identity_id"`
|
||||
ProviderToken string `json:"provider_token"`
|
||||
}
|
||||
|
||||
const EDGEDB_AUTH_BASE_URL = "http://127.0.0.1:10700/db/main/ext/auth"
|
||||
|
||||
func getGoogleUserProfile(providerToken string) (string, string, string) {
|
||||
// Fetch the discovery document
|
||||
resp, err := http.Get("https://accounts.google.com/.well-known/openid-configuration")
|
||||
if err != nil {
|
||||
@ -35,7 +44,7 @@ func getGoogleUserProfile(providerToken string) (string, string) {
|
||||
panic(fmt.Sprintf("failed to fetch discovery document: status code %d", resp.StatusCode))
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to read discovery document response: %v", err))
|
||||
}
|
||||
@ -64,7 +73,7 @@ func getGoogleUserProfile(providerToken string) (string, string) {
|
||||
panic(fmt.Sprintf("failed to fetch user profile: status code %d", resp.StatusCode))
|
||||
}
|
||||
|
||||
body, err = ioutil.ReadAll(resp.Body)
|
||||
body, err = io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to read user profile response: %v", err))
|
||||
}
|
||||
@ -74,10 +83,10 @@ func getGoogleUserProfile(providerToken string) (string, string) {
|
||||
panic(fmt.Sprintf("failed to unmarshal user profile: %v", err))
|
||||
}
|
||||
|
||||
return userProfile.Email, userProfile.Name
|
||||
return userProfile.Email, userProfile.Name, userProfile.AvatarGoogle
|
||||
}
|
||||
|
||||
func getGitHubUserProfile(providerToken string) (string, string) {
|
||||
func getGitHubUserProfile(providerToken string) (string, string, string) {
|
||||
// Create the request to fetch the user profile
|
||||
req, err := http.NewRequest("GET", "https://api.github.com/user", nil)
|
||||
if err != nil {
|
||||
@ -98,21 +107,19 @@ func getGitHubUserProfile(providerToken string) (string, string) {
|
||||
panic(fmt.Sprintf("failed to fetch user profile: status code %d", resp.StatusCode))
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to read user profile response: %v", err))
|
||||
}
|
||||
|
||||
var userProfile GitHubUserProfile
|
||||
var userProfile UserProfile
|
||||
if err := json.Unmarshal(body, &userProfile); err != nil {
|
||||
panic(fmt.Sprintf("failed to unmarshal user profile: %v", err))
|
||||
}
|
||||
|
||||
return userProfile.Email, userProfile.Name
|
||||
return userProfile.Email, userProfile.Name, userProfile.AvatarGitHub
|
||||
}
|
||||
|
||||
const EDGEDB_AUTH_BASE_URL = "http://127.0.0.1:10700/db/main/ext/auth"
|
||||
|
||||
func generatePKCE() (string, string) {
|
||||
verifier_source := make([]byte, 32)
|
||||
_, err := rand.Read(verifier_source)
|
||||
@ -164,11 +171,7 @@ func handleCallbackSignup(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusBadRequest).SendString(fmt.Sprintf("Error from the auth server: %s", string(body)))
|
||||
}
|
||||
|
||||
var tokenResponse struct {
|
||||
AuthToken string `json:"auth_token"`
|
||||
IdentityID string `json:"identity_id"`
|
||||
ProviderToken string `json:"provider_token"`
|
||||
}
|
||||
var tokenResponse TokenResponse
|
||||
err = json.NewDecoder(resp.Body).Decode(&tokenResponse)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).SendString(fmt.Sprintf("Error decoding auth server response: %s", err.Error()))
|
||||
@ -201,41 +204,32 @@ func handleCallbackSignup(c *fiber.Ctx) error {
|
||||
var (
|
||||
providerEmail string
|
||||
providerName string
|
||||
providerAvatar string
|
||||
)
|
||||
|
||||
// Get the email and name from the provider
|
||||
if identity.Issuer == "https://accounts.google.com" {
|
||||
providerEmail, providerName = getGoogleUserProfile(tokenResponse.ProviderToken)
|
||||
providerEmail, providerName, providerAvatar = getGoogleUserProfile(tokenResponse.ProviderToken)
|
||||
} else if identity.Issuer == "https://github.com" {
|
||||
providerEmail, providerName = getGithubUserProfile(tokenResponse.ProviderToken)
|
||||
providerEmail, providerName, providerAvatar = getGitHubUserProfile(tokenResponse.ProviderToken) // Work !!!!
|
||||
}
|
||||
|
||||
fmt.Println(providerEmail, providerName)
|
||||
|
||||
// Create stripe user
|
||||
//stripe.Key = "sk_test_51OxXuWP2nW0okNQyiNAOcBTTWZSiyP1el5KOmV3yIv1DQR0415YPsH1eb89SLrsOFj80o9p2AxGOy042e53yDvZN00jHxHAbE6"
|
||||
//
|
||||
//params := &stripe.CustomerParams{
|
||||
// Name: stripe.String(
|
||||
// Email: stripe.String(),
|
||||
//}
|
||||
//result, err := customer.New(params)
|
||||
|
||||
// Create a new User and attach the identity
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).SendString(fmt.Sprintf("Error in edgedb.ParseUUID: in handleCallbackSignup: %s", err.Error()))
|
||||
}
|
||||
stripCustID := CreateNewStripeCustomer(providerName, providerEmail)
|
||||
|
||||
err = edgeClient.Execute(edgeCtx, `
|
||||
INSERT User {
|
||||
stripe_id := <str>$0,
|
||||
email := <str>$1,
|
||||
name := <str>$2,
|
||||
avatar := <str>$3,
|
||||
setting := (
|
||||
INSERT Setting {
|
||||
default_model := "gpt-3.5-turbo"
|
||||
}
|
||||
),
|
||||
identity := (SELECT ext::auth::Identity FILTER .id = <uuid>$0)
|
||||
identity := (SELECT ext::auth::Identity FILTER .id = <uuid>$4)
|
||||
}
|
||||
`, identityUUID)
|
||||
`, stripCustID, providerEmail, providerName, providerAvatar, identityUUID)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).SendString(fmt.Sprintf("Error in edgedb.QuerySingle: in handleCallbackSignup: %s", err.Error()))
|
||||
}
|
||||
@ -269,9 +263,7 @@ func handleCallback(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusBadRequest).SendString(fmt.Sprintf("Error from the auth server: %s", string(body)))
|
||||
}
|
||||
|
||||
var tokenResponse struct {
|
||||
AuthToken string `json:"auth_token"`
|
||||
}
|
||||
var tokenResponse TokenResponse
|
||||
err = json.NewDecoder(resp.Body).Decode(&tokenResponse)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).SendString(fmt.Sprintf("Error decoding auth server response: %s", err.Error()))
|
||||
|
4
main.go
4
main.go
@ -11,6 +11,7 @@ import (
|
||||
"github.com/gofiber/fiber/v2/middleware/logger"
|
||||
"github.com/gofiber/fiber/v2/middleware/recover"
|
||||
"github.com/gofiber/template/django/v3"
|
||||
"github.com/stripe/stripe-go"
|
||||
)
|
||||
|
||||
var userTmpl *pongo2.Template
|
||||
@ -40,6 +41,9 @@ func sendEvent(event, data string) {
|
||||
}
|
||||
|
||||
func main() {
|
||||
// TODO Change key to env and the live one
|
||||
stripe.Key = "sk_test_51OxXuWP2nW0okNQyiNAOcBTTWZSiyP1el5KOmV3yIv1DQR0415YPsH1eb89SLrsOFj80o9p2AxGOy042e53yDvZN00jHxHAbE6"
|
||||
|
||||
botTmpl = pongo2.Must(pongo2.FromFile("views/partials/message-bot.html"))
|
||||
userTmpl = pongo2.Must(pongo2.FromFile("views/partials/message-user.html"))
|
||||
selectBtnTmpl = pongo2.Must(pongo2.FromFile("views/partials/model-selection-btn.html"))
|
||||
|
@ -93,7 +93,7 @@
|
||||
<p id="api-keys-status"></p>
|
||||
</div>
|
||||
{% if IsSub %}
|
||||
<a class="button is-small mt-1" href="/subscribe">
|
||||
<a class="button is-small mt-1" href="{{ StripeSubLink }}" target="_blank">
|
||||
<span class="icon is-small" style="color: #b00202">
|
||||
<i class="fa-solid fa-heart"></i>
|
||||
</span>
|
||||
|
Loading…
x
Reference in New Issue
Block a user