dkforest

A forum and chat platform (onion)
git clone https://git.dasho.dev/n0tr1v/dkforest.git
Log | Files | Refs | LICENSE

commit f866aa18855118a1c6faf2f7c093ba4c24d3bccf
parent c5cb3cceb41e371228b30bc37dacf625ed80013f
Author: n0tr1v <n0tr1v@protonmail.com>
Date:   Wed, 27 Dec 2023 01:29:06 -0500

rake back

Diffstat:
Acmd/dkf/migrations/157.sql | 8++++++++
Mgo.mod | 3++-
Mgo.sum | 5+++++
Mpkg/database/tableUsers.go | 24++++++++++++++++++++++++
Mpkg/web/handlers/admin.go | 2++
Mpkg/web/handlers/data.go | 9+++++++++
Mpkg/web/handlers/poker.go | 71++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mpkg/web/handlers/poker/poker.go | 74+++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
Mpkg/web/handlers/signup.go | 10++++++++++
Mpkg/web/handlers/utils/utils.go | 9+++++++++
Mpkg/web/middlewares/middlewares.go | 6++++++
Apkg/web/public/views/pages/poker-rake-back.gohtml | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mpkg/web/public/views/pages/poker.gohtml | 14++++++++++++--
Mpkg/web/web.go | 2++
14 files changed, 272 insertions(+), 27 deletions(-)

