Giter Club home page Giter Club logo

birdreader's Introduction

BirdReader

Introduction

In March 2013, Google announced that Google Reader was to be closed. I used Google Reader every day so I set out to find a replacement. I started with other online offerings, but then I thought "I could build one". So I created BirdReader which I have released to the world in its unpolished "alpha".

BirdReader is designed to be installed on your own webserver or laptop, running Node.js. e.g.

  • on an old PC
  • on a cloud server e.g. AWS Micro server (free!)
  • on a Raspberry Pi

desktop screenshot

Features

  • import your old Google Reader subscriptions
  • fetches RSS every 5 minutes
  • web-based aggregated newsfeed
    • mark articles as read
    • delete articles without reading
    • 'star' articles
    • add a new feed
    • sorted in newest-first order
    • bootstrap-based, responsive layout
    • tagging/untagging of feeds
    • Twitter/Facebook sharing
    • basic HTTP authentication (optional)
    • filter read/unread/starred streams by tag
    • filter read/unread/starred streams by feed
    • full-text search (only works when using Cloudant as the CouchDB storage engine)
    • icons for feeds and articles
    • expand all
    • browse-mode - go through unread articles one-by-one, full screen
    • live stats via WebSockets (NEW!)

As of July 2013, the web client also makes a WebSockets connection back to the server so that when new articles are added to the database, then the numbers of read, unread and starred articles can be 'pushed' to the server, without the client having to poll. This also offers other advantages

  • when fetching an article or list of articles, we no longer have to also fetch the article counts, making fetches faster
  • article counts arrive at the client asynchronously
  • article counts are always up to date
  • url scheme has changed to a 'hash-bang' scheme, so that all page updates are via Ajax, to prevent frequent disconnection of the WebSocket and to reduce network traffic

N.B if you have previous installation of BirdReader, you will have to run 'npm install' to pick up the socket.io package.

How does it work?

BirdReader doesn't store anything locally other than its source code and your configuration. The data is stored in a Cloudant (CouchDB) database in the cloud. You will need to sign up for a free Cloudant account (disclaimer: other hosted CouchDB services are available, and this code should work with any CouchDB server e.g. your own).

Two databases are used:

feeds database

The 'feeds' database stores a document per RSS feed you are subscribed to e.g.

{
    "_id": "f1cf38b2f6ffbbb69e75df476310b3a6",
    "_rev": "8-6ad06e42183368bd696aec8d25eb03a1",
    "text": "The GitHub Blog",
    "title": "The GitHub Blog",
    "type": "rss",
    "xmlUrl": "http://feeds.feedburner.com/github",
    "htmlUrl": "http://pipes.yahoo.com/pipes/pipe.info?_id=13d93fdc3d1fb71d8baa50a1e8b50381",
    "tags": ["OpenSource"],
    "lastModified": "2013-03-14 15:06:03 +00:00",
    "icon": "http://www.bbc.co.uk/favicon.ico"
}

This data is directly imported from the Google Checkout OPML file and crucially stores:

  • the url which contains the feed data (xmlUrl)
  • the last modification date of the newest article on that feed (lastModified)

articles database

The 'articles' database stores a document per article e.g. :

{
    "_id": "3c582426df29863513500a736111fa4e",
    "_rev": "1-b49944fd0edf8f50fc17c6562d75169e",
    "feedName": "BBC Entertainment",
    "tags": ["BBC"],
    "title": "VIDEO: Iran planning to sue over Argo",
    "description": "Best Picture winner Argo has been criticised by the Iranian authorities over its portrayal of the 1979 Iran hostage crisis.",
    "pubDate": "2013-03-15T15:20:31.000Z",
    "link": "http://www.bbc.co.uk/news/entertainment-arts-21805140#sa-ns_mchannel=rss&ns_source=PublicRSS20-sa",
    "pubDateTS": 1363360831,
    "read": false,
    "starred": false,
    "icon": "http://www.bbc.co.uk/favicon.ico"
}

The _id and _rev fields are generated by CouchDB. The feedName and tags come from the feed where the article originated. The rest of the fields come form the RSS article itself apart from 'read' and 'starred' which we add to record whether an article has been consumed or favourited.

