1
0
Fork 0
mirror of https://git.sr.ht/~ashkeel/strimertul synced 2024-09-18 01:50:50 +00:00

Handle goal redemption via stulbe

This commit is contained in:
Ash Keel 2021-05-18 15:50:58 +02:00
parent e377a88837
commit bfce1f6ce4
No known key found for this signature in database
GPG key ID: CF2CC050478BD7E5
4 changed files with 102 additions and 66 deletions

2
go.mod
View file

@ -11,6 +11,6 @@ require (
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4
github.com/sirupsen/logrus v1.8.1
github.com/strimertul/kilovolt/v4 v4.0.1
github.com/strimertul/stulbe v0.4.2
github.com/strimertul/stulbe v0.4.3
github.com/strimertul/stulbe-client-go v0.2.0
)

4
go.sum
View file

@ -113,8 +113,8 @@ github.com/strimertul/kilovolt/v4 v4.0.1/go.mod h1:AO2ZFQtSB+AcjCw0RTkXjbM6XBAjh
github.com/strimertul/strimertul v1.3.0/go.mod h1:1pSe9zVWF4BYt56ii1Hg+xTxvtfqfvT4FQ7bYffWsUA=
github.com/strimertul/stulbe v0.2.5/go.mod h1:0AsY4OVf1dNCwOn9s7KySuAxJ85w88pXeostu1n9E7w=
github.com/strimertul/stulbe v0.3.0/go.mod h1:Pb0UQCKdyES7UKSKm2i2g9parkgXSJAFeMH/LSOSbgQ=
github.com/strimertul/stulbe v0.4.2 h1:dxxjGtLiUEyMu/V7Rc7kurcY6DHS7jXS8/GEfQPSFR4=
github.com/strimertul/stulbe v0.4.2/go.mod h1:Pb0UQCKdyES7UKSKm2i2g9parkgXSJAFeMH/LSOSbgQ=
github.com/strimertul/stulbe v0.4.3 h1:apDTvFaChCoMxUokc1Y51Wn43hWyf0qqMNkptnlIj/c=
github.com/strimertul/stulbe v0.4.3/go.mod h1:Pb0UQCKdyES7UKSKm2i2g9parkgXSJAFeMH/LSOSbgQ=
github.com/strimertul/stulbe-client-go v0.1.0/go.mod h1:KtfuDhxCHZ9DCFHnrBOHqb2Pu9zoj+EqA8ZRIUqLD/w=
github.com/strimertul/stulbe-client-go v0.2.0 h1:zoUu+/ssOWz9VsoioJkQNMU88qJ/lQzAu6ak8GcTYxY=
github.com/strimertul/stulbe-client-go v0.2.0/go.mod h1:5S+nDMyzkeoBHi9fq3s37A4mv3XUPJhwgW94UtGzp28=

View file

