163 lines
5.3 KiB
Go

package api
import (
dbclient "github.com/TicketsBot/GoPanel/database"
"github.com/TicketsBot/GoPanel/utils"
"github.com/TicketsBot/GoPanel/utils/types"
"github.com/TicketsBot/common/model"
"github.com/TicketsBot/common/permission"
"github.com/TicketsBot/common/premium"
"github.com/gin-gonic/gin"
"net/http"
)
type setActiveGuildsBody struct {
SelectedGuilds types.UInt64StringSlice `json:"selected_guilds"`
}
func SetActiveGuilds(ctx *gin.Context) {
userId := ctx.Keys["userid"].(uint64)
var body setActiveGuildsBody
if err := ctx.ShouldBindJSON(&body); err != nil {
ctx.JSON(http.StatusBadRequest, utils.ErrorJson(err))
return
}
legacyEntitlement, err := dbclient.Client.LegacyPremiumEntitlements.GetUserTier(ctx, userId, premium.PatreonGracePeriod)
if err != nil {
ctx.JSON(http.StatusInternalServerError, utils.ErrorJson(err))
return
}
if legacyEntitlement == nil || legacyEntitlement.IsLegacy {
ctx.JSON(http.StatusBadRequest, utils.ErrorStr("Not a premium user"))
return
}
tx, err := dbclient.Client.BeginTx(ctx)
if err != nil {
ctx.JSON(http.StatusInternalServerError, utils.ErrorJson(err))
return
}
defer tx.Rollback(ctx)
// Validate under the limit
limit, ok, err := dbclient.Client.MultiServerSkus.GetPermittedServerCount(ctx, tx, legacyEntitlement.SkuId)
if err != nil {
ctx.JSON(http.StatusInternalServerError, utils.ErrorJson(err))
return
}
if !ok {
ctx.JSON(http.StatusBadRequest, utils.ErrorStr("Not a multi-server subscription"))
return
}
if len(body.SelectedGuilds) > limit {
ctx.JSON(http.StatusBadRequest, utils.ErrorStr("Too many guilds selected"))
return
}
// Validate has admin in each server
for _, guildId := range body.SelectedGuilds {
permissionLevel, err := utils.GetPermissionLevel(ctx, guildId, userId)
if err != nil {
ctx.JSON(http.StatusInternalServerError, utils.ErrorJson(err))
return
}
if permissionLevel < permission.Admin {
ctx.JSON(http.StatusForbidden, utils.ErrorStr("Missing permissions in guild %d", guildId))
return
}
}
existingGuildEntitlements, err := dbclient.Client.LegacyPremiumEntitlementGuilds.ListForUser(ctx, tx, userId)
if err != nil {
ctx.JSON(http.StatusInternalServerError, utils.ErrorJson(err))
return
}
// Remove entitlements from guilds that are no longer selected
for _, existingEntitlement := range existingGuildEntitlements {
if !utils.Contains(body.SelectedGuilds, existingEntitlement.GuildId) {
if err := dbclient.Client.LegacyPremiumEntitlementGuilds.DeleteByEntitlement(ctx, tx, existingEntitlement.EntitlementId); err != nil {
ctx.JSON(http.StatusInternalServerError, utils.ErrorJson(err))
return
}
if err := dbclient.Client.Entitlements.DeleteById(ctx, tx, existingEntitlement.EntitlementId); err != nil {
ctx.JSON(http.StatusInternalServerError, utils.ErrorJson(err))
return
}
}
}
// Create entitlements for guilds that were not previously selected, but now are
existingGuildIds := make([]uint64, len(existingGuildEntitlements))
for i, existingEntitlement := range existingGuildEntitlements {
existingGuildIds[i] = existingEntitlement.GuildId
}
for _, guildId := range body.SelectedGuilds {
if !utils.Contains(existingGuildIds, guildId) {
created, err := dbclient.Client.Entitlements.Create(ctx, tx, &guildId, &userId, legacyEntitlement.SkuId, model.EntitlementSourcePatreon, nil)
if err != nil {
ctx.JSON(http.StatusInternalServerError, utils.ErrorJson(err))
return
}
if err := dbclient.Client.LegacyPremiumEntitlementGuilds.Insert(ctx, tx, userId, guildId, created.Id); err != nil {
ctx.JSON(http.StatusInternalServerError, utils.ErrorJson(err))
return
}
}
}
// Update entitlements for guilds that were previously selected and still are. This may involve recreating the
// entitlement if the SKU has changed.
for _, existingEntitlement := range existingGuildEntitlements {
if utils.Contains(body.SelectedGuilds, existingEntitlement.GuildId) {
entitlement, err := dbclient.Client.Entitlements.GetById(ctx, tx, existingEntitlement.EntitlementId)
if err != nil {
ctx.JSON(http.StatusInternalServerError, utils.ErrorJson(err))
return
}
if entitlement == nil {
ctx.JSON(http.StatusInternalServerError, utils.ErrorStr("Entitlement %s not found", existingEntitlement.EntitlementId.String()))
return
}
if entitlement.SkuId == legacyEntitlement.SkuId {
continue
} else {
// If we need to switch the SKU, then delete and recreate the entitlement
if err := dbclient.Client.LegacyPremiumEntitlementGuilds.DeleteByEntitlement(ctx, tx, existingEntitlement.EntitlementId); err != nil {
ctx.JSON(http.StatusInternalServerError, utils.ErrorJson(err))
return
}
if err := dbclient.Client.Entitlements.DeleteById(ctx, tx, existingEntitlement.EntitlementId); err != nil {
ctx.JSON(http.StatusInternalServerError, utils.ErrorJson(err))
return
}
if _, err := dbclient.Client.Entitlements.Create(ctx, tx, &existingEntitlement.GuildId, &userId, legacyEntitlement.SkuId, model.EntitlementSourcePatreon, entitlement.ExpiresAt); err != nil {
ctx.JSON(http.StatusInternalServerError, utils.ErrorJson(err))
return
}
}
}
}
if err := tx.Commit(ctx); err != nil {
ctx.JSON(http.StatusInternalServerError, utils.ErrorJson(err))
return
}
ctx.Status(http.StatusNoContent)
}