← back to Dear Bubbe Nextjs

lib/pricing-wrapper.ts

189 lines

/**
 * Pricing Wrapper for Existing Chat
 * 
 * This shows how to add pricing to your EXISTING chat endpoint
 * without modifying the original code at all
 */

import { checkChatFeatures } from './feature-middleware';
import { getUserSession } from './user-session';
import { FeatureKey } from './bubbe-pricing';

/**
 * Wrap any existing chat response with feature checking
 * This can be added to your existing chat handler WITHOUT modifying it
 * 
 * Example usage in your existing /api/chat/route.ts:
 * 
 * // Your existing code stays the same
 * const bubbeResponse = await generateBubbeResponse(message);
 * 
 * // Just wrap the response before sending
 * const finalResponse = wrapWithPricing(bubbeResponse, message, userId);
 */
export function wrapWithPricing(
  originalResponse: string,
  userMessage: string,
  userId: string
): {
  response: string;
  showUpgrade: boolean;
  blockedFeatures?: FeatureKey[];
  userPlan: string;
} {
  // Get user's current plan
  const session = getUserSession(userId);
  
  // Check if they're trying to use premium features
  const featureCheck = checkChatFeatures(userMessage, userId);
  
  // If no restrictions, return original response unchanged
  if (!featureCheck.hasRestriction) {
    return {
      response: originalResponse,
      showUpgrade: false,
      userPlan: session.plan
    };
  }
  
  // User tried to use premium features - modify response
  const modifiedResponse = `${featureCheck.bubbeResponse}

But let me tell you what I CAN do for free, you cheapskate:

${originalResponse}`;
  
  return {
    response: modifiedResponse,
    showUpgrade: true,
    blockedFeatures: featureCheck.blockedFeatures,
    userPlan: session.plan
  };
}

/**
 * Simple function to add to ANY endpoint to check feature access
 * Returns true if allowed, or sends Bubbe rejection and returns false
 * 
 * Example usage:
 * 
 * if (!checkFeatureOrRespond('voice_notes', userId, res)) {
 *   return; // Already sent response
 * }
 * // Continue with voice generation...
 */
export function checkFeatureOrRespond(
  feature: FeatureKey,
  userId: string,
  res: any
): boolean {
  const session = getUserSession(userId);
  const access = checkChatFeatures(feature, userId);
  
  if (!access.hasRestriction) {
    return true; // Feature allowed
  }
  
  // Feature blocked - send Bubbe response
  res.status(402).json({
    error: 'feature_locked',
    message: access.bubbeResponse,
    requiredFeature: feature,
    currentPlan: session.plan,
    showUpgrade: true
  });
  
  return false; // Feature not allowed, response already sent
}

/**
 * Detect if message seems to be asking about pricing/plans
 * Useful for providing pricing info proactively
 */
export function isAskingAboutPricing(message: string): boolean {
  const lowerMessage = message.toLowerCase();
  
  const pricingKeywords = [
    'how much',
    'cost',
    'price',
    'pricing',
    'subscription',
    'plan',
    'upgrade',
    'premium',
    'free',
    'paid',
    'dollar',
    'month',
    'features'
  ];
  
  return pricingKeywords.some(keyword => lowerMessage.includes(keyword));
}

/**
 * Generate a Bubbe-style pricing pitch
 */
export function getBubbePricingPitch(): string {
  const pitches = [
    "Listen bubbeleh, I got FOUR plans! FREE (basic sass), PLUS for $18 (daily nagging), MAX for $36 (my voice!), and SUPER MAX for $54 (I know EVERYTHING about your neighborhood)!",
    
    "So you're cheap? Fine! Basic is free. Want reminders? $18. Want my voice? $36. Want me to know EVERYTHING about your local area? $54 for Super Max - I'll be your neighborhood yenta!",
    
    "Oy, the pricing! FREE: guilt. $18 PLUS: MORE guilt. $36 MAX: guilt in my VOICE. $54 SUPER MAX: local news, sports, weather - I'll know your neighborhood better than YOU!",
    
    "Four plans, nu? FREE (you get what you pay for), $18 PLUS (I remind you to eat), $36 MAX (voice notes!), $54 SUPER MAX (I'm your local know-it-all)!",
    
    "What, you want the menu? FREE: Basic. $18: Daily reminders. $36: Voice notes. $54: I tell you EVERYTHING about your neighborhood - the weather, the news, whose team lost AGAIN!"
  ];
  
  return pitches[Math.floor(Math.random() * pitches.length)];
}

/**
 * Detect if message is asking about local content (Super Max feature)
 */
export function isAskingAboutLocal(message: string): boolean {
  const lowerMessage = message.toLowerCase();
  
  const localKeywords = [
    'local news',
    'my neighborhood',
    'my area',
    'my city',
    'local weather',
    'weather here',
    'local sports',
    'my team',
    'home team',
    'around here',
    'near me',
    'in my area',
    'neighborhood'
  ];
  
  return localKeywords.some(keyword => lowerMessage.includes(keyword));
}

/**
 * Example: How to modify your EXISTING chat endpoint
 * 
 * This is just an example - don't actually use this code
 * Instead, add these 3 lines to your existing handler:
 */
export async function exampleExistingChatHandler(req: any, res: any) {
  const { message, userId } = req.body;
  
  // === YOUR EXISTING CODE STAYS THE SAME ===
  // const bubbeResponse = await callClaude(message);
  // ... all your existing logic ...
  
  // === ADD THESE 3 LINES ===
  // import { wrapWithPricing } from '@/lib/pricing-wrapper';
  // const wrapped = wrapWithPricing(bubbeResponse, message, userId);
  // return res.json(wrapped); // Instead of res.json({ response: bubbeResponse })
  
  // That's it! Your existing code continues to work,
  // but now with pricing awareness
}