fix: posimai_token(JWT)対応・ログインUI追加・pk_キーはフォールバックに
Made-with: Cursor
This commit is contained in:
parent
7d8297a243
commit
1337c280b0
72
index.html
72
index.html
|
|
@ -472,15 +472,21 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Posimai API Key -->
|
||||
<!-- 認証 / VOICEVOX -->
|
||||
<div style="margin-top:20px">
|
||||
<div class="settings-group-label">Posimai API Key</div>
|
||||
<p class="settings-field-label">
|
||||
設定すると VPS 経由でずんだもん音声が使えます(未設定時はブラウザ音声)。
|
||||
<div class="settings-group-label">アカウント</div>
|
||||
<p class="settings-field-label" id="authStatusLabel">
|
||||
ログインするとずんだもん音声・カスタムRSSが使えます。
|
||||
</p>
|
||||
<input class="settings-text-input" id="apiKeyInput" type="password"
|
||||
placeholder="posimai_api_key" autocomplete="off">
|
||||
<button class="settings-action-btn" id="apiKeySave">保存</button>
|
||||
<div id="authLoggedIn" style="display:none">
|
||||
<div id="authUserLine" style="font-size:13px;color:var(--accent);margin-bottom:8px"></div>
|
||||
<button class="settings-action-btn" id="authLogoutBtn" style="background:transparent;border:1px solid var(--border);color:var(--text2)">ログアウト</button>
|
||||
</div>
|
||||
<div id="authLoggedOut">
|
||||
<a class="settings-action-btn" id="authLoginBtn"
|
||||
style="display:inline-flex;align-items:center;gap:6px;text-decoration:none"
|
||||
href="#">ログインする</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
@ -562,6 +568,16 @@
|
|||
const FEED_API = 'https://posimai-feed.vercel.app/api/feed';
|
||||
const API_BASE = 'https://api.soar-enrich.com/brain/api';
|
||||
const TTS_API = API_BASE + '/tts';
|
||||
|
||||
// ── 認証ヘルパー ─────────────────────────────────────────────
|
||||
// JWT(posimai_token)を優先、なければ旧来の pk_ キーにフォールバック
|
||||
function getAuthToken() {
|
||||
return localStorage.getItem('posimai_token') || localStorage.getItem('posimai-brief-apikey') || '';
|
||||
}
|
||||
function isLoggedIn() { return !!localStorage.getItem('posimai_token'); }
|
||||
function getLoginUrl() {
|
||||
return 'https://posimai.soar-enrich.com/login?redirect=' + encodeURIComponent(location.href);
|
||||
}
|
||||
const DAYS_JP = ['日','月','火','水','木','金','土'];
|
||||
|
||||
// ── 状態 ─────────────────────────────────────────────────────
|
||||
|
|
@ -675,15 +691,15 @@ function preprocessText(t) {
|
|||
}
|
||||
|
||||
async function tryVoicevox(text) {
|
||||
const apiKey = localStorage.getItem('posimai-brief-apikey');
|
||||
if (!apiKey) return false;
|
||||
const token = getAuthToken();
|
||||
if (!token) return false;
|
||||
|
||||
const ctx = getAudioCtx();
|
||||
for (let attempt = 0; attempt < 4; attempt++) {
|
||||
if (attempt > 0) await new Promise(r => setTimeout(r, 2000 * attempt));
|
||||
const res = await fetch(TTS_API, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${apiKey}` },
|
||||
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` },
|
||||
body: JSON.stringify({ text: preprocessText(text), speaker: ttsSpeaker }),
|
||||
});
|
||||
if (res.status === 503) {
|
||||
|
|
@ -944,14 +960,30 @@ function initSpeakerBtns() {
|
|||
});
|
||||
}
|
||||
|
||||
// ── API キー保存 ──────────────────────────────────────────────
|
||||
document.getElementById('apiKeyInput').value = localStorage.getItem('posimai-brief-apikey') || '';
|
||||
document.getElementById('apiKeySave').addEventListener('click', () => {
|
||||
const v = document.getElementById('apiKeyInput').value.trim();
|
||||
localStorage.setItem('posimai-brief-apikey', v);
|
||||
if (typeof showToast === 'function') showToast('保存しました');
|
||||
// ── 認証 UI 初期化 ───────────────────────────────────────────
|
||||
function updateAuthUI() {
|
||||
const loggedIn = isLoggedIn();
|
||||
document.getElementById('authLoggedIn').style.display = loggedIn ? '' : 'none';
|
||||
document.getElementById('authLoggedOut').style.display = loggedIn ? 'none' : '';
|
||||
if (loggedIn) {
|
||||
try {
|
||||
const payload = JSON.parse(atob(localStorage.getItem('posimai_token').split('.')[1]));
|
||||
document.getElementById('authUserLine').textContent = 'ログイン中: ' + (payload.userId || '');
|
||||
} catch (_) {}
|
||||
}
|
||||
document.getElementById('authLoginBtn').href = getLoginUrl();
|
||||
// 音声バッジも更新
|
||||
updateVoiceBadge(!isLoggedIn() && !localStorage.getItem('posimai-brief-apikey'));
|
||||
}
|
||||
|
||||
document.getElementById('authLogoutBtn').addEventListener('click', () => {
|
||||
localStorage.removeItem('posimai_token');
|
||||
updateAuthUI();
|
||||
if (typeof showToast === 'function') showToast('ログアウトしました');
|
||||
});
|
||||
|
||||
updateAuthUI();
|
||||
|
||||
// ── 日付表示 ─────────────────────────────────────────────────
|
||||
function updateDate() {
|
||||
const now = new Date();
|
||||
|
|
@ -967,13 +999,13 @@ async function loadFeed() {
|
|||
document.getElementById('briefList').innerHTML = '';
|
||||
|
||||
try {
|
||||
const apiKey = localStorage.getItem('posimai-brief-apikey');
|
||||
const token = getAuthToken();
|
||||
let res;
|
||||
if (apiKey) {
|
||||
if (token) {
|
||||
let customFeeds = [];
|
||||
try {
|
||||
const mediaRes = await fetch(API_BASE + '/feed/media', {
|
||||
headers: { 'Authorization': `Bearer ${apiKey}` }
|
||||
headers: { 'Authorization': `Bearer ${token}` }
|
||||
});
|
||||
if (mediaRes.ok) {
|
||||
const medias = await mediaRes.json();
|
||||
|
|
@ -994,7 +1026,7 @@ async function loadFeed() {
|
|||
res = await fetch(FEED_API, {
|
||||
method: 'POST',
|
||||
cache: 'no-store',
|
||||
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${apiKey}` },
|
||||
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` },
|
||||
body: JSON.stringify({ customFeeds }),
|
||||
});
|
||||
} catch (_) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue