From 324d892b2895de2c213daba8a76811c6bdfba327 Mon Sep 17 00:00:00 2001 From: posimai Date: Wed, 22 Apr 2026 10:08:18 +0900 Subject: [PATCH] =?UTF-8?q?fix(together):=20x.com=20=E3=83=9C=E3=83=83?= =?UTF-8?q?=E3=83=88=E6=8B=92=E5=90=A6=E6=A4=9C=E5=87=BA=E3=83=BBGemini=20?= =?UTF-8?q?JSON=E3=82=B3=E3=83=BC=E3=83=89=E3=83=96=E3=83=AD=E3=83=83?= =?UTF-8?q?=E3=82=AF=E9=99=A4=E5=8E=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server.js | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/server.js b/server.js index bf1c803b..380abc0d 100644 --- a/server.js +++ b/server.js @@ -2619,11 +2619,30 @@ ${excerpt} const titleMatch = fullContent.match(/^Title:\s*(.+)/m); const jinaTitle = titleMatch ? titleMatch[1].trim().slice(0, 300) : null; + // x.com でタイトルがドメイン名のみ = ボット拒否ページ → AI 要約をスキップして skipped で保存 + try { + const u = new URL(url); + const host = u.hostname.replace('www.', ''); + if (/^(x\.com|twitter\.com)$/.test(host) && (!jinaTitle || jinaTitle === host)) { + await pool.query( + `UPDATE together_shares SET full_content=$1, archive_status='skipped' WHERE id=$2`, + [fullContent, shareId] + ); + return; + } + } catch (_) {} + await pool.query( `UPDATE together_shares SET full_content=$1, title=COALESCE(title, $2) WHERE id=$3`, [fullContent, jinaTitle, shareId] ); + function parseGeminiJson(raw) { + // Gemini がコードブロックで返す場合に対応 + const cleaned = raw.replace(/^```(?:json)?\s*/i, '').replace(/\s*```$/, '').trim(); + return JSON.parse(cleaned); + } + let summary = null; let tags = []; if (togetherGenAI && fullContent) { @@ -2638,7 +2657,7 @@ ${excerpt} const result = await Promise.race([model.generateContent(prompt), timeoutP]); const raw = result.response.text().trim(); try { - const parsed = JSON.parse(raw); + const parsed = parseGeminiJson(raw); summary = (parsed.summary || '').slice(0, 300); tags = Array.isArray(parsed.tags) ? parsed.tags.slice(0, 4).map(t => String(t).slice(0, 20)) : []; } catch { @@ -2647,9 +2666,6 @@ ${excerpt} break; } catch (aiErr) { console.error(`[together archive AI] ${modelName} share=${shareId}`, aiErr.message); - if (modelName === modelsToTry[modelsToTry.length - 1]) { - // 全モデル失敗: Jina 本文は保存済みなので Reader は使える状態で done にする - } } } } @@ -2697,7 +2713,7 @@ ${excerpt} const result = await Promise.race([model.generateContent(prompt), timeoutP]); const raw = result.response.text().trim(); let summary = null, tags = []; - try { const p = JSON.parse(raw); summary = (p.summary || '').slice(0, 300); tags = Array.isArray(p.tags) ? p.tags.slice(0, 4).map(t => String(t).slice(0, 20)) : []; } + try { const cleaned = raw.replace(/^```(?:json)?\s*/i,'').replace(/\s*```$/,'').trim(); const p = JSON.parse(cleaned); summary = (p.summary || '').slice(0, 300); tags = Array.isArray(p.tags) ? p.tags.slice(0, 4).map(t => String(t).slice(0, 20)) : []; } catch { summary = raw.slice(0, 300); } await pool.query(`UPDATE together_shares SET summary=$1, tags=$2, archive_status='done' WHERE id=$3`, [summary, tags, shareId]); rearchiveDone = true;