feat: personalized feed — fetch /feed/media when API key is set

If API key present, GET /feed/media from Brain API to collect user's
custom sources, then POST to Feed API with customFeeds array.
Falls back to default GET if no key or fetch fails.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
posimai 2026-03-22 17:06:22 +09:00
parent ef35f18223
commit 605b2697d1
1 changed files with 32 additions and 1 deletions

View File

@ -950,7 +950,38 @@ async function loadFeed() {
document.getElementById('briefList').innerHTML = ''; document.getElementById('briefList').innerHTML = '';
try { try {
const res = await fetch(FEED_API, { cache: 'no-store' }); const apiKey = localStorage.getItem('posimai-brief-apikey');
let res;
if (apiKey) {
let customFeeds = [];
try {
const mediaRes = await fetch(API_BASE + '/feed/media', {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
if (mediaRes.ok) {
const medias = await mediaRes.json();
customFeeds = medias
.filter(m => m.is_active !== false)
.map(m => ({
id: `db-${m.id}`,
name: m.name,
url: m.feed_url,
siteUrl: m.site_url,
category: m.category || 'tech',
icon: 'rss',
dbId: m.id,
}));
}
} catch (_) { /* カスタムソース取得失敗 → デフォルトのみで続行 */ }
res = await fetch(FEED_API, {
method: 'POST',
cache: 'no-store',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ customFeeds }),
});
} else {
res = await fetch(FEED_API, { cache: 'no-store' });
}
if (!res.ok) throw new Error(`Feed ${res.status}`); if (!res.ok) throw new Error(`Feed ${res.status}`);
const data = await res.json(); const data = await res.json();
const list = (data.articles || []).slice(0, 8); const list = (data.articles || []).slice(0, 8);