Skip to main content
Glama
kevin-weitgenant

LinkedIn-Posts-Hunter-MCP-Server

api-handlers.ts6.51 kB
import fs from 'fs'; import path from 'path'; import { Request, Response } from 'express'; import { getAllPosts, deletePostById, updatePost, getPostById, updateAppliedStatus, updateSavedStatus } from '../../db/operations.js'; import { getScreenshotsPath } from '../../utils/paths.js'; import { getFilterState, updateFilterState, resetFilterState, type FilterState } from '../../utils/filter-state.js'; import type { DbPost } from '../../db/operations.js'; /** * GET /api/posts - Get all posts from database */ export async function handleGetAllPosts(req: Request, res: Response): Promise<void> { try { const posts = await getAllPosts(); res.json(posts); } catch (error) { res.status(500).json({ error: 'Failed to load posts from database' }); } } /** * GET /api/posts/:id - Get single post by ID */ export async function handleGetSinglePost(req: Request, res: Response): Promise<void> { try { const id = parseInt(req.params.id); if (isNaN(id)) { res.status(400).json({ error: 'Invalid post ID' }); return; } const post = await getPostById(id); if (!post) { res.status(404).json({ error: 'Post not found' }); return; } res.json(post); } catch (error) { res.status(500).json({ error: 'Failed to load post' }); } } /** * POST /api/posts/bulk-update - Update multiple posts */ export async function handleBulkUpdatePosts(req: Request, res: Response): Promise<void> { try { const posts: DbPost[] = req.body; let updatedCount = 0; for (const post of posts) { if (await updatePost(post)) { updatedCount++; } } res.json({ message: `Successfully updated ${updatedCount} post(s)`, updated: updatedCount }); } catch (error) { const message = error instanceof Error ? error.message : 'Failed to update posts'; res.status(500).json({ error: message }); } } /** * DELETE /api/posts/:id - Delete a post by ID */ export async function handleDeletePost(req: Request, res: Response): Promise<void> { try { const id = parseInt(req.params.id); if (isNaN(id)) { res.status(400).json({ error: 'Invalid post ID' }); return; } const deleted = await deletePostById(id); if (deleted) { res.json({ message: 'Post deleted successfully' }); } else { res.status(404).json({ error: 'Post not found' }); } } catch (error) { res.status(500).json({ error: 'Failed to delete post' }); } } /** * PATCH /api/posts/:id/applied - Update applied status for a post */ export async function handleUpdateAppliedStatus(req: Request, res: Response): Promise<void> { try { const id = parseInt(req.params.id); if (isNaN(id)) { res.status(400).json({ error: 'Invalid post ID' }); return; } const { applied } = req.body; if (applied === undefined) { res.status(400).json({ error: 'Missing applied status in request body' }); return; } const updated = await updateAppliedStatus(id, applied); if (updated) { res.json({ success: true, applied, message: `Post marked as ${applied ? 'applied' : 'not applied'}` }); } else { res.status(404).json({ error: 'Post not found' }); } } catch (error) { res.status(500).json({ error: 'Failed to update applied status' }); } } /** * GET /api/screenshots/:filename - Serve screenshot images */ export function handleGetScreenshot(req: Request, res: Response): void { try { const filename = decodeURIComponent(req.params.filename); const screenshotsDir = getScreenshotsPath(); const filePath = path.join(screenshotsDir, filename); // Security check: ensure the file is within the screenshots directory const normalizedFilePath = path.normalize(filePath); const normalizedScreenshotsDir = path.normalize(screenshotsDir); if (!normalizedFilePath.startsWith(normalizedScreenshotsDir)) { res.status(403).send('Access denied'); return; } if (!fs.existsSync(filePath)) { res.status(404).send('Screenshot not found'); return; } // Serve the image res.sendFile(filePath); } catch (error) { res.status(500).send('Failed to load screenshot'); } } /** * GET /api/filter-state - Get current filter state */ export function handleGetFilterState(req: Request, res: Response): void { try { const state = getFilterState(); res.json(state); } catch (error) { res.status(500).json({ error: 'Failed to load filter state' }); } } /** * PUT /api/filter-state - Update filter state (partial or full) */ export function handleUpdateFilterState(req: Request, res: Response): void { try { const updates: Partial<FilterState> = req.body; // Validate that at least one field is being updated if (Object.keys(updates).length === 0) { res.status(400).json({ error: 'No updates provided' }); return; } const newState = updateFilterState(updates); res.json(newState); } catch (error) { const message = error instanceof Error ? error.message : 'Failed to update filter state'; res.status(400).json({ error: message }); } } /** * DELETE /api/filter-state - Reset filter state to defaults */ export function handleResetFilterState(req: Request, res: Response): void { try { const defaultState = resetFilterState(); res.json(defaultState); } catch (error) { res.status(500).json({ error: 'Failed to reset filter state' }); } } /** * PATCH /api/posts/:id/saved - Update saved status for a post */ export async function handleUpdateSavedStatus(req: Request, res: Response): Promise<void> { try { const id = parseInt(req.params.id); if (isNaN(id)) { res.status(400).json({ error: 'Invalid post ID' }); return; } const { saved } = req.body; if (saved === undefined) { res.status(400).json({ error: 'Missing saved status in request body' }); return; } const updated = await updateSavedStatus(id, saved); if (updated) { res.json({ success: true, saved, message: `Post marked as ${saved ? 'saved' : 'not saved'}` }); } else { res.status(404).json({ error: 'Post not found' }); } } catch (error) { res.status(500).json({ error: 'Failed to update saved status' }); } }

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/kevin-weitgenant/LinkedIn-Posts-Hunter-MCP-Server'

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