diff --git a/server.js b/server.js index af534b59..6f3bbbdb 100644 --- a/server.js +++ b/server.js @@ -2000,6 +2000,12 @@ ${excerpt} if (JSON.stringify(contents).length > 60000) { return res.status(400).json({ error: 'contents too large' }); } + const VALID_ROLES = new Set(['user', 'model']); + for (const item of contents) { + if (!VALID_ROLES.has(item?.role)) { + return res.status(400).json({ error: 'invalid role in contents' }); + } + } try { const modelOpts = { model: 'gemini-2.5-flash' }; if (systemPrompt && typeof systemPrompt === 'string') { @@ -2008,7 +2014,7 @@ ${excerpt} const model = genAI.getGenerativeModel(modelOpts); const generationConfig = { maxOutputTokens: Math.min(config.maxOutputTokens || 500, 1000), - temperature: config.temperature ?? 0.5 + temperature: Math.max(0, Math.min(config.temperature ?? 0.5, 2)) }; const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 15000) @@ -2782,6 +2788,29 @@ ${excerpt} } }); + // PUT /together/members/rename — 表示名変更 + r.put('/together/members/rename', async (req, res) => { + const { group_id, old_username, new_username } = req.body || {}; + const trimmed = normalizeTogetherUsername(new_username); + if (!group_id || !old_username || !trimmed) return res.status(400).json({ error: 'group_id, old_username, new_username は必須です' }); + if (trimmed.length > 30) return res.status(400).json({ error: '名前は30文字以内にしてください' }); + const jwtUserId = getTogetherJwtUserId(req); + try { + if (!(await togetherEnsureMember(pool, res, group_id, old_username, jwtUserId))) return; + const conflict = await pool.query( + 'SELECT 1 FROM together_members WHERE group_id=$1 AND username=$2', + [group_id, trimmed] + ); + if (conflict.rows.length > 0) return res.status(409).json({ error: '同じ名前のメンバーが既にいます' }); + await pool.query('UPDATE together_members SET username=$1 WHERE group_id=$2 AND username=$3', [trimmed, group_id, old_username]); + await pool.query('UPDATE together_shares SET shared_by=$1 WHERE group_id=$2 AND shared_by=$3', [trimmed, group_id, old_username]); + res.json({ ok: true }); + } catch (e) { + console.error('[together/rename]', e.message); + res.status(500).json({ error: 'Internal server error' }); + } + }); + // DELETE /together/share/:id — 自分の投稿を削除 r.delete('/together/share/:id', async (req, res) => { const { username } = req.body || {};