eight-hourr/extension/popup.js

105 lines
3.0 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const AUTH_KEY = "pts_authdata";
const statusEl = document.getElementById("status");
const backendInput = document.getElementById("backendUrl");
chrome.storage.local.get(["backendUrl"], (data) => {
if (data.backendUrl) backendInput.value = data.backendUrl;
});
function isPtsUrl(url) {
return !!url && url.includes("tw-timesheet.supermicro.com");
}
async function getActiveTab() {
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
return tab;
}
function readAuthViaMessage(tabId) {
return new Promise((resolve) => {
chrome.tabs.sendMessage(tabId, { type: "GET_PTS_AUTH" }, (response) => {
if (chrome.runtime.lastError) {
resolve({
ok: false,
error: chrome.runtime.lastError.message,
});
return;
}
resolve(response || { ok: false, error: "No response from content script" });
});
});
}
async function readAuthViaInjection(tabId) {
const results = await chrome.scripting.executeScript({
target: { tabId },
func: (key) => {
const raw = localStorage.getItem(key);
if (!raw) return null;
try {
return JSON.parse(raw);
} catch {
return null;
}
},
args: [AUTH_KEY],
});
const auth = results?.[0]?.result ?? null;
return { ok: true, auth };
}
async function readAuthFromPage(tab) {
let result = await readAuthViaMessage(tab.id);
if (!result.ok || !result.auth) {
result = await readAuthViaInjection(tab.id);
}
return result;
}
async function syncSession(auth, backendUrl) {
if (!auth?.accessToken) {
throw new Error("找不到登入憑證,請確認已登入工時系統");
}
const res = await fetch(`${backendUrl}/api/session`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
accessToken: auth.accessToken,
refreshToken: auth.refreshToken,
groupCode: auth.groupCode,
raw: auth,
}),
});
const data = await res.json().catch(() => ({}));
if (!res.ok) throw new Error(data.detail || res.statusText);
return data;
}
document.getElementById("syncBtn").addEventListener("click", async () => {
statusEl.textContent = "同步中...";
const backendUrl = backendInput.value.trim().replace(/\/$/, "");
chrome.storage.local.set({ backendUrl });
try {
const tab = await getActiveTab();
if (!tab?.id || !isPtsUrl(tab.url)) {
throw new Error("請先切到工時系統分頁tw-timesheet.supermicro.com再按同步");
}
const pageAuth = await readAuthFromPage(tab);
if (!pageAuth.auth) {
throw new Error(
pageAuth.error
? `${pageAuth.error}。請重新整理工時系統頁面後再試`
: "無法讀取登入憑證,請重新整理工時系統頁面並確認已登入"
);
}
const result = await syncSession(pageAuth.auth, backendUrl);
statusEl.textContent = `成功:${result.message || "已同步"}`;
} catch (err) {
statusEl.textContent = `失敗:${err.message}`;
}
});