/** * Posimai Tech Events - /api/events * * GET /api/events?q=keyword -> Connpass APIを呼び出して整形したイベント一覧を返す。 * * Connpass API: https://connpass.com/about/api/ */ export default async function handler(req, res) { res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); res.setHeader('Cache-Control', 's-maxage=1800, stale-while-revalidate=3600'); if (req.method === 'OPTIONS') { return res.status(200).end(); } if (req.method !== 'GET') { return res.status(405).json({ error: 'Method not allowed' }); } try { const { q } = req.query; // Search either specific query from UI or broad default queries for tech events const fetchKeyword = q && q.trim().length > 0 ? q.trim() : 'IT,エンジニア,デザイン,Web,AI,アプリ'; const urlObj = new URL('https://connpass.com/api/v1/event/'); // ConnpassのOR検索仕様に合わせて keyword_or を使用する urlObj.searchParams.append('keyword_or', fetchKeyword); urlObj.searchParams.append('order', '2'); // 開催降順(新着イベント) urlObj.searchParams.append('count', '50'); // Connpass APIはUser-Agentが必須 const response = await fetch(urlObj.toString(), { headers: { 'User-Agent': 'PosimaiTechEvents/1.0 (https://posimai-tech-events.vercel.app)' } }); if (!response.ok) { console.error('Connpass API Error', await response.text()); res.status(502).json({ error: 'Failed to fetch events from Connpass' }); return; } const data = await response.json(); // Map to Posimai Events structure const events = (data.events || []).map(ev => { const startStr = ev.started_at || ''; const endStr = ev.ended_at || ''; const startDate = startStr.slice(0, 10); const startTime = startStr.slice(11, 16); const endDate = endStr.slice(0, 10); const endTime = endStr.slice(11, 16); let location = ev.place || 'オンライン'; if (!ev.address && !ev.place) { if (ev.event_url && ev.event_type === 'online') location = 'オンライン開催'; else location = '会場未定 / オンライン'; } return { id: String(ev.event_id), title: ev.title, startDate: startDate, startTime: startTime, endDate: endDate, endTime: endTime, location: location, address: ev.address || '', description: ev.catch || '詳細説明はリンク先をご覧ください。', category: ev.series ? ev.series.title : 'IT/テック', url: ev.event_url, source: 'Connpass', // To be enhanced: derive tags based on title/description interestTags: [], audienceTags: [] }; }); return res.status(200).json({ events: events, updatedAt: new Date().toISOString(), source: 'connpass' }); } catch (e) { console.error('API /events error:', e); return res.status(500).json({ error: 'Internal Server Error' }); } }