mirror of
https://github.com/gethomepage/homepage.git
synced 2025-05-24 02:02:35 -04:00
83 lines
2.6 KiB
JavaScript
83 lines
2.6 KiB
JavaScript
import { getSettings } from "utils/config/config";
|
|
import createLogger from "utils/logger";
|
|
import { cachedRequest } from "utils/proxy/http";
|
|
|
|
const logger = createLogger("stocks");
|
|
|
|
export default async function handler(req, res) {
|
|
const { watchlist, provider, cache } = req.query;
|
|
|
|
logger.debug("Stocks API request: %o", { watchlist, provider, cache });
|
|
|
|
if (!watchlist) {
|
|
return res.status(400).json({ error: "Missing watchlist" });
|
|
}
|
|
|
|
const watchlistArr = watchlist.split(",") || [watchlist];
|
|
|
|
if (!watchlistArr.length || watchlistArr[0] === "null" || !watchlistArr[0]) {
|
|
return res.status(400).json({ error: "Missing watchlist" });
|
|
}
|
|
|
|
if (watchlistArr.length > 8) {
|
|
return res.status(400).json({ error: "Max items in watchlist is 8" });
|
|
}
|
|
|
|
const hasDuplicates = new Set(watchlistArr).size !== watchlistArr.length;
|
|
|
|
if (hasDuplicates) {
|
|
return res.status(400).json({ error: "Watchlist contains duplicates" });
|
|
}
|
|
|
|
if (!provider) {
|
|
return res.status(400).json({ error: "Missing provider" });
|
|
}
|
|
|
|
if (provider !== "finnhub") {
|
|
return res.status(400).json({ error: "Invalid provider" });
|
|
}
|
|
|
|
const providersInConfig = getSettings()?.providers;
|
|
|
|
let apiKey;
|
|
Object.entries(providersInConfig).forEach(([key, val]) => {
|
|
if (key === provider) apiKey = val;
|
|
});
|
|
|
|
if (typeof apiKey === "undefined") {
|
|
return res.status(400).json({ error: "Missing or invalid API Key for provider" });
|
|
}
|
|
|
|
if (provider === "finnhub") {
|
|
// Finnhub allows up to 30 calls/second
|
|
// https://finnhub.io/docs/api/rate-limit
|
|
const results = await Promise.all(
|
|
watchlistArr.map(async (ticker) => {
|
|
if (!ticker) {
|
|
return { ticker: null, currentPrice: null, percentChange: null };
|
|
}
|
|
// https://finnhub.io/docs/api/quote
|
|
const apiUrl = `https://finnhub.io/api/v1/quote?symbol=${ticker}&token=${apiKey}`;
|
|
// Finnhub free accounts allow up to 60 calls/minute
|
|
// https://finnhub.io/pricing
|
|
const { c, dp } = await cachedRequest(apiUrl, cache || 1);
|
|
logger.debug("Finnhub API response for %s: %o", ticker, { c, dp });
|
|
|
|
// API sometimes returns 200, but values returned are `null`
|
|
if (c === null || dp === null) {
|
|
return { ticker, currentPrice: null, percentChange: null };
|
|
}
|
|
|
|
// Rounding percentage, but we want it back to a number for comparison
|
|
return { ticker, currentPrice: c.toFixed(2), percentChange: parseFloat(dp.toFixed(2)) };
|
|
}),
|
|
);
|
|
|
|
return res.send({
|
|
stocks: results,
|
|
});
|
|
}
|
|
|
|
return res.status(400).json({ error: "Invalid configuration" });
|
|
}
|