From 341aade87c56dc75846c2b5738d59b66f5b33126 Mon Sep 17 00:00:00 2001 From: Cadence Fish Date: Sat, 1 Feb 2020 16:15:12 +1300 Subject: [PATCH] Instance owners can disable RSS RSS is still enabled by default, but will be disabled on bibliogram.art. --- src/lib/constants.js | 4 +++ src/site/api/api.js | 11 +++++- src/site/api/feed.js | 62 ++++++++++++++++++++++----------- src/site/api/routes.js | 17 +++++---- src/site/pug/blocked.pug | 3 +- src/site/pug/friendlyerror.pug | 4 +-- src/site/pug/includes/error.pug | 9 +++-- src/site/pug/user.pug | 5 ++- 8 files changed, 80 insertions(+), 35 deletions(-) diff --git a/src/lib/constants.js b/src/lib/constants.js index 4b6459e..7b236cf 100644 --- a/src/lib/constants.js +++ b/src/lib/constants.js @@ -9,6 +9,10 @@ let constants = { website_origin: "http://localhost:10407", // Things that server owners _could_ change if they want to. + settings: { + rss_enabled: true + }, + caching: { image_cache_control: `public, max-age=${7*24*60*60}`, resource_cache_time: 30*60*1000, diff --git a/src/site/api/api.js b/src/site/api/api.js index 5de3a61..7d4cda7 100644 --- a/src/site/api/api.js +++ b/src/site/api/api.js @@ -41,7 +41,7 @@ module.exports = [ }, { route: "/api/stats/2.0", methods: ["GET"], code: async ({url}) => { - const versions = ["1.0", "1.1"] + const versions = ["1.0", "1.1", "1.2"] const features = [ "PAGE_PROFILE", "PAGE_POST", @@ -60,6 +60,15 @@ module.exports = [ availableVersions: versions, features, history: history.export() + }], + ["1.2", { + version: "1.2", + availableVersions: versions, + features, + history: history.export(), + settings: { + rssEnabled: constants.settings.rss_enabled + } }] ]) ).get(url.searchParams.get("bv") || versions[0]) diff --git a/src/site/api/feed.js b/src/site/api/feed.js index 290153d..3dc4472 100644 --- a/src/site/api/feed.js +++ b/src/site/api/feed.js @@ -1,27 +1,49 @@ const constants = require("../../lib/constants") -const {fetchUser} = require("../../lib/collectors") +const {fetchUser, requestCache} = require("../../lib/collectors") const {render} = require("pinski/plugins") +const {pugCache} = require("../passthrough") module.exports = [ {route: `/u/(${constants.external.username_regex})/rss.xml`, methods: ["GET"], code: ({fill}) => { - return fetchUser(fill[0]).then(async user => { - const content = await user.timeline.fetchFeed() - const xml = content.xml() - return { - statusCode: 200, - contentType: "application/rss+xml", // see https://stackoverflow.com/questions/595616/what-is-the-correct-mime-type-to-use-for-an-rss-feed - content: xml - } - }).catch(error => { - if (error === constants.symbols.NOT_FOUND) { - return render(404, "pug/friendlyerror.pug", { - statusCode: 404, - title: "Not found", - message: "This user doesn't exist." - }) - } else { - throw error - } - }) + if (constants.settings.rss_enabled) { + return fetchUser(fill[0]).then(async user => { + const content = await user.timeline.fetchFeed() + const xml = content.xml() + return { + statusCode: 200, + contentType: "application/rss+xml", // see https://stackoverflow.com/questions/595616/what-is-the-correct-mime-type-to-use-for-an-rss-feed + content: xml + } + }).catch(error => { + if (error === constants.symbols.NOT_FOUND) { + return render(404, "pug/friendlyerror.pug", { + statusCode: 404, + title: "Not found", + message: "This user doesn't exist.", + withInstancesLink: false + }) + } else if (error === constants.symbols.INSTAGRAM_DEMANDS_LOGIN) { + return { + statusCode: 503, + contentType: "text/html", + headers: { + "Retry-After": requestCache.getTtl("user/"+fill[0], 1000) + }, + content: pugCache.get("pug/blocked.pug").web({ + expiresMinutes: requestCache.getTtl("user/"+fill[0], 1000*60) + }) + } + } else { + throw error + } + }) + } else { + return Promise.resolve(render(403, "pug/friendlyerror.pug", { + statusCode: 403, + title: "RSS disabled", + message: "RSS is disabled on this instance.", + withInstancesLink: true + })) + } }} ] diff --git a/src/site/api/routes.js b/src/site/api/routes.js index 2e11267..852be75 100644 --- a/src/site/api/routes.js +++ b/src/site/api/routes.js @@ -17,7 +17,8 @@ module.exports = [ statusCode: 400, title: "Bad request", message: "Expected a username", - explanation: "Write /u/{username} or /u?u={username}." + explanation: "Write /u/{username} or /u?u={username}.", + withInstancesLink: false }) } } @@ -30,13 +31,14 @@ module.exports = [ if (typeof page === "number" && !isNaN(page) && page >= 1) { await user.timeline.fetchUpToPage(page - 1) } - return render(200, "pug/user.pug", {url, user}) + return render(200, "pug/user.pug", {url, user, constants}) }).catch(error => { if (error === constants.symbols.NOT_FOUND) { return render(404, "pug/friendlyerror.pug", { statusCode: 404, title: "Not found", - message: "This user doesn't exist." + message: "This user doesn't exist.", + withInstancesLink: false }) } else if (error === constants.symbols.INSTAGRAM_DEMANDS_LOGIN) { return { @@ -75,7 +77,8 @@ module.exports = [ return render(404, "pug/friendlyerror.pug", { statusCode: 404, title: "Not found", - message: "This user doesn't exist." + message: "This user doesn't exist.", + withInstancesLink: false }) } else { throw error @@ -94,7 +97,8 @@ module.exports = [ statusCode: 400, title: "Bad request", message: "Expected a shortcode", - explanation: "Write /p/{shortcode} or /p?p={shortcode}." + explanation: "Write /p/{shortcode} or /p?p={shortcode}.", + withInstancesLink: false }) } } @@ -111,7 +115,8 @@ module.exports = [ return render(404, "pug/friendlyerror.pug", { statusCode: 404, title: "Not found", - message: "Somehow, you reached a post that doesn't exist." + message: "Somehow, you reached a post that doesn't exist.", + withInstancesLink: false }) } else { throw error diff --git a/src/site/pug/blocked.pug b/src/site/pug/blocked.pug index 4f0183d..11712a7 100644 --- a/src/site/pug/blocked.pug +++ b/src/site/pug/blocked.pug @@ -12,8 +12,7 @@ html title= `Blocked | Bibliogram` link(rel="stylesheet" type="text/css" href="/static/css/main.css") body.error-page - +error(503, "Blocked by Instagram") + +error(503, "Blocked by Instagram", true) | Instagram is refusing to provide data to this server. Try again later to see if the block has been lifted. | This error has been cached. The internal cache will expire in #{expiresMinutes} minutes. | - a(href="https://github.com/cloudrac3r/bibliogram/wiki/Instances") You could try browsing Bibliogram on another instance. diff --git a/src/site/pug/friendlyerror.pug b/src/site/pug/friendlyerror.pug index 3fc241e..1e166ce 100644 --- a/src/site/pug/friendlyerror.pug +++ b/src/site/pug/friendlyerror.pug @@ -1,4 +1,4 @@ -//- Needs title, message, statusCode ?explanation +//- Needs title, message, statusCode, ?explanation, withInstancesLink include includes/error.pug @@ -12,6 +12,6 @@ html title= `${title} | Bibliogram` link(rel="stylesheet" type="text/css" href="/static/css/main.css") body.error-page - +error(statusCode, message) + +error(statusCode, message, withInstancesLink) if explanation =explanation diff --git a/src/site/pug/includes/error.pug b/src/site/pug/includes/error.pug index b30aef7..7c08a4f 100644 --- a/src/site/pug/includes/error.pug +++ b/src/site/pug/includes/error.pug @@ -1,7 +1,10 @@ -mixin error(statusCode, message) +mixin error(statusCode, message, withInstancesLink) h1.code= statusCode p.message= message - if block + if block || withInstancesLink p.explanation - block + if block + block + if withInstancesLink + a(href="https://github.com/cloudrac3r/bibliogram/wiki/Instances") You could try browsing Bibliogram on another instance. a(href="javascript:history.back()").back ← Go back? diff --git a/src/site/pug/user.pug b/src/site/pug/user.pug index b1531f6..fd7e41a 100644 --- a/src/site/pug/user.pug +++ b/src/site/pug/user.pug @@ -1,3 +1,5 @@ +//- Needs user, url, constants + include includes/timeline_page.pug include includes/next_page_button.pug @@ -30,7 +32,8 @@ html div.profile-counter #[span(data-numberformat=user.following).count #{numberFormat(user.following)}] following div.profile-counter #[span(data-numberformat=user.followedBy).count #{numberFormat(user.followedBy)}] followed by div.links - a(rel="alternate" type="application/rss+xml" href=`/u/${user.data.username}/rss.xml`) RSS + if constants.settings.rss_enabled + a(rel="alternate" type="application/rss+xml" href=`/u/${user.data.username}/rss.xml`) RSS a(rel="noreferrer noopener" href=`https://www.instagram.com/${user.data.username}`) instagram.com - const hasPosts = !user.data.is_private && user.timeline.pages.length && user.timeline.pages[0].length