MCPcopy Create free account
hub / github.com/adcontextprotocol/adcp / createPortraitRouter

Function createPortraitRouter

server/src/routes/portraits.ts:165–314  ·  view source on GitHub ↗
(config: PortraitRoutesConfig)

Source from the content-addressed store, hash-verified

163// =============================================================================
164
165export function createPortraitRouter(config: PortraitRoutesConfig): Router {
166 const { orgDb, memberDb, invalidateMemberContextCache } = config;
167 const router = Router();
168
169 // GET / — get current portrait metadata
170 router.get('/', requireAuth, async (req, res) => {
171 try {
172 const userId = resolveUserId(req);
173 if (!userId) {
174 return res.status(401).json({ error: 'Not authenticated' });
175 }
176
177 const portrait = await portraitDb.getActivePortrait(userId);
178 const pending = await portraitDb.getLatestGenerated(userId);
179 const monthlyCount = await portraitDb.countMonthlyGenerations(userId);
180 const canGenerate = await isPaidMember(req, orgDb, memberDb);
181
182 res.json({
183 portrait: portrait || null,
184 pending: pending || null,
185 generationsThisMonth: monthlyCount,
186 maxMonthlyGenerations: MAX_MONTHLY_GENERATIONS,
187 canGenerate,
188 vibeOptions: Object.keys(VIBE_OPTIONS),
189 });
190 } catch (err) {
191 logger.error({ err }, 'Failed to get portrait');
192 res.status(500).json({ error: 'Failed to load portrait' });
193 }
194 });
195
196 // POST /generate — upload photo + vibe, generate portrait
197 router.post('/generate', requireAuth, upload.single('photo'), async (req, res) => {
198 try {
199 const userId = resolveUserId(req);
200 if (!userId) {
201 return res.status(401).json({ error: 'Not authenticated' });
202 }
203
204 if (!await isPaidMember(req, orgDb, memberDb)) {
205 return res.status(402).json({ error: 'Active subscription required for portrait generation' });
206 }
207
208 const monthlyCount = await portraitDb.countMonthlyGenerations(userId);
209 if (monthlyCount >= MAX_MONTHLY_GENERATIONS) {
210 return res.status(429).json({
211 error: 'Monthly generation limit reached',
212 generationsThisMonth: monthlyCount,
213 maxMonthlyGenerations: MAX_MONTHLY_GENERATIONS,
214 });
215 }
216
217 const vibe = (req.body.vibe as string) || 'casual';
218 const photoBuffer = req.file?.buffer;
219 const photoMimeType = req.file?.mimetype;
220
221 const result = await generatePortrait({
222 photoBuffer,

Callers 1

setupRoutesMethod · 0.85

Calls 7

resolveUserIdFunction · 0.85
isPaidMemberFunction · 0.85
generatePortraitFunction · 0.85
singleMethod · 0.80
deleteMethod · 0.80
getMethod · 0.45

Tested by

no test coverage detected