/* * Copyright (C) 2026 Fluxer Contributors * * This file is part of Fluxer. * * Fluxer is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Fluxer is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Fluxer. If not, see . */ import {Endpoints} from '~/Endpoints'; import http from '~/lib/HttpClient'; import {Logger} from '~/lib/Logger'; const logger = new Logger('Premium'); export interface VisionarySlots { total: number; remaining: number; } export interface PriceIds { monthly: string | null; yearly: string | null; visionary: string | null; giftVisionary: string | null; gift1Month: string | null; gift1Year: string | null; currency: 'USD' | 'EUR'; } export const fetchVisionarySlots = async (): Promise => { try { const response = await http.get(Endpoints.PREMIUM_VISIONARY_SLOTS); logger.debug('Visionary slots fetched', response.body); return response.body; } catch (error) { logger.error('Visionary slots fetch failed', error); throw error; } }; export const fetchPriceIds = async (countryCode?: string): Promise => { try { const url = countryCode ? `${Endpoints.PREMIUM_PRICE_IDS}?country_code=${encodeURIComponent(countryCode)}` : Endpoints.PREMIUM_PRICE_IDS; const response = await http.get(url); logger.debug('Price IDs fetched', response.body); return response.body; } catch (error) { logger.error('Price IDs fetch failed', error); throw error; } }; export const createCustomerPortalSession = async (): Promise => { try { const response = await http.post<{url: string}>(Endpoints.PREMIUM_CUSTOMER_PORTAL); logger.info('Customer portal session created'); return response.body.url; } catch (error) { logger.error('Customer portal session creation failed', error); throw error; } }; export const createCheckoutSession = async (priceId: string, isGift: boolean = false): Promise => { try { const url = isGift ? Endpoints.STRIPE_CHECKOUT_GIFT : Endpoints.STRIPE_CHECKOUT_SUBSCRIPTION; const response = await http.post<{url: string}>(url, {price_id: priceId}); logger.info('Checkout session created', {priceId, isGift}); return response.body.url; } catch (error) { logger.error('Checkout session creation failed', error); throw error; } }; export const cancelSubscriptionAtPeriodEnd = async (): Promise => { try { await http.post({url: Endpoints.PREMIUM_CANCEL_SUBSCRIPTION}); logger.info('Subscription set to cancel at period end'); } catch (error) { logger.error('Failed to cancel subscription at period end', error); throw error; } }; export const reactivateSubscription = async (): Promise => { try { await http.post({url: Endpoints.PREMIUM_REACTIVATE_SUBSCRIPTION}); logger.info('Subscription reactivated'); } catch (error) { logger.error('Failed to reactivate subscription', error); throw error; } }; export const rejoinVisionaryGuild = async (): Promise => { try { await http.post({url: Endpoints.PREMIUM_VISIONARY_REJOIN}); logger.info('Visionary guild rejoin requested'); } catch (error) { logger.error('Failed to rejoin Visionary guild', error); throw error; } }; export const rejoinOperatorGuild = async (): Promise => { try { await http.post({url: Endpoints.PREMIUM_OPERATOR_REJOIN}); logger.info('Operator guild rejoin requested'); } catch (error) { logger.error('Failed to rejoin Operator guild', error); throw error; } };