Create interface for selecting premium guilds
This commit is contained in:
parent
dbdccb2e3d
commit
18e81f4936
162
app/http/endpoints/api/premium/activeguilds.go
Normal file
162
app/http/endpoints/api/premium/activeguilds.go
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
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)
|
||||||
|
}
|
70
app/http/endpoints/api/premium/entitlements.go
Normal file
70
app/http/endpoints/api/premium/entitlements.go
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
dbclient "github.com/TicketsBot/GoPanel/database"
|
||||||
|
"github.com/TicketsBot/GoPanel/utils"
|
||||||
|
"github.com/TicketsBot/GoPanel/utils/types"
|
||||||
|
"github.com/TicketsBot/common/premium"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/jackc/pgx/v4"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetEntitlements(ctx *gin.Context) {
|
||||||
|
userId := ctx.Keys["userid"].(uint64)
|
||||||
|
|
||||||
|
entitlements, err := dbclient.Client.Entitlements.ListUserSubscriptions(ctx, userId, premium.GracePeriod)
|
||||||
|
if err != nil {
|
||||||
|
ctx.JSON(http.StatusInternalServerError, utils.ErrorJson(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
legacyEntitlement, err := dbclient.Client.LegacyPremiumEntitlements.GetUserTier(ctx, userId, premium.GracePeriod)
|
||||||
|
if err != nil {
|
||||||
|
ctx.JSON(http.StatusInternalServerError, utils.ErrorJson(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res := gin.H{
|
||||||
|
"entitlements": entitlements,
|
||||||
|
"legacy_entitlement": legacyEntitlement,
|
||||||
|
}
|
||||||
|
|
||||||
|
if legacyEntitlement == nil || legacyEntitlement.IsLegacy {
|
||||||
|
ctx.JSON(http.StatusOK, res)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it's a multi-server subscription, fetch more data
|
||||||
|
var permitted *int
|
||||||
|
guildIds := make([]uint64, 0)
|
||||||
|
if err := dbclient.Client.WithTx(ctx, func(tx pgx.Tx) error {
|
||||||
|
tmp, ok, err := dbclient.Client.MultiServerSkus.GetPermittedServerCount(ctx, tx, legacyEntitlement.SkuId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok {
|
||||||
|
permitted = &tmp
|
||||||
|
}
|
||||||
|
|
||||||
|
activeEntitlements, err := dbclient.Client.LegacyPremiumEntitlementGuilds.ListForUser(ctx, tx, userId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, entitlement := range activeEntitlements {
|
||||||
|
guildIds = append(guildIds, entitlement.GuildId)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
ctx.JSON(http.StatusInternalServerError, utils.ErrorJson(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res["permitted_server_count"] = permitted
|
||||||
|
res["selected_guilds"] = types.UInt64StringSlice(guildIds)
|
||||||
|
|
||||||
|
ctx.JSON(http.StatusOK, res)
|
||||||
|
}
|
@ -7,6 +7,7 @@ import (
|
|||||||
api_forms "github.com/TicketsBot/GoPanel/app/http/endpoints/api/forms"
|
api_forms "github.com/TicketsBot/GoPanel/app/http/endpoints/api/forms"
|
||||||
api_integrations "github.com/TicketsBot/GoPanel/app/http/endpoints/api/integrations"
|
api_integrations "github.com/TicketsBot/GoPanel/app/http/endpoints/api/integrations"
|
||||||
api_panels "github.com/TicketsBot/GoPanel/app/http/endpoints/api/panel"
|
api_panels "github.com/TicketsBot/GoPanel/app/http/endpoints/api/panel"
|
||||||
|
api_premium "github.com/TicketsBot/GoPanel/app/http/endpoints/api/premium"
|
||||||
api_settings "github.com/TicketsBot/GoPanel/app/http/endpoints/api/settings"
|
api_settings "github.com/TicketsBot/GoPanel/app/http/endpoints/api/settings"
|
||||||
api_override "github.com/TicketsBot/GoPanel/app/http/endpoints/api/staffoverride"
|
api_override "github.com/TicketsBot/GoPanel/app/http/endpoints/api/staffoverride"
|
||||||
api_tags "github.com/TicketsBot/GoPanel/app/http/endpoints/api/tags"
|
api_tags "github.com/TicketsBot/GoPanel/app/http/endpoints/api/tags"
|
||||||
@ -79,6 +80,7 @@ func StartServer(sm *livechat.SocketManager) {
|
|||||||
{
|
{
|
||||||
apiGroup.GET("/session", api.SessionHandler)
|
apiGroup.GET("/session", api.SessionHandler)
|
||||||
|
|
||||||
|
{
|
||||||
integrationGroup := apiGroup.Group("/integrations")
|
integrationGroup := apiGroup.Group("/integrations")
|
||||||
|
|
||||||
integrationGroup.GET("/self", api_integrations.GetOwnedIntegrationsHandler)
|
integrationGroup.GET("/self", api_integrations.GetOwnedIntegrationsHandler)
|
||||||
@ -90,6 +92,13 @@ func StartServer(sm *livechat.SocketManager) {
|
|||||||
apiGroup.POST("/integrations", api_integrations.CreateIntegrationHandler)
|
apiGroup.POST("/integrations", api_integrations.CreateIntegrationHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
premiumGroup := apiGroup.Group("/premium/@me")
|
||||||
|
premiumGroup.GET("/entitlements", api_premium.GetEntitlements)
|
||||||
|
premiumGroup.PUT("/active-guilds", api_premium.SetActiveGuilds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
guildAuthApiAdmin := apiGroup.Group("/:id", middleware.AuthenticateGuild(permission.Admin))
|
guildAuthApiAdmin := apiGroup.Group("/:id", middleware.AuthenticateGuild(permission.Admin))
|
||||||
guildAuthApiSupport := apiGroup.Group("/:id", middleware.AuthenticateGuild(permission.Support))
|
guildAuthApiSupport := apiGroup.Group("/:id", middleware.AuthenticateGuild(permission.Support))
|
||||||
guildApiNoAuth := apiGroup.Group("/:id", middleware.ParseGuildId)
|
guildApiNoAuth := apiGroup.Group("/:id", middleware.ParseGuildId)
|
||||||
|
@ -34,6 +34,7 @@ import CreatePanel from "./views/panels/CreatePanel.svelte";
|
|||||||
import CreateMultiPanel from "./views/panels/CreateMultiPanel.svelte";
|
import CreateMultiPanel from "./views/panels/CreateMultiPanel.svelte";
|
||||||
import EditPanel from "./views/panels/EditPanel.svelte";
|
import EditPanel from "./views/panels/EditPanel.svelte";
|
||||||
import EditMultiPanel from "./views/panels/EditMultiPanel.svelte";
|
import EditMultiPanel from "./views/panels/EditMultiPanel.svelte";
|
||||||
|
import SelectServers from "./views/premium/SelectServers.svelte";
|
||||||
|
|
||||||
export const routes = [
|
export const routes = [
|
||||||
{name: '/', component: Index, layout: IndexLayout},
|
{name: '/', component: Index, layout: IndexLayout},
|
||||||
@ -43,6 +44,12 @@ export const routes = [
|
|||||||
{name: '/logout', component: Logout},
|
{name: '/logout', component: Logout},
|
||||||
{name: '/error', component: Error, layout: ErrorLayout},
|
{name: '/error', component: Error, layout: ErrorLayout},
|
||||||
{name: '/whitelabel', component: Whitelabel, layout: IndexLayout},
|
{name: '/whitelabel', component: Whitelabel, layout: IndexLayout},
|
||||||
|
{
|
||||||
|
name: 'premium',
|
||||||
|
nestedRoutes: [
|
||||||
|
{name: 'select-servers', component: SelectServers, layout: IndexLayout}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'admin',
|
name: 'admin',
|
||||||
nestedRoutes: [
|
nestedRoutes: [
|
||||||
|
@ -0,0 +1,183 @@
|
|||||||
|
<main>
|
||||||
|
<Card fill={false} footer={false}>
|
||||||
|
<span slot="title">Choose Premium Servers</span>
|
||||||
|
<div slot="body" class="card-body">
|
||||||
|
<div class="explanation">
|
||||||
|
<span>Your premium subscription allows you to choose {@html limit === 1 ? "<b>one</b> server" : `up to <b>${limit}</b> servers`}
|
||||||
|
to apply premium to.
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
Currently selected: <b>{selected.length} / {limit}</b> server{limit > 1 ? "s" : ""}.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="servers">
|
||||||
|
{#each getAdminGuilds(guilds) as guild}
|
||||||
|
<div class="server" class:active={selected.includes(guild.id)} class:pointer={selected.length < limit || selected.includes(guild.id)}
|
||||||
|
on:click={() => toggleSelected(guild.id)}>
|
||||||
|
<img src="{getIconUrl(guild.id, guild.icon)}" alt="Guild Icon" on:error={(e) => handleImgLoadError(e, guild.id)} />
|
||||||
|
<span class="name">{guild.name}</span>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
<div class="submit-wrapper">
|
||||||
|
<Button on:click={submitServers}>Save</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
main {
|
||||||
|
width: 100%;
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1em;
|
||||||
|
padding-bottom: 1em;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.explanation {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.servers {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 1em;
|
||||||
|
row-gap: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.server {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex: 1 0 21%;
|
||||||
|
gap: 1em;
|
||||||
|
padding: 8px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
user-select: none;
|
||||||
|
background-color: #121212;
|
||||||
|
border: 1px solid #121212;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.server.pointer {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.server.active {
|
||||||
|
border-color: var(--primary);
|
||||||
|
box-shadow: 0 0 10px var(--primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.server > img {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {withLoadingScreen, notifyError, notifySuccess} from '../../js/util';
|
||||||
|
import {setDefaultHeaders} from '../../includes/Auth.svelte'
|
||||||
|
import Card from "../../components/Card.svelte";
|
||||||
|
import {getIconUrl, getDefaultIcon} from "../../js/icons";
|
||||||
|
import {API_URL} from "../../js/constants";
|
||||||
|
import Button from "../../components/Button.svelte";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
let limit = 1;
|
||||||
|
let selected = [];
|
||||||
|
let guilds = [];
|
||||||
|
|
||||||
|
function getAdminGuilds(guilds) {
|
||||||
|
return guilds.filter(g => g.permission_level === 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
let failed = [];
|
||||||
|
function handleImgLoadError(e, guildId) {
|
||||||
|
if (!failed.includes(guildId)) {
|
||||||
|
failed = [...failed, guildId];
|
||||||
|
e.target.src = getDefaultIcon(guildId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleSelected(guildId) {
|
||||||
|
if (selected.includes(guildId)) {
|
||||||
|
selected = selected.filter(id => id !== guildId);
|
||||||
|
} else {
|
||||||
|
if (selected.length < limit) {
|
||||||
|
selected = [...selected, guildId];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setDefaultHeaders();
|
||||||
|
|
||||||
|
async function loadEntitlements() {
|
||||||
|
const res = await axios.get(`${API_URL}/api/premium/@me/entitlements`)
|
||||||
|
if (res.status !== 200) {
|
||||||
|
notifyError(`Failed to load entitlements: ${res.data.error}`)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.data.legacy_entitlement === null || res.data.legacy_entitlement.is_legacy) {
|
||||||
|
notifyError('This feature is only available to users with a server-specific premium subscription via Patreon.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
limit = res.data.permitted_server_count;
|
||||||
|
selected = res.data.selected_guilds;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadGuilds() {
|
||||||
|
const res = await axios.get(`${API_URL}/user/guilds`)
|
||||||
|
if (res.status !== 200) {
|
||||||
|
notifyError(`Failed to load guilds: ${res.data.error}`)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
guilds = [...guilds, ...res.data];
|
||||||
|
}
|
||||||
|
|
||||||
|
async function submitServers() {
|
||||||
|
const res = await axios.put(`${API_URL}/api/premium/@me/active-guilds`, {
|
||||||
|
selected_guilds: selected
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.status !== 204) {
|
||||||
|
notifyError(`Failed to save servers: ${res.data.error}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
notifySuccess('Your premium server selection has been saved.')
|
||||||
|
}
|
||||||
|
|
||||||
|
withLoadingScreen(async () => {
|
||||||
|
await Promise.all([
|
||||||
|
loadEntitlements(),
|
||||||
|
loadGuilds()
|
||||||
|
]);
|
||||||
|
|
||||||
|
for (const id of selected) {
|
||||||
|
if (!guilds.find(g => g.id === id)) {
|
||||||
|
guilds = [{
|
||||||
|
id,
|
||||||
|
name: `Unknown Server ${id}`,
|
||||||
|
icon: "",
|
||||||
|
permission_level: 2
|
||||||
|
}, ...guilds];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
2
go.mod
2
go.mod
@ -8,7 +8,7 @@ require (
|
|||||||
github.com/BurntSushi/toml v1.2.1
|
github.com/BurntSushi/toml v1.2.1
|
||||||
github.com/TicketsBot/archiverclient v0.0.0-20240613013458-accc062facc2
|
github.com/TicketsBot/archiverclient v0.0.0-20240613013458-accc062facc2
|
||||||
github.com/TicketsBot/common v0.0.0-20240829163809-6f60869d8941
|
github.com/TicketsBot/common v0.0.0-20240829163809-6f60869d8941
|
||||||
github.com/TicketsBot/database v0.0.0-20240829163737-86b657b7e506
|
github.com/TicketsBot/database v0.0.0-20240901155918-d0c56594a09a
|
||||||
github.com/TicketsBot/logarchiver v0.0.0-20220326162808-cdf0310f5e1c
|
github.com/TicketsBot/logarchiver v0.0.0-20220326162808-cdf0310f5e1c
|
||||||
github.com/TicketsBot/worker v0.0.0-20240829163848-84556c59ee72
|
github.com/TicketsBot/worker v0.0.0-20240829163848-84556c59ee72
|
||||||
github.com/apex/log v1.1.2
|
github.com/apex/log v1.1.2
|
||||||
|
2
go.sum
2
go.sum
@ -70,6 +70,8 @@ github.com/TicketsBot/database v0.0.0-20240829155519-6b47874c9775 h1:4BhqGSlvI+t
|
|||||||
github.com/TicketsBot/database v0.0.0-20240829155519-6b47874c9775/go.mod h1:XhV3kI4ogTxBJATmO20kxmaynUcqCf3PCnbVbxkYNyQ=
|
github.com/TicketsBot/database v0.0.0-20240829155519-6b47874c9775/go.mod h1:XhV3kI4ogTxBJATmO20kxmaynUcqCf3PCnbVbxkYNyQ=
|
||||||
github.com/TicketsBot/database v0.0.0-20240829163737-86b657b7e506 h1:mU2wx9pyb7258RYyh9ZpTkDDFZMtP3C8YFphFEjxgWE=
|
github.com/TicketsBot/database v0.0.0-20240829163737-86b657b7e506 h1:mU2wx9pyb7258RYyh9ZpTkDDFZMtP3C8YFphFEjxgWE=
|
||||||
github.com/TicketsBot/database v0.0.0-20240829163737-86b657b7e506/go.mod h1:tnSNh3i0tPw2xmTzF8JnQPPpKY9QdwbeH2d4xzYcqcM=
|
github.com/TicketsBot/database v0.0.0-20240829163737-86b657b7e506/go.mod h1:tnSNh3i0tPw2xmTzF8JnQPPpKY9QdwbeH2d4xzYcqcM=
|
||||||
|
github.com/TicketsBot/database v0.0.0-20240901155918-d0c56594a09a h1:kNDfpVimz3kEBYpiIql1rJDDUHiBKZEdw+JLyH4Ne9w=
|
||||||
|
github.com/TicketsBot/database v0.0.0-20240901155918-d0c56594a09a/go.mod h1:tnSNh3i0tPw2xmTzF8JnQPPpKY9QdwbeH2d4xzYcqcM=
|
||||||
github.com/TicketsBot/logarchiver v0.0.0-20220326162808-cdf0310f5e1c h1:OqGjFH6mbE6gd+NqI2ARJdtH3UUvhiAkD0r0fhGJK2s=
|
github.com/TicketsBot/logarchiver v0.0.0-20220326162808-cdf0310f5e1c h1:OqGjFH6mbE6gd+NqI2ARJdtH3UUvhiAkD0r0fhGJK2s=
|
||||||
github.com/TicketsBot/logarchiver v0.0.0-20220326162808-cdf0310f5e1c/go.mod h1:jgi2OXQKsd5nUnTIRkwvPmeuD/i7OhN68LKMssuQY1c=
|
github.com/TicketsBot/logarchiver v0.0.0-20220326162808-cdf0310f5e1c/go.mod h1:jgi2OXQKsd5nUnTIRkwvPmeuD/i7OhN68LKMssuQY1c=
|
||||||
github.com/TicketsBot/ttlcache v1.6.1-0.20200405150101-acc18e37b261 h1:NHD5GB6cjlkpZFjC76Yli2S63/J2nhr8MuE6KlYJpQM=
|
github.com/TicketsBot/ttlcache v1.6.1-0.20200405150101-acc18e37b261 h1:NHD5GB6cjlkpZFjC76Yli2S63/J2nhr8MuE6KlYJpQM=
|
||||||
|
Loading…
x
Reference in New Issue
Block a user