@ -16,7 +16,8 @@ import (
)
var (
ErrGoalNotFound = errors.New("goal not found")
ErrGoalNotFound = errors.New("goal not found")
ErrGoalAlreadyReached = errors.New("goal already reached")
)
type Manager struct {
@ -171,7 +172,7 @@ func (m *Manager) handleRemote(kvs []database.ModifiedKV) error {
break
}
// Find reward
reward := m.getReward(redeemRequest.RewardID)
reward := m.GetReward(redeemRequest.RewardID)
if reward.ID == "" {
m.logger.WithField("reward-id", redeemRequest.RewardID).Warn("redeem request contains invalid reward id")
break
@ -186,6 +187,24 @@ func (m *Manager) handleRemote(kvs []database.ModifiedKV) error {
if err != nil {
m.logger.WithError(err).Warn("error performing redeem request")
}
case api.KVExLoyaltyContribute:
// Parse request
var contributeRequest api.ExLoyaltyContribute
err := jsoniter.ConfigFastest.Unmarshal(kv.Data, &contributeRequest)
if err != nil {
m.logger.WithError(err).Warn("error decoding contribution request")
break
}
// Find goal
goal := m.GetGoal(contributeRequest.GoalID)
if goal.ID == "" {
m.logger.WithField("goal-id", contributeRequest.GoalID).Warn("contribute request contains invalid goal id")
break
}
err = m.PerformContribution(goal, contributeRequest.Username, contributeRequest.Amount)
if err != nil {
m.logger.WithError(err).Warn("error performing contribution request")
}
}
}
return nil
@ -305,13 +324,42 @@ func (m *Manager) ContributeGoal(goal Goal, user string, points int64) error {
return ErrGoalNotFound
}
func (m *Manager) PerformContribution(goal Goal, user string, points int64) error {
// Get user balance
balance := m.GetPoints(user)
// If user specified more points than they have, pick the maximum possible
if points > balance {
points = balance
}
// Check if goal was reached already
if goal.Contributed >= goal.TotalGoal {
return ErrGoalAlreadyReached
}
// If remaining points are lower than what user is contributing, only take what's needed
remaining := goal.TotalGoal - goal.Contributed
if points > remaining {
points = remaining
}
// Remove points from user
if err := m.TakePoints(map[string]int64{user: points}); err != nil {
return err
}
// Add points to goal
return m.ContributeGoal(goal, user, points)
}
func (m *Manager) Rewards() []Reward {
m.mu.Lock()
defer m.mu.Unlock()
return m.rewards[:]
}
func (m *Manager) getReward(id string) Reward {
func (m *Manager) GetReward(id string) Reward {
m.mu.Lock()
defer m.mu.Unlock()
for _, reward := range m.rewards {
@ -322,6 +370,17 @@ func (m *Manager) getReward(id string) Reward {
return Reward{}
}
func (m *Manager) GetGoal(id string) Goal {
m.mu.Lock()
defer m.mu.Unlock()
for _, goal := range m.goals {
if goal.ID == id {
return goal
}
}
return Goal{}
}
func (m *Manager) Config() Config {
m.mu.Lock()
defer m.mu.Unlock()

View file

@ -69,47 +69,44 @@ func cmdRedeemReward(bot *Bot, message irc.PrivateMessage) {
redeemID := parts[1]
// Find reward
for _, reward := range bot.Loyalty.Rewards() {
if reward.ID != redeemID {
continue
}
// Reward not active, return early
if !reward.Enabled {
return
}
// Get user balance
balance := bot.Loyalty.GetPoints(message.User.Name)
config := bot.Loyalty.Config()
// Check if user can afford the reward
if balance-reward.Price < 0 {
bot.Client.Say(message.Channel, fmt.Sprintf("I'm sorry %s but you cannot afford this (have %d %s, need %d)", message.User.DisplayName, balance, config.Currency, reward.Price))
return
}
text := ""
if len(parts) > 2 {
text = strings.Join(parts[2:], " ")
}
// Perform redeem
if err := bot.Loyalty.PerformRedeem(loyalty.Redeem{
Username: message.User.Name,
DisplayName: message.User.DisplayName,
When: time.Now(),
Reward: reward,
RequestText: text,
}); err != nil {
bot.logger.WithError(err).Error("error while performing redeem")
return
}
bot.Client.Say(message.Channel, fmt.Sprintf("HolidayPresent %s has redeemed %s! (new balance: %d %s)", message.User.DisplayName, reward.Name, bot.Loyalty.GetPoints(message.User.Name), config.Currency))
reward := bot.Loyalty.GetReward(redeemID)
if reward.ID == "" {
return
}
// Reward not active, return early
if !reward.Enabled {
return
}
// Get user balance
balance := bot.Loyalty.GetPoints(message.User.Name)
config := bot.Loyalty.Config()
// Check if user can afford the reward
if balance-reward.Price < 0 {
bot.Client.Say(message.Channel, fmt.Sprintf("I'm sorry %s but you cannot afford this (have %d %s, need %d)", message.User.DisplayName, balance, config.Currency, reward.Price))
return
}
text := ""
if len(parts) > 2 {
text = strings.Join(parts[2:], " ")
}
// Perform redeem
if err := bot.Loyalty.PerformRedeem(loyalty.Redeem{
Username: message.User.Name,
DisplayName: message.User.DisplayName,
When: time.Now(),
Reward: reward,
RequestText: text,
}); err != nil {
bot.logger.WithError(err).Error("error while performing redeem")
return
}
bot.Client.Say(message.Channel, fmt.Sprintf("HolidayPresent %s has redeemed %s! (new balance: %d %s)", message.User.DisplayName, reward.Name, bot.Loyalty.GetPoints(message.User.Name), config.Currency))
}
func cmdGoalList(bot *Bot, message irc.PrivateMessage) {
@ -192,14 +189,6 @@ func cmdContributeGoal(bot *Bot, message irc.PrivateMessage) {
}
}
// Get user balance
balance := bot.Loyalty.GetPoints(message.User.Name)
// If user specified more points than they have, pick the maximum possible
if points > balance {
points = balance
}
// Get goal
selectedGoal := goals[goalIndex]
@ -209,20 +198,8 @@ func cmdContributeGoal(bot *Bot, message irc.PrivateMessage) {
return
}
// If remaining points are lower than what user is contributing, only take what's needed
remaining := selectedGoal.TotalGoal - selectedGoal.Contributed
if points > remaining {
points = remaining
}
// Remove points from user
if err := bot.Loyalty.TakePoints(map[string]int64{message.User.Name: points}); err != nil {
bot.logger.WithError(err).Error("error while taking points for redeem")
return
}
// Add points to goal
if err := bot.Loyalty.ContributeGoal(selectedGoal, message.User.Name, points); err != nil {
if err := bot.Loyalty.PerformContribution(selectedGoal, message.User.Name, points); err != nil {
bot.logger.WithError(err).Error("error while contributing to goal")
return
}