diff --git a/packages/backend/package.json b/packages/backend/package.json index 0bf47888e4..ef3f554583 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -92,6 +92,7 @@ "rename": "1.0.4", "require-all": "3.0.0", "rndstr": "1.0.0", + "rss-parser": "3.12.0", "s-age": "1.1.2", "sanitize-html": "2.7.0", "semver": "7.3.7", diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index f019677542..f458763923 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -312,6 +312,7 @@ import * as ep___users_searchByUsernameAndHost from './endpoints/users/search-by import * as ep___users_search from './endpoints/users/search.js'; import * as ep___users_show from './endpoints/users/show.js'; import * as ep___users_stats from './endpoints/users/stats.js'; +import * as ep___fetchRss from './endpoints/fetch-rss.js'; const eps = [ ['admin/meta', ep___admin_meta], @@ -626,6 +627,7 @@ const eps = [ ['users/search', ep___users_search], ['users/show', ep___users_show], ['users/stats', ep___users_stats], + ['fetch-rss', ep___fetchRss], ]; export interface IEndpointMeta { diff --git a/packages/backend/src/server/api/endpoints/fetch-rss.ts b/packages/backend/src/server/api/endpoints/fetch-rss.ts new file mode 100644 index 0000000000..05fa22a9e4 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/fetch-rss.ts @@ -0,0 +1,39 @@ +import Parser from 'rss-parser'; +import { getResponse } from '@/misc/fetch.js'; +import config from '@/config/index.js'; +import define from '../define.js'; + +const rssParser = new Parser(); + +export const meta = { + tags: ['meta'], + + requireCredential: false, + allowGet: true, + cacheSec: 60 * 3, +} as const; + +export const paramDef = { + type: 'object', + properties: { + url: { type: 'string' }, + }, + required: ['url'], +} as const; + +// eslint-disable-next-line import/no-default-export +export default define(meta, paramDef, async (ps) => { + const res = await getResponse({ + url: ps.url, + method: 'GET', + headers: Object.assign({ + 'User-Agent': config.userAgent, + Accept: 'application/rss+xml, */*', + }), + timeout: 5000, + }); + + const text = await res.text(); + + return rssParser.parseString(text); +}); diff --git a/packages/backend/yarn.lock b/packages/backend/yarn.lock index 880bbf7d19..3c9f2680f5 100644 --- a/packages/backend/yarn.lock +++ b/packages/backend/yarn.lock @@ -2485,6 +2485,11 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== +entities@^2.0.3: + version "2.2.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== + entities@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/entities/-/entities-4.3.0.tgz#62915f08d67353bb4eb67e3d62641a4059aec656" @@ -5985,6 +5990,14 @@ rndstr@1.0.0: rangestr "0.0.1" seedrandom "2.4.2" +rss-parser@3.12.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/rss-parser/-/rss-parser-3.12.0.tgz#b8888699ea46304a74363fbd8144671b2997984c" + integrity sha512-aqD3E8iavcCdkhVxNDIdg1nkBI17jgqF+9OqPS1orwNaOgySdpvq6B+DoONLhzjzwV8mWg37sb60e4bmLK117A== + dependencies: + entities "^2.0.3" + xml2js "^0.4.19" + run-parallel@^1.1.9: version "1.1.9" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" @@ -7174,7 +7187,7 @@ xml2js@0.4.19: sax ">=0.6.0" xmlbuilder "~9.0.1" -xml2js@^0.4.23: +xml2js@^0.4.19, xml2js@^0.4.23: version "0.4.23" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== diff --git a/packages/client/src/widgets/rss-marquee.vue b/packages/client/src/widgets/rss-marquee.vue index 6d910a2fb8..d96eadb4e0 100644 --- a/packages/client/src/widgets/rss-marquee.vue +++ b/packages/client/src/widgets/rss-marquee.vue @@ -80,7 +80,7 @@ const fetching = ref(true); let key = $ref(0); const tick = () => { - fetch(`https://api.rss2json.com/v1/api.json?rss_url=${widgetProps.url}`, {}).then(res => { + fetch(`/api/fetch-rss?url=${widgetProps.url}`, {}).then(res => { res.json().then(feed => { items.value = feed.items; fetching.value = false; diff --git a/packages/client/src/widgets/rss.vue b/packages/client/src/widgets/rss.vue index ea896478a3..72f6249820 100644 --- a/packages/client/src/widgets/rss.vue +++ b/packages/client/src/widgets/rss.vue @@ -51,7 +51,7 @@ const items = ref([]); const fetching = ref(true); const tick = () => { - fetch(`https://api.rss2json.com/v1/api.json?rss_url=${widgetProps.url}`, {}).then(res => { + fetch(`/api/fetch-rss?url=${widgetProps.url}`, {}).then(res => { res.json().then(feed => { items.value = feed.items; fetching.value = false;