2024-11-09 11:42:56 +05:30

131 lines
4.1 KiB
Go

package offer
import (
"context"
"database/sql"
"encoding/json"
"errors"
"fmt"
"os"
"github.com/ente-io/museum/pkg/controller/usercache"
"github.com/ente-io/museum/ente"
storageBonusEntity "github.com/ente-io/museum/ente/storagebonus"
"github.com/ente-io/museum/pkg/controller/discord"
"github.com/ente-io/museum/pkg/repo"
"github.com/ente-io/museum/pkg/repo/storagebonus"
"github.com/ente-io/museum/pkg/utils/array"
"github.com/ente-io/museum/pkg/utils/billing"
"github.com/ente-io/museum/pkg/utils/config"
emailUtil "github.com/ente-io/museum/pkg/utils/email"
"github.com/ente-io/museum/pkg/utils/time"
"github.com/ente-io/stacktrace"
log "github.com/sirupsen/logrus"
)
// OfferController controls all offer related operations
type OfferController struct {
BlackFridayOffers ente.BlackFridayOfferPerCountry
UserRepo repo.UserRepository
DiscordController *discord.DiscordController
StorageBonusRepo *storagebonus.Repository
UserCacheCtrl *usercache.Controller
}
func NewOfferController(
userRepo repo.UserRepository,
discordController *discord.DiscordController,
storageBonusRepo *storagebonus.Repository,
userCacheCtrl *usercache.Controller,
) *OfferController {
blackFridayOffers := make(ente.BlackFridayOfferPerCountry)
path, err := config.BillingConfigFilePath("black-friday.json")
if err != nil {
log.Fatalf("Error getting offer config file: %v", err)
}
data, err := os.ReadFile(path)
if err != nil {
log.Error("Error reading config file", err)
}
err = json.Unmarshal(data, &blackFridayOffers)
if err != nil {
log.Error("Error un-marshalling JSON", err)
}
return &OfferController{
BlackFridayOffers: blackFridayOffers,
UserRepo: userRepo,
DiscordController: discordController,
StorageBonusRepo: storageBonusRepo,
UserCacheCtrl: userCacheCtrl,
}
}
func (c *OfferController) GetBlackFridayOffers(countryCode string) []ente.BlackFridayOffer {
if array.StringInList(countryCode, billing.CountriesInEU) {
countryCode = "EU"
}
if offers, found := c.BlackFridayOffers[countryCode]; found {
return offers
}
// unable to find plans for given country code, return plans for default country
defaultCountry := billing.GetDefaultPlanCountry()
return c.BlackFridayOffers[defaultCountry]
}
func (c *OfferController) ApplyOffer(email string, productID string) error {
var offerToBeApplied ente.BlackFridayOffer
found := false
for _, offers := range c.BlackFridayOffers {
for _, offer := range offers {
if offer.ID == productID {
found = true
offerToBeApplied = offer
}
}
}
if !found {
return stacktrace.Propagate(ente.ErrNotFound, "Could not find an offer for "+productID)
}
var validTill int64
if offerToBeApplied.PeriodInYears == ente.Period3Years {
validTill = time.NDaysFromNow(3 * 365)
} else if offerToBeApplied.PeriodInYears == ente.Period5Years {
validTill = time.NDaysFromNow(5 * 365)
} else if offerToBeApplied.PeriodInYears == ente.Period10Years {
validTill = time.NDaysFromNow(10 * 365)
} else {
return stacktrace.Propagate(ente.ErrNotFound, "Could not find a valid time period for "+productID)
}
userID, err := c.UserRepo.GetUserIDWithEmail(email)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
log.Error("Product purchased with unknown email: " + email)
c.DiscordController.Notify("Unknown user paid " + offerToBeApplied.Price)
return nil
} else {
return stacktrace.Propagate(err, "")
}
}
err = c.StorageBonusRepo.InsertAddOnBonus(context.Background(), storageBonusEntity.AddOnBf2024, userID, validTill, offerToBeApplied.Storage)
if err != nil {
c.DiscordController.Notify("Error inserting bonus")
return stacktrace.Propagate(err, "")
}
go c.UserCacheCtrl.GetActiveStorageBonus(context.Background(), userID)
go emailUtil.SendTemplatedEmail([]string{email}, "Ente", "team@ente.io",
ente.BF2024EmailSubject,
ente.BF2024EmailTemplate, map[string]interface{}{
"Storage": c.readableStorage(offerToBeApplied.Storage),
}, nil)
c.DiscordController.NotifyBlackFridayUser(userID, offerToBeApplied.Price)
return nil
}
func (c *OfferController) readableStorage(storage int64) string {
return fmt.Sprintf("%d GB", storage/(1<<30))
}