mirror of
https://github.com/DI0IK/homepage-plus.git
synced 2025-07-10 07:18:47 +00:00
Feature: stock market service and info widget (#3617)
--------- Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
This commit is contained in:
parent
810c321881
commit
231e2408c3
14 changed files with 424 additions and 1 deletions
76
src/pages/api/widgets/stocks.js
Normal file
76
src/pages/api/widgets/stocks.js
Normal file
|
@ -0,0 +1,76 @@
|
|||
import cachedFetch from "utils/proxy/cached-fetch";
|
||||
import { getSettings } from "utils/config/config";
|
||||
|
||||
export default async function handler(req, res) {
|
||||
const { watchlist, provider, cache } = req.query;
|
||||
|
||||
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 cachedFetch(apiUrl, cache || 1);
|
||||
|
||||
// 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" });
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue