palico-bot/public/scripts/common.js

118 lines
3.2 KiB
JavaScript

const API_KEY_STORAGE_KEY = "palico-api-key";
const DISPLAY_NAME_STORAGE_KEY = "palico-display-name";
export function getStoredApiKey() {
return sessionStorage.getItem(API_KEY_STORAGE_KEY) || "";
}
export function setStoredApiKey(value) {
sessionStorage.setItem(API_KEY_STORAGE_KEY, value || "");
}
export function getStoredDisplayName() {
return localStorage.getItem(DISPLAY_NAME_STORAGE_KEY) || "";
}
export function setStoredDisplayName(value) {
localStorage.setItem(DISPLAY_NAME_STORAGE_KEY, value || "");
}
export function createStatusManager(statusElement) {
let hideTimeout;
function setStatus(message, type = "info", autoHide = true) {
if (!statusElement) return;
statusElement.textContent = message;
statusElement.className = `status status--${type}`;
statusElement.hidden = false;
if (autoHide) {
clearTimeout(hideTimeout);
hideTimeout = setTimeout(() => {
statusElement.hidden = true;
}, 5000);
}
}
function clearStatus() {
if (!statusElement) return;
statusElement.hidden = true;
statusElement.textContent = "";
clearTimeout(hideTimeout);
}
return { setStatus, clearStatus };
}
export function escapeHtml(text = "") {
return text
.toString()
.replace(/&/g, "&")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
export function formatBytes(bytes = 0) {
if (!Number(bytes)) return "0 B";
const units = ["B", "KB", "MB", "GB", "TB"];
const index = Math.floor(Math.log(bytes) / Math.log(1024));
return `${(bytes / Math.pow(1024, index)).toFixed(1)} ${units[index]}`;
}
export function formatDate(value) {
if (!value) return "?";
try {
return new Date(value).toLocaleString();
} catch (_) {
return value;
}
}
export function createApiClient({ getApiKey, basePath = "" } = {}) {
const normalizedBase = (basePath || "").replace(/\/$/, "");
return async function apiFetch(path, options = {}) {
const url = path.startsWith("http")
? path
: `${normalizedBase}${path.startsWith("/") ? "" : "/"}${path}`;
const fetchOptions = {
method: options.method || "GET",
headers: new Headers(options.headers || {}),
};
const apiKey = typeof getApiKey === "function" ? getApiKey() : null;
if (apiKey) {
fetchOptions.headers.set("Authorization", `Bearer ${apiKey}`);
}
if (options.body instanceof FormData) {
fetchOptions.body = options.body;
} else if (options.body) {
if (!fetchOptions.headers.has("Content-Type")) {
fetchOptions.headers.set("Content-Type", "application/json");
}
fetchOptions.body =
typeof options.body === "string" ? options.body : JSON.stringify(options.body);
}
const response = await fetch(url, fetchOptions);
const contentType = response.headers.get("content-type") || "";
let payload = null;
if (contentType.includes("application/json")) {
payload = await response.json();
} else {
payload = await response.text();
}
if (!response.ok) {
const errorMessage = payload?.error || payload?.message || response.statusText;
throw new Error(errorMessage);
}
return payload;
};
}