Views

Cloudant/CouchDB only allows data to be retrieved by its "_id" unless you define a "view". We have one view on the articles database called "byts" that allows us to query our data:

  • unread article, sorted by timestamp
  • read articles, sorted by timestamp
  • starred articles, sorted by timestamp
  • counts of the number of read/unread/starred articles

The view creates a "map" function which emits keys like

  ["string",123455]

where "string" can be "unread", "read" or "starred", and "12345" is the timestamp of the article.

Another view "bytag" has a different key:

  ['string','tag',12345]

where "string" can be "unread", "read" or "starred", the "tag" is the user supplied tag and "12345" is the timestamp of the article. This allows us to get unread articles tagged by "BBC" in newest first order, for example.

Full-text search

BirdReader supports full-text search of articles by utilising Cloudant's full-text capability. A Lucene index is created to allow the articles' titles and descriptions to searchable. A simple form on the top bar allows the user to search the collected articles with ease. N.B if you are using a non-Cloudant backend (e.g. plain CouchDB), then the search facility will not work.

Scraping articles

Every so often, BirdReader fetches all the feeds using the feedparser. Any articles newer than the feed's previous newest article is saved to the articles database.

Adding new feeds

New feeds can be added by filling in a web form with the url of the page that has an RSS link tag. We use the extractor library to pull back the page, find the title, meta description and link tags and add the data to our feeds database.

What does it look like?

The site is built with Bootstrap so that it provides a decent interface on desktop and mobile browsers

Mobile Screenshot

mobile browse screenshot

mobile screenshot

Key technologies

  • Node.js - Server side Javascript
  • Express - Application framework for node
  • feedparser - RSS feed parser
  • Cloudant - Hosted CouchDB
  • async - Control your parallelism in Node.js
  • Bootstrap - Twitter responsive HTML framework
  • sax - XML parser for Node.js
  • extractor - HTML scraper, to find RSS links in HTML pages
  • socket-io - WebSockets library

Installation

You will need Node.js and npm installed on your computer (version 0.8.x or version 0.10.x). Unpack the BirdReader repository and install its dependencies e.g.

  git clone [email protected]:glynnbird/birdreader.git
  cd birdreader
  npm install

N.B on Mac, your're likely to need [https://developer.apple.com/xcode/](development tools) installed.

Copy the sample configuration into place

  cd includes
  cp _config.json config.json

Edit the sample configuration to point to your CouchDB server.

Run Birdreader with

  node birdreader.js

See the website by pointing your browser to port 3000:

  http://localhost:3000/

Importing Google Reader subscriptions

You can export your Google Reader subscriptions using Google Takeout. Download the file, unpack it and locate the subscriptions.xml file.

You can import this into BirdReader with:

  node import_opml.js subscriptions.xml

Securing your BirdReader server

BirdReader allows you to protect your webserver by username and password by adding an "authentication" section to our includes/config.json:

  "cloudant": {
    .  
    .
  },
  "authentication": {
    "on": true,
    "username": "myusername",
    "password": "mypassword"
  }
}

Authentication will only be enforced if "authentication.on" is set to "true". A restart of BirdReader is required to pick up the config.

Purging older articles

If you don't want to keep articles older than x days, then you can add the following to your config:

"purgeArticles": {
  "on": true,
  "purgeBefore": 15
}

The above will instruct BirdReader to purge articles older than 15 days every 24 hours.

Benchmarks

BirdReader has been tested on a Mac, Amazon EC2 and Raspberry Pi. Benchmarks here.

Icons

When a feed is added to BirdReader, we attempt to get an "icon" for the feed based on the "Favicon" of the blog. This is stored in the feeds database and every article that is fetched subsequently, inherits the feed's icon.

This feature was added after launch. To retro-fit icons to your existing feeds, run:

  node retrofit_favicons.js

Tests

There are some tests in the 'test' directory to run them you'll need Mocha:

  sudo npm install -g mocha

and then run the tests

  mocha

birdreader's People

Contributors

bigbluehat avatar glynnbird avatar maghoff avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

birdreader's Issues

incorrect node version Ubuntu 12.04

Following the instructions in README.md:
npm install

