← 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
}