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 }); } }