This throws the error:
Unsupported
npm ERR! Not compatible with your version of node/npm: [email protected]
npm ERR! Required: {"node":">= 0.8.0"}
npm ERR! Actual: {"npm":"1.1.4","node":"0.6.12"}

OS: Ubunto 12.04
node -v v0.6.12
npm -v 1.1.4

Thanks.

feeds saving issue

Hi there,

For some reason I'm not able to save any feeds using 'add' button. I receive 'Successfully added feed' response, but the feeds is actually not added.

Here is the link to the deployment: http://aggr-mhlab.rhcloud.com/

Any advice would be appreciated.

Many thanks,
Max

enhancement - filter by feed

any chance of being able to filter the articles list when clicking on the feed name in the article list to only show articles for that feed only - similar to when you click on a tag.

no description for article causes crash

if an article doesnt contain a description i get the following crash:

TypeError: Cannot call method 'replace' of undefined
at processArticles (/usr/home/mike/birdreader/birdreader.js:92:42)
at /usr/home/mike/birdreader/birdreader.js:110:20
at /usr/home/mike/birdreader/node_modules/async/lib/async.js:227:13
at /usr/home/mike/birdreader/node_modules/async/lib/async.js:107:25
at /usr/home/mike/birdreader/node_modules/async/lib/async.js:24:16
at /usr/home/mike/birdreader/node_modules/async/lib/async.js:224:17
at /usr/home/mike/birdreader/node_modules/async/lib/async.js:507:34
at /usr/home/mike/birdreader/includes/article.js:18:5
at Request._callback (/usr/home/mike/birdreader/node_modules/nano/nano.js:296:11)
at Request.self.callback (/usr/home/mike/birdreader/node_modules/nano/node_modules/request/main.js:120:22)

adding "description": "" to any article docs will fix any articles which cause this

the temp view below will help find any docs with out a description:

function(doc) { if(!doc.description){emit(doc); } }

Using a local CouchDB

This maybe a setup issue but I installed CouchDB on my RaspberryPi and I'm able to access the admin panel it via my server's external IP.

I've followed your instructions to the letter and everything is setup, running and listening but I can't see anything at http://myserversip:3000
Here's is my config - (server named here as "myserverip"):

{
"cloudant": {
"server": "http://myserverip",
"port": 5489,
"username": "",
"password": "",
"secure": true
},
"authentication": {
"on": false,
"username": "",
"password": ""
},
"purgeArticles": {
"on": false,
"purgeBefore": 15
}
}

Searching for local couchdb via elasticsearch

I have made a small change to the article.js to allow for searching for normal couchdb setups via elasticsearch and the couchdb river
https://github.com/elasticsearch/elasticsearch-river-couchdb

Once the river plugin is installed setup the river for articles:

curl -XPUT 'http://elasticsearch_host:9200/_river/articles/_meta' -d '{
"type" : "couchdb",
"couchdb" : {
"host" : "couchdb_host",
"port" : 5984,
"db" : "articles"
}


Install elasticsearch node client

npm install --save elasticsearch


Changes to: includes/article.js

var articles = require('./cloudant.js').articles;

var moment = require('moment');
var async = require('async');
var mc = require('./mc.js');
var elasticsearch = require('elasticsearch');

Replace the search part from line 322

var search = function (keywords, callback) {
var client = new elasticsearch.Client( { host: 'elasticsearch_host:9200', log: 'info' } );
client.search({
q: keywords, index: "articles", size: 99
}).then(function (body) {
retval = [];
for (i = 0; i < body.hits.hits.length; i++) {
retval.push(body.hits.hits[i]._source);
}
callback(false, retval);
}, function (error) {
console.trace(error.message);
});
};

async callback error

Sorry I seem to be creating a few issues for you - after running for a while i get a crash as follows:

Listening on port 3000

Checking articles database
Checking views

