Initial commit
commit
bcdd389edf
@ -0,0 +1 @@
|
|||||||
|
/node_modules/
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"printWidth": 140,
|
||||||
|
"singleQuote": true,
|
||||||
|
"semi": true,
|
||||||
|
"useTabs": true
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
For annoying RSS channels that have bot protection and thus cannot be subscribed to.
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
// xml-proxy.js
|
||||||
|
import express from 'express';
|
||||||
|
import puppeteer from 'puppeteer-extra';
|
||||||
|
import StealthPlugin from 'puppeteer-extra-plugin-stealth';
|
||||||
|
import he from 'he'; // HTML entity decoder
|
||||||
|
|
||||||
|
puppeteer.use(StealthPlugin());
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
const PORT = process.env.PORT || 3000;
|
||||||
|
const PASSWORD = process.env.PASSWORD || '8yug8976tyu7654etdr645etr65etrdyugydt';
|
||||||
|
|
||||||
|
app.get('/fetch', async (req, res) => {
|
||||||
|
const { url, password } = req.query;
|
||||||
|
if (password !== PASSWORD) {
|
||||||
|
res.status(403);
|
||||||
|
res.send('Missing password');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!url) return res.status(400).send('Missing url parameter');
|
||||||
|
|
||||||
|
let browser;
|
||||||
|
try {
|
||||||
|
browser = await puppeteer.launch({
|
||||||
|
headless: true,
|
||||||
|
args: ['--no-sandbox', '--disable-setuid-sandbox'],
|
||||||
|
});
|
||||||
|
|
||||||
|
const page = await browser.newPage();
|
||||||
|
|
||||||
|
await page.setUserAgent(
|
||||||
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36',
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.goto(url, { waitUntil: 'networkidle2' });
|
||||||
|
|
||||||
|
// Extract escaped XML from <pre> and decode
|
||||||
|
const xml = await page.evaluate(() => {
|
||||||
|
const pre = document.querySelector('pre');
|
||||||
|
return pre ? pre.innerHTML : document.documentElement.outerHTML;
|
||||||
|
});
|
||||||
|
|
||||||
|
const decodedXml = he.decode(xml);
|
||||||
|
|
||||||
|
res.set('Content-Type', 'application/xml; charset=utf-8');
|
||||||
|
res.send(decodedXml);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
res.status(500).send('Error fetching XML');
|
||||||
|
} finally {
|
||||||
|
if (browser) await browser.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.listen(PORT, () => {
|
||||||
|
console.log(`XML Puppeteer proxy listening at http://localhost:${PORT}`);
|
||||||
|
});
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "rss-proxy",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.mjs",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"express": "^5.2.1",
|
||||||
|
"he": "^1.2.0",
|
||||||
|
"puppeteer": "^24.36.1",
|
||||||
|
"puppeteer-extra": "^3.3.6",
|
||||||
|
"puppeteer-extra-plugin-stealth": "^2.11.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue