feat: social video uploads + hero page video + TikTok content
Hero page:
- Replace GIF with squaremcp-hero-loop.mp4 (autoplay, muted, loop)
- Update styles, scripts, tests, Dockerfile, baselines
- Deployed and verified
Social video uploads:
- Twitter/X: uploadVideoAndTweet via v1.1 media/upload + v2 tweets
- Facebook: createVideoPost via Graph API /{pageId}/videos
- Instagram: createReel via Graph API (container → poll → publish)
- TikTok: REST endpoints + OpenAPI schema for video upload
Marketing:
- TikTok content prompts, scripts, and posting schedule
Note: Remotion not mentioned in any user-facing content
This commit is contained in:
121
src/index.ts
121
src/index.ts
@@ -935,6 +935,17 @@ app.post('/api/instagram/post', requireAuth, async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/instagram/reel', requireAuth, async (req, res) => {
|
||||
const { video_url, caption, account } = req.body as Record<string, unknown>;
|
||||
if (!video_url) { res.status(400).json({ error: 'video_url is required' }); return; }
|
||||
try {
|
||||
const result = await handleToolCall('instagram_create_reel', { video_url, caption, account });
|
||||
res.json(parseToolResult(result));
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: (err as Error).message });
|
||||
}
|
||||
});
|
||||
|
||||
// ── Twitter/X REST endpoints ────────────────────────────────────
|
||||
app.get('/api/twitter/search', requireAuth, async (req, res) => {
|
||||
const query = req.query.query as string | undefined;
|
||||
@@ -985,6 +996,116 @@ app.post('/api/twitter/tweet', requireAuth, async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/twitter/video', requireAuth, async (req, res) => {
|
||||
const { video_url, text, account } = req.body as Record<string, unknown>;
|
||||
if (!video_url || !text) { res.status(400).json({ error: 'video_url and text are required' }); return; }
|
||||
try {
|
||||
const result = await handleToolCall('twitter_upload_video', { video_url, text, account });
|
||||
res.json(parseToolResult(result));
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: (err as Error).message });
|
||||
}
|
||||
});
|
||||
|
||||
// ── Facebook REST endpoints ─────────────────────────────────────
|
||||
app.get('/api/facebook/page', requireAuth, async (req, res) => {
|
||||
const account = req.query.account as string | undefined;
|
||||
try {
|
||||
const result = await handleToolCall('facebook_get_page', { account });
|
||||
res.json(parseToolResult(result));
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: (err as Error).message });
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/api/facebook/posts', requireAuth, async (req, res) => {
|
||||
const limit = req.query.limit ? parseInt(req.query.limit as string, 10) : undefined;
|
||||
const account = req.query.account as string | undefined;
|
||||
try {
|
||||
const result = await handleToolCall('facebook_get_posts', { limit, account });
|
||||
res.json(parseToolResult(result));
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: (err as Error).message });
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/facebook/post', requireAuth, async (req, res) => {
|
||||
const { message, link, account } = req.body as Record<string, unknown>;
|
||||
if (!message) { res.status(400).json({ error: 'message is required' }); return; }
|
||||
try {
|
||||
const result = await handleToolCall('facebook_create_post', { message, link, account });
|
||||
res.json(parseToolResult(result));
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: (err as Error).message });
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/facebook/photo', requireAuth, async (req, res) => {
|
||||
const { image_url, caption, account } = req.body as Record<string, unknown>;
|
||||
if (!image_url) { res.status(400).json({ error: 'image_url is required' }); return; }
|
||||
try {
|
||||
const result = await handleToolCall('facebook_create_photo_post', { image_url, caption, account });
|
||||
res.json(parseToolResult(result));
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: (err as Error).message });
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/facebook/video', requireAuth, async (req, res) => {
|
||||
const { video_url, description, account } = req.body as Record<string, unknown>;
|
||||
if (!video_url) { res.status(400).json({ error: 'video_url is required' }); return; }
|
||||
try {
|
||||
const result = await handleToolCall('facebook_create_video_post', { video_url, description, account });
|
||||
res.json(parseToolResult(result));
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: (err as Error).message });
|
||||
}
|
||||
});
|
||||
|
||||
// ── TikTok REST endpoints ───────────────────────────────────────
|
||||
app.get('/api/tiktok/profile', requireAuth, async (req, res) => {
|
||||
const account = req.query.account as string | undefined;
|
||||
try {
|
||||
const result = await handleToolCall('tiktok_get_profile', { account });
|
||||
res.json(parseToolResult(result));
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: (err as Error).message });
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/api/tiktok/videos', requireAuth, async (req, res) => {
|
||||
const max_count = req.query.max_count ? parseInt(req.query.max_count as string, 10) : undefined;
|
||||
const account = req.query.account as string | undefined;
|
||||
try {
|
||||
const result = await handleToolCall('tiktok_get_videos', { max_count, account });
|
||||
res.json(parseToolResult(result));
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: (err as Error).message });
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/tiktok/video', requireAuth, async (req, res) => {
|
||||
const { video_url, title, description, account } = req.body as Record<string, unknown>;
|
||||
if (!video_url) { res.status(400).json({ error: 'video_url is required' }); return; }
|
||||
try {
|
||||
const result = await handleToolCall('tiktok_create_video', { video_url, title, description, account });
|
||||
res.json(parseToolResult(result));
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: (err as Error).message });
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/tiktok/video/status', requireAuth, async (req, res) => {
|
||||
const { publish_id, account } = req.body as Record<string, unknown>;
|
||||
if (!publish_id) { res.status(400).json({ error: 'publish_id is required' }); return; }
|
||||
try {
|
||||
const result = await handleToolCall('tiktok_get_video_status', { publish_id, account });
|
||||
res.json(parseToolResult(result));
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: (err as Error).message });
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/pilot-request', async (req, res) => {
|
||||
const origin = req.get('origin');
|
||||
if (origin && !SQUAREMCP_ALLOWED_ORIGINS.has(origin)) {
|
||||
|
||||
Reference in New Issue
Block a user