/usr/home/mike/birdreader/node_modules/async/lib/async.js:22
if (called) throw new Error("Callback was already called.");
^
Error: Callback was already called.
at /usr/home/mike/birdreader/node_modules/async/lib/async.js:22:31
at /usr/home/mike/birdreader/node_modules/async/lib/async.js:224:17
at /usr/home/mike/birdreader/node_modules/async/lib/async.js:507:34
at /usr/home/mike/birdreader/includes/feed.js:71:7
at FeedParser. (/usr/home/mike/birdreader/includes/feed.js:62:9)
at FeedParser.EventEmitter.emit (events.js:95:17)
at /usr/home/mike/birdreader/node_modules/feedparser/main.js:967:15
at process._tickCallback (node.js:415:13)

Process crash on invalid URL

If the database stores an invalid feed URL, it takes down the whole process.

info: socket.io started
Checking feeds database
Listening on port 3000
Checking articles database
Checking views

events.js:72
        throw er; // Unhandled 'error' event
              ^
Error: Invalid URI "files/feed.xml"
    at Request.init (/home/mag/prog/traume-roat/deploy/birdreader/node_modules/request/request.js:186:24)
    at new Request (/home/mag/prog/traume-roat/deploy/birdreader/node_modules/request/request.js:105:8)
    at request (/home/mag/prog/traume-roat/deploy/birdreader/node_modules/request/index.js:53:11)
    at fetchFeed (/home/mag/prog/traume-roat/deploy/birdreader/includes/feed.js:47:3)
    at /home/mag/prog/traume-roat/deploy/birdreader/includes/feed.js:123:11
    at /home/mag/prog/traume-roat/deploy/birdreader/node_modules/async/lib/async.js:508:21
    at /home/mag/prog/traume-roat/deploy/birdreader/node_modules/async/lib/async.js:224:13
    at replenish (/home/mag/prog/traume-roat/deploy/birdreader/node_modules/async/lib/async.js:176:21)
    at /home/mag/prog/traume-roat/deploy/birdreader/node_modules/async/lib/async.js:188:33
    at /home/mag/prog/traume-roat/deploy/birdreader/node_modules/async/lib/async.js:226:17

Adding a Feed

Adding a feed URL via the web form will return an error.

By example

Could not add feed for http://feeds.mashable.com/Mashable

enhancement - expand all button

if there are only 3 or 4 unread articles (eg after filtering by feed) is it possible to have an expand all button which opens all of the articles listed and marks them as read

unable to run tests

i installed mocha and tried to run the tests but it failed, below is the log..

    throw err;
    ^

Error: Cannot find module 'should'
    at Function.Module._resolveFilename (module.js:485:15)
    at Function.Module._load (module.js:437:25)
    at Module.require (module.js:513:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (H:\Projects\newExperiments\birdreader\test\api.js:5:12)
    at Module._compile (module.js:569:30)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:503:32)
    at tryModuleLoad (module.js:466:12)
    at Function.Module._load (module.js:458:3)
    at Module.require (module.js:513:17)
    at require (internal/module.js:11:18)
    at C:\Users\salus\AppData\Roaming\nvm\v8.0.0\node_modules\mocha\lib\mocha.js:231:27
    at Array.forEach (native)
    at Mocha.loadFiles (C:\Users\salus\AppData\Roaming\nvm\v8.0.0\node_modules\mocha\lib\mocha.js:228:14)
    at Mocha.run (C:\Users\salus\AppData\Roaming\nvm\v8.0.0\node_modules\mocha\lib\mocha.js:536:10)
    at Object.<anonymous> (C:\Users\salus\AppData\Roaming\nvm\v8.0.0\node_modules\mocha\bin\_mocha:573:18)
    at Module._compile (module.js:569:30)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:503:32)
    at tryModuleLoad (module.js:466:12)
    at Function.Module._load (module.js:458:3)
    at Function.Module.runMain (module.js:605:10)
    at startup (bootstrap_node.js:158:16)
    at bootstrap_node.js:575:3

Show listing of feed tags as a sidebar

Most/all feed readers have a sidebar showing the subscriptions. In birdreader this would be a listing of the feed tags, and perhaps subsidiary to each feed tag would be the feeds that have that tag.

By having this list it would become easy to navigate to showing the articles for a given feed tag.

Excessive writes to database?

Currently, the update sequence number for my feeds database is 2.5 million. This is maybe more than it needs to be, and it degrades performance by growing the database file way too much. The un-beefy machine I am running the database on also can't afford the disk space :)