diff --git a/cmd/dkf/migrations/157.sql b/cmd/dkf/migrations/157.sql @@ -0,0 +1,8 @@ +-- +migrate Up +ALTER TABLE users ADD COLUMN poker_referred_by INTEGER NULL; +ALTER TABLE users ADD COLUMN poker_referral_token VARCHAR(50) NULL; +ALTER TABLE users ADD COLUMN poker_rake_back INTEGER NOT NULL DEFAULT 0; + +CREATE UNIQUE INDEX users_poker_referral_token_uniq ON users (poker_referral_token); + +-- +migrate Down diff --git a/go.mod b/go.mod @@ -9,6 +9,7 @@ require ( github.com/alecthomas/chroma v0.9.2 github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc + github.com/chehsunliu/poker v0.1.0 github.com/dustin/go-humanize v1.0.0 github.com/fogleman/gg v1.3.0 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 @@ -30,6 +31,7 @@ require ( github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 github.com/stretchr/testify v1.7.0 github.com/t-tiger/gorm-bulk-insert v1.3.0 + github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 github.com/ulule/limiter v2.2.2+incompatible github.com/urfave/cli/v2 v2.3.0 github.com/valyala/quicktemplate v1.7.0 @@ -45,7 +47,6 @@ require ( github.com/alecthomas/repr v0.0.0-20200325044227-4184120f674c // indirect github.com/andybalholm/cascadia v1.1.0 // indirect github.com/aymerick/douceur v0.2.0 // indirect - github.com/chehsunliu/poker v0.1.0 // indirect github.com/cloudflare/circl v1.1.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 // indirect diff --git a/go.sum b/go.sum @@ -239,6 +239,7 @@ github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/loganjspears/joker v0.0.0-20180219043703-3f2f69a75914 h1:yAIlIiOkdoJvqd5xtWzM9tNDpLZrFfJdpnNSKha78G8= github.com/loganjspears/joker v0.0.0-20180219043703-3f2f69a75914/go.mod h1:76SAnflG7ZFhgtnaVCpP6A5Z1S/VMFzRBN7KGm5j4oc= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magefile/mage v1.10.0 h1:3HiXzCUY12kh9bIuyXShaVe529fJfyqoVM42o/uom2g= @@ -292,6 +293,7 @@ github.com/nicksnyder/go-i18n/v2 v2.0.0-20190611170653-0c6ce6ac1e8c h1:MtOLrfLzA github.com/nicksnyder/go-i18n/v2 v2.0.0-20190611170653-0c6ce6ac1e8c/go.mod h1:JXS4+OKhbcwDoVTEj0sLFWL1vOwec2g/YBAxZ9owJqY= github.com/notnil/chess v1.8.0 h1:wU50vrPpH3kiT0WRC/6EN9kJpb7EBxFLCRf05TwXys8= github.com/notnil/chess v1.8.0/go.mod h1:cRuJUIBFq9Xki05TWHJxHYkC+fFpq45IWwk94DdlCrA= +github.com/notnil/joker v0.0.0-20180219043703-3f2f69a75914 h1:xXPuFr3PVM4p6Vw3j0CP29oWYRVKO3cPZjR6D7BxggQ= github.com/notnil/joker v0.0.0-20180219043703-3f2f69a75914/go.mod h1:L0Sdr2nYdktjerdXpIn9wOCn+GebPs/nCL2qH6RTGa0= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= @@ -395,6 +397,8 @@ github.com/t-tiger/gorm-bulk-insert v1.3.0 h1:9k7BaVEhw/3fsvh6GTOBwJ2RXk3asc5xs5 github.com/t-tiger/gorm-bulk-insert v1.3.0/go.mod h1:ruDlk8xDl+8sX4bA7PQuYly9YEb3pbp1eP2LCyeRrFY= github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM= github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog= +github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 h1:xzABM9let0HLLqFypcxvLmlvEciCHL7+Lv+4vwZqecI= +github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569/go.mod h1:2Ly+NIftZN4de9zRmENdYbvPQeaVIYKWpLFStLFEBgI= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ulule/limiter v2.2.2+incompatible h1:1lk9jesmps1ziYHHb4doL7l5hFkYYYA3T8dkNyw7ffY= @@ -518,6 +522,7 @@ golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= diff --git a/pkg/database/tableUsers.go b/pkg/database/tableUsers.go @@ -130,6 +130,9 @@ type User struct { ChessSoundsEnabled bool PokerSoundsEnabled bool PokerXmrSubAddress string + PokerReferredBy *UserID + PokerReferralToken *string + PokerRakeBack PokerChip HighlightOwnMessages bool `gorm:"-"` } @@ -340,6 +343,11 @@ func (d *DkfDB) GetUserByID(userID UserID) (out User, err error) { return } +func (d *DkfDB) GetUserByPokerReferralToken(token string) (out User, err error) { + err = d.db.First(&out, "poker_referral_token = ?", token).Error + return +} + func (d *DkfDB) GetUserByPokerXmrSubAddress(pokerXmrSubAddress string) (out User, err error) { err = d.db.First(&out, "poker_xmr_sub_address = ?", pokerXmrSubAddress).Error return @@ -730,3 +738,19 @@ func (d *DkfDB) SetPokerSubAddress(userID UserID, subAddress string) (err error) func (u *User) GetUserChips(isTest bool) PokerChip { return utils.Ternary(isTest, u.ChipsTest, u.XmrBalance.ToPokerChip()) } + +func (d *DkfDB) GetUsersRakeBack() (out PokerChip, err error) { + var tmp struct{ PokerRakeBack PokerChip } + err = d.db.Raw(`SELECT SUM(poker_rake_back) as poker_rake_back FROM users`).Scan(&tmp).Error + return tmp.PokerRakeBack, err +} + +func (d *DkfDB) ClaimRakeBack(userID UserID) (err error) { + err = d.db.Exec(`UPDATE users SET xmr_balance = xmr_balance + (poker_rake_back * 10000000), poker_rake_back = 0 WHERE id = ?`, int64(userID)).Error + return +} + +func (d *DkfDB) IncrUserRakeBack(referredBy UserID, rakeBack PokerChip) (err error) { + err = d.db.Exec(`UPDATE users SET poker_rake_back = poker_rake_back + ? WHERE id = ?`, uint64(rakeBack), int64(referredBy)).Error + return +} diff --git a/pkg/web/handlers/admin.go b/pkg/web/handlers/admin.go @@ -494,9 +494,11 @@ func AdminPokerTransactionsHandler(c echo.Context) error { data.SumOut, _ = db.GetPokerXmrTransactionsSumOut() data.DiffInOut = data.SumIn - data.SumOut sumXmrBalance, _ := db.GetUsersXmrBalance() + sumRakeBack, _ := db.GetUsersRakeBack() sumTableAccounts, sumTableBets, _ := db.GetPokerTableAccountSums() data.Discrepancy = (int64(data.SumIn) - int64(data.SumOut)) - int64(sumXmrBalance) - + int64(sumRakeBack.ToPiconero()) - int64(data.PokerCasino.Rake.ToPiconero()) - int64(sumTableAccounts.ToPiconero()) - int64(sumTableBets.ToPiconero()) diff --git a/pkg/web/handlers/data.go b/pkg/web/handlers/data.go @@ -956,6 +956,13 @@ type TmpTable struct { NbSeated int } +type pokerRakeBackData struct { + ReferralToken string + ReferralURL string + RakeBackPct float64 + SetReferralError string +} + type pokerTableData struct { PokerTableSlug string } @@ -965,6 +972,7 @@ type pokerData struct { XmrBalance database.Piconero PokerXmrSubAddress string Img string + RakeBack database.PokerChip ChipsTest database.PokerChip Tables []TmpTable Transactions []database.PokerXmrTransaction @@ -980,6 +988,7 @@ type pokerData struct { HelperpXmr string HelperChips database.PokerChip HelperUsd string + RakeBackPct float64 } type powHelperData struct { diff --git a/pkg/web/handlers/poker.go b/pkg/web/handlers/poker.go @@ -18,6 +18,7 @@ import ( "github.com/labstack/echo" wallet1 "github.com/monero-ecosystem/go-monero-rpc-client/wallet" "github.com/sirupsen/logrus" + "github.com/teris-io/shortid" "image" "image/png" "math/rand" @@ -44,9 +45,11 @@ func PokerHomeHandler(c echo.Context) error { } const minWithdrawAmount = 1 var data pokerData + data.RakeBackPct = poker.RakeBackPct * 100 data.XmrPrice = fmt.Sprintf("$%.2f", config.MoneroPrice.Load()) data.Transactions, _ = db.GetUserPokerXmrTransactions(authUser.ID) data.PokerXmrSubAddress = authUser.PokerXmrSubAddress + data.RakeBack = authUser.PokerRakeBack data.ChipsTest = authUser.ChipsTest data.XmrBalance = authUser.XmrBalance withdrawUnique := rand.Int63() @@ -131,6 +134,12 @@ func PokerHomeHandler(c echo.Context) error { authUser.ChipsTest = 1000 authUser.DoSave(db) return c.Redirect(http.StatusFound, c.Request().Referer()) + + } else if formName == "claim_rake_back" { + if err := db.ClaimRakeBack(authUser.ID); err != nil { + logrus.Error(err) + } + return c.Redirect(http.StatusFound, c.Request().Referer()) } if config.PokerWithdrawEnabled.IsFalse() { @@ -318,6 +327,66 @@ func doCashOut(db *database.DkfDB, pokerTableSlug string, userID database.UserID return err } +func PokerRakeBackHandler(c echo.Context) error { + authUser := c.Get("authUser").(*database.User) + db := c.Get("database").(*database.DkfDB) + + var data pokerRakeBackData + data.RakeBackPct = poker.RakeBackPct * 100 + pokerReferralToken := authUser.PokerReferralToken + if pokerReferralToken != nil { + data.ReferralToken = *pokerReferralToken + data.ReferralURL = fmt.Sprintf("%s/poker?r=%s", config.DkfOnion, *pokerReferralToken) + } + + if c.Request().Method == http.MethodGet { + return c.Render(http.StatusOK, "poker-rake-back", data) + } + + formName := c.Request().PostFormValue("form_name") + if formName == "generate_referral_url" { + if pokerReferralToken != nil { + return c.Redirect(http.StatusFound, c.Request().Referer()) + } + token, err := shortid.Generate() + if err != nil { + logrus.Error(err) + return c.Redirect(http.StatusFound, c.Request().Referer()) + } + authUser.PokerReferralToken = &token + authUser.DoSave(db) + return c.Redirect(http.StatusFound, c.Request().Referer()) + + } else if formName == "set_referrer" { + referralToken := c.Request().PostFormValue("referral_token") + if len(referralToken) != 9 { + data.SetReferralError = "Invalid referral token" + return c.Render(http.StatusOK, "poker-rake-back", data) + } + if authUser.PokerReferredBy != nil { + data.SetReferralError = "You are already giving your rake back" + return c.Render(http.StatusOK, "poker-rake-back", data) + } + if pokerReferralToken != nil && referralToken == *pokerReferralToken { + data.SetReferralError = "Yon can't give yourself the rake back" + return c.Render(http.StatusOK, "poker-rake-back", data) + } + referrer, err := db.GetUserByPokerReferralToken(referralToken) + if err != nil { + data.SetReferralError = "no user found with this referral token" + return c.Render(http.StatusOK, "poker-rake-back", data) + } + if referrer.ID == authUser.ID { + data.SetReferralError = "Yon can't give yourself the rake back" + return c.Render(http.StatusOK, "poker-rake-back", data) + } + authUser.PokerReferredBy = &referrer.ID + authUser.DoSave(db) + return c.Redirect(http.StatusFound, c.Request().Referer()) + } + return c.Redirect(http.StatusFound, c.Request().Referer()) +} + func PokerTableHandler(c echo.Context) error { roomID := c.Param("roomID") var data pokerTableData @@ -602,7 +671,7 @@ func PokerSitHandler(c echo.Context) error { return c.HTML(http.StatusOK, html) } if c.Request().Method == http.MethodPost { - g.Sit(authUser.ID, authUser.Username, pos) + g.Sit(authUser.ID, authUser.Username, authUser.PokerReferredBy, pos) } return c.HTML(http.StatusOK, html) } diff --git a/pkg/web/handlers/poker/poker.go b/pkg/web/handlers/poker/poker.go @@ -35,6 +35,7 @@ const DealerStackX = 250 const DealerStackY = 30 const NbCardsPerPlayer = 2 const animationTime = 1000 * time.Millisecond +const RakeBackPct = 0.15 type Poker struct { sync.Mutex @@ -196,13 +197,14 @@ func (g *Game) getEligibles() (out seatedPlayers) { } type seatedPlayer struct { - seatIdx int - userID database.UserID - username database.Username - cash rwmtx.RWMtxUInt64[database.PokerChip] - status rwmtx.RWMtx[string] - hasChecked bool - lastActionTS time.Time + seatIdx int + userID database.UserID + username database.Username + cash rwmtx.RWMtxUInt64[database.PokerChip] + status rwmtx.RWMtx[string] + hasChecked bool + lastActionTS time.Time + pokerReferredBy *database.UserID } func (p *seatedPlayer) getCash() (out database.PokerChip) { @@ -226,6 +228,7 @@ type PokerPlayer struct { unsit atomic.Bool gameBet database.PokerChip allInMaxGain database.PokerChip + rakePaid database.PokerChip countChancesToAction int } @@ -566,7 +569,7 @@ func (g *Game) incrDealerIdx() (smallBlindIdx, bigBlindIdx int) { return } -func (g *Game) Sit(userID database.UserID, username database.Username, pos int) { +func (g *Game) Sit(userID database.UserID, username database.Username, pokerReferredBy *database.UserID, pos int) { if err := g.Players.WithE(func(gPlayers *seatedPlayers) error { pokerTable, err := g.db.GetPokerTableBySlug(g.roomID.String()) if err != nil { @@ -589,11 +592,12 @@ func (g *Game) Sit(userID database.UserID, username database.Username, pos int) return errors.New("seat already taken") } (*gPlayers)[pos] = &seatedPlayer{ - seatIdx: pos, - userID: userID, - username: username, - cash: rwmtx.RWMtxUInt64[database.PokerChip]{rwmtx.New(tableAccount.Amount)}, - lastActionTS: time.Now(), + seatIdx: pos, + userID: userID, + username: username, + cash: rwmtx.RWMtxUInt64[database.PokerChip]{rwmtx.New(tableAccount.Amount)}, + lastActionTS: time.Now(), + pokerReferredBy: pokerReferredBy, } PubSub.Pub(g.roomID.Topic(), PokerSeatTakenEvent{}) @@ -1345,9 +1349,10 @@ func dealerThread(g *Game, eligiblePlayers seatedPlayers) { END: winners := ongoing.computeWinners() - mainPot := ongoing.mainPot.Get() - playersGain, rake := processPot(winners, mainPot, bigBlindBet, collectRake, len(ongoing.players)) - winnersStr, winnerHand := applyGains(g, playersGain, mainPot, rake) + mainPotOrig := ongoing.mainPot.Get() + mainPot, rake := computeRake(g.ongoing.players, bigBlindBet, mainPotOrig, collectRake) + playersGain := processPot(winners, mainPot) + winnersStr, winnerHand := applyGains(g, playersGain, mainPotOrig, rake) ongoing.mainPot.Set(0) @@ -1378,6 +1383,20 @@ func (g *ongoingGame) gameStr() string { return out } +func computeRake(players []*PokerPlayer, pokerTableMinBet, mainPotIn database.PokerChip, collectRake bool) (mainPotOut, rake database.PokerChip) { + if !collectRake { + return mainPotIn, 0 + } + rake = calculateRake(mainPotIn, pokerTableMinBet, len(players)) + for _, p := range players { + pctOfPot := float64(p.gameBet) / float64(mainPotIn) + pctOfRake := pctOfPot * float64(rake) + p.rakePaid = database.PokerChip(pctOfRake) + } + mainPotOut = mainPotIn - rake + return mainPotOut, rake +} + func applySmallBlindBet(g *Game, bigBlindBet database.PokerChip, sbIdx int) { applyBlindBet(g, sbIdx, bigBlindBet/2, "small blind") } @@ -1438,10 +1457,24 @@ func applyGains(g *Game, playersGain []PlayerGain, mainPot, rake database.PokerC winnerHand = utils.Ternary(nbPlayersGain == 1, playersGain[0].HandStr, "Split pot") if g.tableType == TableTypeRake { + rakeOrig := rake if !g.pokerTableIsTest { + rakeBackMap := make(map[database.UserID]database.PokerChip) + for _, p := range g.ongoing.players { + if p.pokerReferredBy != nil { + rakeBack := database.PokerChip(RakeBackPct * float64(p.rakePaid)) + rakeBackMap[*p.pokerReferredBy] += rakeBack + rake -= rakeBack + } + } + for userID, totalRakeBack := range rakeBackMap { + if err := tx.IncrUserRakeBack(userID, totalRakeBack); err != nil { + rake += totalRakeBack + } + } _ = tx.IncrPokerCasinoRake(rake) } - g.newLogEvent(fmt.Sprintf("Rake %d (%.2f%%)", rake, (float64(rake)/float64(mainPot))*100)) + g.newLogEvent(fmt.Sprintf("Rake %d (%.2f%%)", rakeOrig, (float64(rakeOrig)/float64(mainPot))*100)) } for _, el := range playersGain { @@ -1497,17 +1530,12 @@ func calculateRake(mainPot, pokerTableMinBet database.PokerChip, nbPlayers int) return rake } -func processPot(winners []gameResult, mainPot, pokerTableMinBet database.PokerChip, collectRake bool, nbPlayers int) (res []PlayerGain, rake database.PokerChip) { +func processPot(winners []gameResult, mainPot database.PokerChip) (res []PlayerGain) { if len(winners) == 0 { logrus.Error("winners has len 0") return } - if collectRake { - rake = calculateRake(mainPot, pokerTableMinBet, nbPlayers) - mainPot -= rake - } - isOnlyPlayerAlive := len(winners) == 1 && len(winners[0].players) == 1 for groupIdx, group := range winners { if mainPot == 0 { diff --git a/pkg/web/handlers/signup.go b/pkg/web/handlers/signup.go @@ -87,6 +87,8 @@ func signupHandler(c echo.Context) error { hbCookie, hbCookieErr := c.Cookie(hutils.HBCookieName) hasHBCookie := hbCookieErr == nil && hbCookie.Value != "" + pokerReferralCookie, _ := hutils.GetPokerReferralCookie(c) + signupInfo, _ := signupCache.Get(signupToken) data.HasSolvedCaptcha = signupInfo.hasSolvedCaptcha @@ -157,6 +159,14 @@ func signupHandler(c echo.Context) error { newUser.DoSave(db) } + if pokerReferralCookie != nil { + if referredByUser, err := db.GetUserByPokerReferralToken(pokerReferralCookie.Value); err == nil { + newUser.PokerReferredBy = &referredByUser.ID + newUser.DoSave(db) + c.SetCookie(hutils.DeleteCookie(hutils.PokerReferralName)) + } + } + invitationToken := c.Param("invitationToken") if invitationToken != "" { if invitation, err := db.GetUnusedInvitationByToken(invitationToken); err == nil { diff --git a/pkg/web/handlers/utils/utils.go b/pkg/web/handlers/utils/utils.go @@ -26,6 +26,7 @@ import ( const ( HBCookieName = "dkft" // dkf troll WaitCookieName = "wait-token" + PokerReferralName = "poker-referral-token" AuthCookieName = "auth-token" AprilFoolCookieName = "april_fool" ByteRoadCookieName = "challenge_byte_road_session" @@ -143,6 +144,14 @@ func GetLastMsgCookie(c echo.Context, roomName string) (*http.Cookie, error) { return c.Cookie(getLastMsgCookieName(roomName)) } +func CreatePokerReferralCookie(c echo.Context, v string) { + c.SetCookie(CreateCookie(PokerReferralName, v, utils.OneDaySecs)) +} + +func GetPokerReferralCookie(c echo.Context) (*http.Cookie, error) { + return c.Cookie(PokerReferralName) +} + func GetAprilFoolCookie(c echo.Context) int { v, err := c.Cookie(AprilFoolCookieName) if err != nil { diff --git a/pkg/web/middlewares/middlewares.go b/pkg/web/middlewares/middlewares.go @@ -283,6 +283,12 @@ func IsAuthMiddleware(next echo.HandlerFunc) echo.HandlerFunc { if strings.HasPrefix(c.Path(), "/api/") { return c.String(http.StatusUnauthorized, "unauthorized") } + referralToken := c.QueryParam("r") + if strings.HasPrefix(c.Path(), "/poker") && referralToken != "" { + if len(referralToken) == 9 { + hutils.CreatePokerReferralCookie(c, referralToken) + } + } return c.Redirect(http.StatusFound, "/?redirect="+c.Request().URL.String()) } diff --git a/pkg/web/public/views/pages/poker-rake-back.gohtml b/pkg/web/public/views/pages/poker-rake-back.gohtml @@ -0,0 +1,62 @@ +{{ define "extra-head" }} +{{ end }} + +{{ define "title" }}dkf - Poker rake back{{ end }} + +{{ define "content" }} + <div class="container mb-5"> + + <nav aria-label="breadcrumb"> + <ol class="breadcrumb"> + <li class="breadcrumb-item"><a href="/poker">Poker</a></li> + <li class="breadcrumb-item active">Rake back</li> + </ol> + </nav> + + <h3>Rake back</h3> + + <p> + When someone register using your referral code/url, + you will receive <strong>{{ .Data.RakeBackPct }}%</strong> of the rake + that this person generates while playing poker. + </p> + + <hr /> + + {{ if .Data.ReferralURL }} + <div class="form-group"> + <label>Your referral token:</label> + <input type="text" value="{{ .Data.ReferralToken }}" class="form-control" readonly /> + </div> + <div class="form-group"> + <label>Your referral URL:</label> + <input type="text" value="{{ .Data.ReferralURL }}" class="form-control" readonly /> + </div> + {{ else }} + <form method="post"> + <input type="hidden" name="csrf" value="{{ .CSRF }}" /> + <input type="hidden" name="form_name" value="generate_referral_url" /> + <button class="btn btn-primary">Generate referral URL</button> + </form> + {{ end }} + <hr /> + + <p> + If you wish to give your rake back to someone, enter their referral token here. + </p> + + {{ if .Data.SetReferralError }} + <div class="alert alert-danger">{{ .Data.SetReferralError }}</div> + {{ end }} + <form method="post"> + <input type="hidden" name="csrf" value="{{ .CSRF }}" /> + <input type="hidden" name="form_name" value="set_referrer" /> + <div class="input-group"> + <input type="text" name="referral_token" class="form-control" placeholder="Referral token (9 characters)" maxlength="9" /> + <div class="input-group-append"> + <button class="btn btn-primary">Set referrer</button> + </div> + </div> + </form> + </div> +{{ end }} diff --git a/pkg/web/public/views/pages/poker.gohtml b/pkg/web/public/views/pages/poker.gohtml @@ -18,10 +18,11 @@ rake is capped<br /> 2 confirmations needed for deposits under 0.2 XMR (~4min)<br /> 10 confirmations needed for deposits over 0.2 XMR (~20min)<br /> + Rake back percentage is <strong>{{ .Data.RakeBackPct }}%</strong><br /> <div class="clearfix"></div> </div> <div class="mb-3"> - <table> + <table class="mb-3"> <tr> <td> <span style="vertical-align: middle;">Balance: <span style="color: #eaac45;">{{ .Data.XmrBalance }} <small>pXMR</small></span></span><br /> @@ -30,7 +31,16 @@ <td style="vertical-align: middle;"><span class="ml-3" style="font-size: 30px; color: #1ee91e;">{{ .Data.XmrBalance.UsdStr }}</span></td> </tr> </table> - <br /> + <div class="mb-3"> + <a href="/poker/rake-back">Rake back</a>: <span style="color: #eaac45;">{{ .Data.RakeBack }} <small>chips</small></span> + {{ if gt .Data.RakeBack 0 }} + <form method="post" class="d-inline ml-3"> + <input type="hidden" name="csrf" value="{{ .CSRF }}" /> + <input type="hidden" name="form_name" value="claim_rake_back" /> + <button class="btn btn-primary btn-sm">Claim chips</button> + </form> + {{ end }} + </div> Free tables balance: <span style="color: #eaac45;">{{ .Data.ChipsTest }} <small>chips</small></span> <form method="post" class="d-inline ml-3"> <input type="hidden" name="csrf" value="{{ .CSRF }}" /> diff --git a/pkg/web/web.go b/pkg/web/web.go @@ -99,6 +99,8 @@ func getMainServer(db *database.DkfDB, i18nBundle *i18n.Bundle, renderer *tmp.Te authGroup.GET("/shop", handlers.ShopHandler) authGroup.GET("/poker", handlers.PokerHomeHandler) authGroup.POST("/poker", handlers.PokerHomeHandler, middlewares.AuthRateLimitMiddleware(time.Second, 1)) + authGroup.GET("/poker/rake-back", handlers.PokerRakeBackHandler) + authGroup.POST("/poker/rake-back", handlers.PokerRakeBackHandler) authGroup.GET("/poker/:roomID", handlers.PokerTableHandler) authGroup.GET("/poker/:roomID/stream", handlers.PokerStreamHandler) authGroup.GET("/poker/:roomID/logs", handlers.PokerLogsHandler)