UNPKG

pssst

Version:

A CLI tool for sharing and discovering developer thoughts from around the world

202 lines (162 loc) 6.29 kB
const axios = require('axios'); const BOT_TOKEN = process.env.PSSST_BOT_TOKEN; const TARGET_REPO = 'yybmion/pssst'; function getLocalISOString() { const now = new Date(); const year = now.getFullYear(); const month = String(now.getMonth() + 1).padStart(2, '0'); const day = String(now.getDate()).padStart(2, '0'); const hours = String(now.getHours()).padStart(2, '0'); const minutes = String(now.getMinutes()).padStart(2, '0'); const seconds = String(now.getSeconds()).padStart(2, '0'); const milliseconds = String(now.getMilliseconds()).padStart(3, '0'); return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}.${milliseconds}Z`; } module.exports = async function handler(req, res) { res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Authorization'); if (req.method === 'OPTIONS') { return res.status(200).end(); } if (req.method === 'GET') { return res.status(200).json({ status: "PSSST API is working!", hasToken: !!BOT_TOKEN, timestamp: getLocalISOString(), environment: process.env.NODE_ENV || 'production' }); } if (req.method === 'POST') { try { const { message, isAnonymous = false, author = 'anonymous', timestamp } = req.body; if (!message || typeof message !== 'string') { return res.status(400).json({ success: false, error: 'Message is required and must be a string' }); } if (message.length > 200) { return res.status(400).json({ success: false, error: `Message too long (${message.length}/200 characters)` }); } if (!BOT_TOKEN) { return res.status(500).json({ success: false, error: 'Bot token not configured' }); } const github = axios.create({ baseURL: 'https://api.github.com', headers: { 'Authorization': `token ${BOT_TOKEN}`, 'Accept': 'application/vnd.github.v3+json', 'User-Agent': 'pssst-bot' } }); const lang = detectLanguage(message); const newMessage = { text: message, author: isAnonymous ? 'anonymous' : author, timestamp: timestamp || getLocalISOString(), lang: lang }; console.log('Creating PR for message:', newMessage); const result = await createPRWithBot(github, newMessage, isAnonymous); return res.status(200).json({ success: true, prUrl: result.prUrl, message: newMessage, language: lang }); } catch (error) { console.error('API Error:', error); return res.status(500).json({ success: false, error: `Failed to create PR: ${error.message}` }); } } return res.status(405).json({ error: 'Method not allowed' }); } function detectLanguage(text) { const hasKorean = /[ㄱ-ㅎ|ㅏ-ㅣ|가-힣]/.test(text); const hasChinese = /[\u4e00-\u9fff]/.test(text); const hasJapanese = /[\u3040-\u309f\u30a0-\u30ff]/.test(text); if (hasKorean) return 'ko'; if (hasChinese) return 'ch'; if (hasJapanese) return 'jp'; return 'en'; } async function createPRWithBot(github, newMessage, isAnonymous) { try { console.log('Getting main branch info...'); const mainBranchResponse = await github.get(`/repos/${TARGET_REPO}/git/refs/heads/main`); const mainSha = mainBranchResponse.data.object.sha; const branchName = `add-message-${Date.now()}`; console.log(`Creating branch: ${branchName}`); await github.post(`/repos/${TARGET_REPO}/git/refs`, { ref: `refs/heads/${branchName}`, sha: mainSha }); console.log('Updating files...'); await updateFileWithBot(github, `messages/${newMessage.lang}.json`, newMessage, branchName); await updateFileWithBot(github, 'messages/all.json', newMessage, branchName); const prTitle = isAnonymous ? `Add new ${newMessage.lang} anonymous message` : `Add new ${newMessage.lang} message by @${newMessage.author}`; const prBody = `## 🌍 New Developer Message **Message:** "${newMessage.text}" **Author:** ${newMessage.author} **Language:** ${newMessage.lang} **Mode:** ${isAnonymous ? 'Anonymous' : 'Public'} *This PR was created automatically by PSSST Bot*`; console.log('Creating PR...'); const prResponse = await github.post(`/repos/${TARGET_REPO}/pulls`, { title: prTitle, body: prBody, head: branchName, base: 'main' }); console.log('PR created successfully:', prResponse.data.html_url); return { prUrl: prResponse.data.html_url }; } catch (error) { console.error('GitHub API Error:', error.response?.data || error.message); throw error; } } async function updateFileWithBot(github, filePath, newMessage, branchName) { try { let fileData = { messages: [] }; let fileSha = null; try { const fileResponse = await github.get(`/repos/${TARGET_REPO}/contents/${filePath}`, { params: { ref: branchName } }); const content = Buffer.from(fileResponse.data.content, 'base64').toString(); fileData = JSON.parse(content); fileSha = fileResponse.data.sha; } catch (error) { console.log(`File ${filePath} not found, creating new file`); } fileData.messages.push(newMessage); const updatedContent = Buffer.from(JSON.stringify(fileData, null, 2)).toString('base64'); const updateData = { message: `Add message to ${filePath}`, content: updatedContent, branch: branchName }; if (fileSha) { updateData.sha = fileSha; } await github.put(`/repos/${TARGET_REPO}/contents/${filePath}`, updateData); console.log(`Updated ${filePath} successfully`); } catch (error) { console.error(`Failed to update ${filePath}:`, error.response?.data || error.message); throw new Error(`Failed to update ${filePath}: ${error.message}`); } }