60 lines
2.5 KiB
JavaScript
60 lines
2.5 KiB
JavaScript
import getServiceWidget from "utils/config/service-helpers";
|
|
import createLogger from "utils/logger";
|
|
const logger = createLogger("freshrsslist");
|
|
export default async function freshrsslistProxyHandler(req, res) {
|
|
try {
|
|
const { group, service } = req.query;
|
|
const serviceWidget = await getServiceWidget(group, service);
|
|
if (!serviceWidget) {
|
|
return res.status(400).json({ error: "Widget not found" });
|
|
}
|
|
const { url, username, password, category, limit } = serviceWidget;
|
|
const itemLimit = parseInt(limit, 10) || 5;
|
|
if (!url || !username || !password) {
|
|
return res.status(400).json({ error: "Missing required fields" });
|
|
}
|
|
const baseUrl = url.replace(/\/+$/, "");
|
|
// 1) ClientLogin to get Auth token
|
|
const loginUrl = `${baseUrl}/api/greader.php/accounts/ClientLogin`;
|
|
const loginRes = await fetch(loginUrl, {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
body: `Email=${encodeURIComponent(username)}&Passwd=${encodeURIComponent(password)}`,
|
|
});
|
|
const loginText = await loginRes.text();
|
|
const authMatch = loginText.match(/Auth=([^\n]+)/);
|
|
if (!authMatch) {
|
|
logger.error(`FreshRSS ClientLogin failed: ${loginText}`);
|
|
return res.status(401).json({ error: "FreshRSS auth failed" });
|
|
}
|
|
const authToken = authMatch[1];
|
|
// 2) Fetch reading list with GoogleLogin auth header
|
|
const streamPath = category
|
|
? `user/-/label/${encodeURIComponent(category)}`
|
|
: "user/-/state/com.google/reading-list";
|
|
const targetUrl = `${baseUrl}/api/greader.php/reader/api/0/stream/contents/${streamPath}?n=${itemLimit}&output=json&r=n`;
|
|
const response = await fetch(targetUrl, {
|
|
headers: { Authorization: `GoogleLogin auth=${authToken}` },
|
|
});
|
|
if (!response.ok) {
|
|
logger.error(`FreshRSS returned ${response.status}`);
|
|
return res
|
|
.status(response.status)
|
|
.json({ error: `HTTP ${response.status}` });
|
|
}
|
|
const json = await response.json();
|
|
const items = (json.items || []).map((item) => ({
|
|
id: item.id || item.timestampUsec,
|
|
title: item.title || "Untitled",
|
|
url: item.alternate?.[0]?.href || item.canonical?.[0]?.href || "",
|
|
author: item.author || "",
|
|
created_on_time: item.published || Math.floor(Date.now() / 1000),
|
|
feed_name: item.origin?.title || "",
|
|
}));
|
|
return res.status(200).json({ items });
|
|
} catch (err) {
|
|
logger.error(err);
|
|
return res.status(500).json({ error: err.message });
|
|
}
|
|
}
|