On my machine it also seems that the daily compaction (https://github.com/glynnbird/birdreader/blob/master/birdreader.js#L60) as well as the automatic compaction configured in my CouchDb installation doesn't really prevent the feeds database file from growing up into GBs of space, when 1.2 MB is sufficient. I don't know why that is. Maybe it just grows that much during a normal day?

I suspect that the culprit is this call here: https://github.com/glynnbird/birdreader/blob/master/includes/feed.js#L156

Am I correctly interpreting this to mean that all the documents in the feeds database are written every time feeds are fetched?

It seems that a better solution would be to only write the feeds documents that have changed.

I can probably implement this some day, but I wanted to check if I have understood correctly and if you agree :)

server_admin error

I've done npm i and tweaked just the cloudant bits in config.json as well as setup an API key/secret with _admin privs on both the articles and feeds databases.

But I get this when running:

$ node birdreader.js
   info  - socket.io started
Checking feeds database
Listening on port 3000
Database error - server_admin access is required for this request

I've double checked the _security objects and confirmed that the API key is setup as an _admin.

Is it hitting a different database that needs to be writeable via this key?

Cheers!
๐ŸŽฉ

Configuration issue

I've gotten the reader to run, but when I hit the page in my browser I get:

TypeError: /Users/mike/dev/birdreader/views/index.jade:13
    11|         h1 #{title}
    12|         p 
  > 13|         p #{articles.length} #{title} articles
    14|         p 
    15|         div.spacer
    16|       

Cannot read property 'length' of undefined
at eval (eval at (/Users/mike/dev/birdreader/node_modules/jade/lib/jade.js:176:8), :307:40)
at /Users/mike/dev/birdreader/node_modules/jade/lib/jade.js:181:12
at Object.exports.render (/Users/mike/dev/birdreader/node_modules/jade/lib/jade.js:216:14)
at View.exports.renderFile as engine
at View.render (/Users/mike/dev/birdreader/node_modules/express/lib/view.js:75:8)
at Function.app.render (/Users/mike/dev/birdreader/node_modules/express/lib/application.js:504:10)
at ServerResponse.res.render (/Users/mike/dev/birdreader/node_modules/express/lib/response.js:753:7)
at /Users/mike/dev/birdreader/birdreader.js:48:11
at /Users/mike/dev/birdreader/includes/article.js:16:5
at Object.exports.handle (/Users/mike/dev/birdreader/node_modules/nano/node_modules/errs/lib/errs.js:198:5)

When I look at my local CouchDB in Futon, I din't see an birdreader db's, so I created a "feeds" and an "articles" db, did an import of the sample xml file (nothing imported), and even inserted your sample docs from the .md file....but still the same error.

I'm running on a Mac.

Oh, one other dependency I learned - I needed to install 'make' before the npm install would work, until then I got errors when (I think it was) extractor-js wanted to run make.

Thanks,
Mike

Tags for individual articles

I personally need to be able to tag each article ... and to browse articles by tag.

The API should have related methods to retrieve articles by article tags.

Have glanced through the code and see it would be easy to add this to the schema. Then a dialog for adding tags, ..etc..

crash when fetching feeds

I think this crash is happening while feeds are being read without me using the app in a browser.

Checking feeds database
Listening on port 3000
Checking articles database
Checking views

crypto.js:176
this._binding.update(data);
^
TypeError: Not a buffer
at Hash.update (crypto.js:176:17)
at FeedParser. (/usr/home/mike/birdreader/includes/feed.js:42:16)
at FeedParser.EventEmitter.emit (events.js:95:17)
at /usr/home/mike/birdreader/node_modules/feedparser/main.js:967:15
at process._tickCallback (node.js:415:13)

Can't install : Cannot call method 'use' of undefined

I tried to install birdreader, I've configured my cloudant db correctly, i've created the feeds, articles and views dbs, bur when I finally try to launch birdreader using node birdreader.js, it throws me an error

/var/lib/stickshift/51f282bd5004461ccc000049/app-root/data/569723/includes/cloudant.js:11                                                                                                                       
var feeds = nano.db.use('feeds');                                                                                                                                                                               
                    ^                                                                                                                                                                                           
