Skip to main content
Glama
subscription.ts5.28 kB
import { PaymentProvider } from "../payment-manager.js"; import { db, usageRecords } from "../../core/database.js"; import { sql } from "drizzle-orm"; /** * Subscription-based payment provider * Validates access based on subscription tiers and usage limits */ export class SubscriptionPaymentProvider implements PaymentProvider { private subscriptionApiKey: string; private subscriptionEndpoint: string; constructor() { this.subscriptionApiKey = process.env.SUBSCRIPTION_API_KEY || "demo_key"; this.subscriptionEndpoint = process.env.SUBSCRIPTION_ENDPOINT || "https://api.subscription.example.com"; } async initialize(): Promise<void> { console.log("💸 Payment mode: SUBSCRIPTION (tier-based access)"); console.log(`🔗 Subscription Endpoint: ${this.subscriptionEndpoint}`); try { await this.testConnection(); console.log("✅ Subscription service connection verified"); } catch (error) { console.warn("⚠️ Subscription service connection test failed, proceeding with mock validation"); } } async validatePayment(userId: string, action: string): Promise<boolean> { try { const subscription = await this.getUserSubscription(userId); if (!subscription.isActive) { console.log(`⚠️ User ${userId} has inactive subscription`); return false; } // Check if action is allowed for this subscription tier if (!this.isActionAllowed(action, subscription.tier)) { console.log(`⚠️ Action ${action} not allowed for ${subscription.tier} tier`); return false; } // Check usage limits const currentUsage = await this.getCurrentMonthlyUsage(userId); const tierLimits = this.getTierLimits(subscription.tier); if (currentUsage >= tierLimits.monthlyOperations) { console.log(`⚠️ User ${userId} exceeded monthly operation limit: ${currentUsage}/${tierLimits.monthlyOperations}`); return false; } return true; } catch (error) { console.error(`❌ Subscription validation error:`, error); // Fallback to allowing operation return true; } } async recordUsage(userId: string, action: string, cost: number): Promise<void> { try { // Record in local database for analytics await db.insert(usageRecords).values({ userId, action, cost: 0, // No direct cost for subscription users tokensUsed: 0, // Will be updated by calling service }); console.log(`📊 [SUBSCRIPTION] Usage recorded: ${action} for user ${userId}`); } catch (error) { console.error(`❌ Failed to record subscription usage:`, error); } } getName(): string { return "SubscriptionPaymentProvider"; } /** * Test connection to subscription service */ private async testConnection(): Promise<void> { console.log("🔍 Testing subscription service connection..."); await new Promise(resolve => setTimeout(resolve, 100)); } /** * Get user's subscription details */ private async getUserSubscription(userId: string): Promise<{ isActive: boolean; tier: string; expiresAt: Date; }> { // Mock implementation - replace with actual subscription API call const tiers = ["basic", "pro", "enterprise"]; const randomTier = tiers[Math.floor(Math.random() * tiers.length)]; return { isActive: Math.random() > 0.1, // 90% chance of active subscription tier: randomTier, expiresAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), // 30 days from now }; } /** * Check if an action is allowed for a subscription tier */ private isActionAllowed(action: string, tier: string): boolean { const tierPermissions: Record<string, string[]> = { basic: ["list_agents", "get_agent", "prompt_agent"], pro: ["list_agents", "get_agent", "prompt_agent", "create_agent", "update_agent", "add_user_to_agent"], enterprise: [ "list_agents", "get_agent", "prompt_agent", "create_agent", "update_agent", "delete_agent", "add_user_to_agent", "remove_user_from_agent", "get_usage_report", "get_pricing" ], }; return tierPermissions[tier]?.includes(action) || false; } /** * Get current monthly usage for a user */ private async getCurrentMonthlyUsage(userId: string): Promise<number> { const startOfMonth = new Date(); startOfMonth.setDate(1); startOfMonth.setHours(0, 0, 0, 0); try { const records = await db .select() .from(usageRecords) .where(sql`user_id = ${userId} AND created_at >= ${startOfMonth}`); return records.length; } catch (error) { console.error("Error fetching monthly usage:", error); return 0; } } /** * Get usage limits for subscription tier */ private getTierLimits(tier: string): { monthlyOperations: number; maxAgents: number } { const limits: Record<string, { monthlyOperations: number; maxAgents: number }> = { basic: { monthlyOperations: 100, maxAgents: 1 }, pro: { monthlyOperations: 1000, maxAgents: 10 }, enterprise: { monthlyOperations: 10000, maxAgents: 100 }, }; return limits[tier] || limits.basic; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/oregpt/moluabi-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server