TypeError: Cannot call method 'use' of undefined                                                                                                                                                                
    at Object.<anonymous> (/var/lib/stickshift/51f282bd5004461ccc000049/app-root/data/569723/includes/cloudant.js:11:21)                                                                                        
    at Module._compile (module.js:449:26)                                                                                                                                                                       
    at Object.Module._extensions..js (module.js:467:10)                                                                                                                                                         
    at Module.load (module.js:356:32)                                                                                                                                                                           
    at Function.Module._load (module.js:312:12)                                                                                                                                                                 
    at Module.require (module.js:362:17)                                                                                                                                                                        
    at require (module.js:378:17)                                                                                                                                                                               
    at Object.<anonymous> (/var/lib/stickshift/51f282bd5004461ccc000049/app-root/data/569723/birdreader.js:3:16)                                                                                                
    at Module._compile (module.js:449:26)                                                                                                                                                                       
    at Object.Module._extensions..js (module.js:467:10) 

I've tried to reinstall nano, but it didn't worked
Thanks in advance if someone have any ideas.

automatic feeds compaction

I have left birdreader running for a few days with about 80 feeds.

Initially the db size is < 1mb but after its left for a few days it has grown to about 30 mb.

A new schedule which runs daily to compact the feeds db automatically would stop the feeds db growing too large.

Error on page view

Having installed on my local server, I load port 3000. All I see is the menu bar, and the terminal return the following:

    10|     div.span10
    11|       div.feedName

> 12|         a.feedlink(href="/"+type+"/byfeed/"+escape(article.feedName.replace("/","%2F"))) @#{article.feedName}
>     13|         if article.icon != null
>     14|           img.miniicon(src=article.icon)
>     15|         span.tags.ml10

Cannot call method 'replace' of undefined
    at eval (eval at <anonymous> (/var/www/birdreader/node_modules/jade/lib/jade.js:176:8), <anonymous>:66:70)
    at /var/www/birdreader/node_modules/jade/lib/jade.js:181:12
    at Object.exports.render (/var/www/birdreader/node_modules/jade/lib/jade.js:216:14)
    at View.exports.renderFile [as engine](/var/www/birdreader/node_modules/jade/lib/jade.js:243:13)
    at View.render (/var/www/birdreader/node_modules/express/lib/view.js:75:8)
    at Function.app.render (/var/www/birdreader/node_modules/express/lib/application.js:504:10)
    at ServerResponse.res.render (/var/www/birdreader/node_modules/express/lib/response.js:753:7)
    at /var/www/birdreader/birdreader.js:312:9
    at /var/www/birdreader/node_modules/async/lib/async.js:227:13
    at /var/www/birdreader/node_modules/async/lib/async.js:107:25```

remove feed just opens window with false

If i try to remove a feed the address bar changes to:

javascript:removeFeed('f771ac4b0f352ddb82acfc2683028f2e')

and the document window contains "false"

I get a similar issue when deleting tags from a feed and the address bar becomes:

javascript:removeTag('f771ac4b0f352ddb82acfc268300bb98','something')

again with false as the page content

I'm using FireFox

Fails to resolve relative URLs when adding an RSS feed

When adding an URL with a <link> element with a relative href attribute, birdreader assumes that this link is absolute.

Instead, it should be resolved as relative to the current document, for example using url.resolve(htmlUrl, feedUrl).

Example of problematic page: http://jimbenton.com/page14/page14.html

Excerpt: <link rel="alternate" type="application/rss+xml" title="Comics" href="files/feed.xml"/>

Notice that the href attribute is relative, and the absolute URL to the RSS feed is therefore http://jimbenton.com/page14/files/feed.xml

Accept RSS links to the /api/feed/add endpoint

Apparently, you are supposed to pass the URL to a web page which has a <link> to an RSS feed.

This is all well and good, but it should also accept URLs that go directly to RSS feeds, since that is after all what it requires in the end. It might even be necessary to disambiguate when a web page has several RSS links.

As it happens, I've been trying to add RSS URLs for a long while and just sighed and walked away when I inevitably got a nondescript error message (See also #21)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.