From 4cc07fc8e589fc74b7ad90c079842b1b0d20a8bc Mon Sep 17 00:00:00 2001 From: Samuel Clay Date: Fri, 9 Sep 2011 17:43:10 -0700 Subject: [PATCH] Adding in Python API. Needs some love to get the rest of the api up to standard. --- api/__init__.py | 0 api/newsblur.py | 370 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 370 insertions(+) create mode 100644 api/__init__.py create mode 100644 api/newsblur.py diff --git a/api/__init__.py b/api/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/newsblur.py b/api/newsblur.py new file mode 100644 index 000000000..fa1f0648e --- /dev/null +++ b/api/newsblur.py @@ -0,0 +1,370 @@ +# Original API work by Dananjaya Ramanayake +# Retooled by Samuel Clay, August 2011 + +import urllib, urllib2 +import cookielib +import json + +__author__ = "Dananjaya Ramanayake , Samuel Clay " +__version__ = "1.0" + +API_URL = "http://www.newsblur.com/" +# API_URL = "http://nb.local.host:8000/" + + +class request(): + + opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookielib.CookieJar())) + + def __init__(self, endpoint=None, method='get'): + self.endpoint = endpoint + self.method = method + + def __call__(self, func): + def wrapped(*args, **kwargs): + params = func(*args, **kwargs) or {} + url = self.endpoint + if not url: + url = params['url'] + del params['url'] + params = urllib.urlencode(params) + url = "%s%s" % (API_URL, url) + + response = self.opener.open(url, params).read() + + return json.loads(response) + return wrapped + +class API: + + @request('api/login', method='post') + def login(self, username, password): + ''' + Login as an existing user. + If a user has no password set, you cannot just send any old password. + Required parameters, username and password, must be of string type. + ''' + return { + 'username': username, + 'password': password + } + + @request('api/logout') + def logout(self): + ''' + Logout the currently logged in user. + ''' + return + + @request('api/signup') + def signup(self, username, password, email): + ''' + Create a new user. + All three required parameters must be of type string. + ''' + return { + 'signup_username': username, + 'signup_password': password, + 'signup_email': email + } + + @request('rss_feeds/search_feed') + def search_feed(self, address, offset=0): + ''' + Retrieve information about a feed from its website or RSS address. + Parameter address must be of type string while parameter offset must be an integer. + Will return a feed. + ''' + return { + 'address': address, + 'offset': offset + } + + @request('reader/feeds') + def feeds(self, include_favicons=True, flat=False): + ''' + Retrieve a list of feeds to which a user is actively subscribed. + Includes the 3 unread counts (positive, neutral, negative), as well as optional favicons. + ''' + return { + 'include_favicons': include_favicons, + 'flat': flat + } + + @request('reader/favicons') + def favicons(self, feeds=None): + ''' + Retrieve a list of favicons for a list of feeds. + Used when combined with /reader/feeds and include_favicons=false, so the feeds request contains far less data. + Useful for mobile devices, but requires a second request. + ''' + return { + 'feeds': feeds + } + + @request(None) + def page(self, feed_id): + ''' + Retrieve the original page from a single feed. + ''' + return { + 'url': 'reader/page/%s' % feed_id + } + + @request(None) + def feed(self, feed_id, page=1): + ''' + Retrieve the stories from a single feed. + ''' + return { + 'url': 'reader/feed/%s' % feed_id, + 'page': page, + } + + @request('reader/refresh_feeds') + def refresh_feeds(self): + ''' + Up-to-the-second unread counts for each active feed. + Poll for these counts no more than once a minute. + ''' + return + + @request('reader/feeds_trainer') + def feeds_trainer(self, feed_id=None): + ''' + Retrieves all popular and known intelligence classifiers. + Also includes user's own classifiers. + ''' + return { + 'feed_id': feed_id, + } + + def statistics(self, id_no): + ''' + + If you only want a user's classifiers, use /classifiers/:id. + Omit the feed_id to get all classifiers for all subscriptions. + + ''' + + url = 'http://www.newsblur.com/rss_feeds/statistics/%d' % id_no + return urllib.urlopen(url).read() + + def feed_autocomplete(self, term): + ''' + + Get a list of feeds that contain a search phrase. + Searches by feed address, feed url, and feed title, in that order. + Will only show sites with 2+ subscribers. + + ''' + url = 'http://www.newsblur.com/rss_feeds/feed_autocomplete' + params = urllib.urlencode({'term':term}) + return urllib.urlopen(url,params).read() + + def read(self, page=1): + ''' + + Retrieve stories from a single feed. + + ''' + url = 'http://www.newsblur.com/reader/feed/%d' % page + return urllib.urlopen(url).read() + + def starred_stories(self, page=1): + ''' + + Retrieve a user's starred stories. + + ''' + url = 'http://www.newsblur.com/reader/starred_stories' + params = urllib.urlencode({'page':page}) + return urllib.urlopen(url,params).read() + + def river_stories(self, feeds,page=1,read_stories_count=0): + ''' + + Retrieve stories from a collection of feeds. This is known as the River of News. + Stories are ordered in reverse chronological order. + + ''' + + url = 'http://www.newsblur.com/reader/river_stories' + params = urllib.urlencode({'feeds':feeds,'page':page,'read_stories_count':read_stories_count}) + return urllib.urlopen(url,params).read() + + def mark_story_as_read(self, story_id,feed_id): + ''' + + Mark stories as read. + Multiple story ids can be sent at once. + Each story must be from the same feed. + + ''' + + url = 'http://www.newsblur.com/reader/mark_story_as_read' + params = urllib.urlencode({'story_id':story_id,'feed_id':feed_id}) + return urllib.urlopen(url,params).read() + + def mark_story_as_starred(self, story_id,feed_id): + ''' + + Mark a story as starred (saved). + + ''' + url = 'http://www.newsblur.com/reader/mark_story_as_starred' + params = urllib.urlencode({'story_id':story_id,'feed_id':feed_id}) + return urllib.urlopen(url,params).read() + + def mark_all_as_read(self, days=0): + ''' + + Mark all stories in a feed or list of feeds as read. + + ''' + url = 'http://www.newsblur.com/reader/mark_all_as_read' + params = urllib.urlencode({'days':days}) + return urllib.urlopen(url,params).read() + + def add_url(self, url,folder='[Top Level]'): + ''' + + Add a feed by its URL. + Can be either the RSS feed or the website itself. + + ''' + url = 'http://www.newsblur.com/reader/add_url' + params = urllib.urlencode({'url':url,'folder':folder}) + return urllib.urlopen(url,params).read() + + + def add_folder(self, folder,parent_folder='[Top Level]'): + ''' + + Add a new folder. + + ''' + + url = 'http://www.newsblur.com/reader/add_folder' + params = urllib.urlencode({'folder':folder,'parent_folder':parent_folder}) + return urllib.urlopen(url,params).read() + + def rename_feed(self, feed_title,feed_id): + ''' + + Rename a feed title. Only the current user will see the new title. + + ''' + url = 'http://www.newsblur.com/reader/rename_feed' + params = urllib.urlencode({'feed_title':feed_title,'feed_id':feed_id}) + return urllib.urlopen(url,params).read() + + def delete_feed(self, feed_id,in_folder): + ''' + + Unsubscribe from a feed. Removes it from the folder. + Set the in_folder parameter to remove a feed from the correct + folder, in case the user is subscribed to the feed in multiple folders. + + ''' + url = 'http://www.newsblur.com/reader/delete_feed' + params = urllib.urlencode({'feed_id':feed_id,'in_folder':in_folder}) + return urllib.urlopen(url,params).read() + + def rename_folder(self, folder_to_rename,new_folder_name,in_folder): + ''' + + Rename a folder. + + ''' + url = 'http://www.newsblur.com/reader/rename_folder' + params = urllib.urlencode({'folder_to_rename':folder_to_rename,'new_folder_name':new_folder_name,'in_folder':in_folder}) + return urllib.urlopen(url,params).read() + + def delete_folder(self, folder_to_delete,in_folder,feed_id): + ''' + + Delete a folder and unsubscribe from all feeds inside. + + ''' + url = 'http://www.newsblur.com/reader/delete_folder' + params = urllib.urlencode({'folder_to_delete':folder_to_delete,'in_folder':in_folder,'feed_id':feed_id}) + return urllib.urlopen(url,params).read() + + + def mark_feed_as_read(self, feed_id): + ''' + + Mark a list of feeds as read. + + ''' + url = 'http://www.newsblur.com/reader/mark_feed_as_read' + params = urllib.urlencode({'feed_id':feed_id}) + return urllib.urlopen(url,params).read() + + + def save_feed_order(self, folders): + ''' + + Reorder feeds and move them around between folders. + The entire folder structure needs to be serialized. + + ''' + + url = 'http://www.newsblur.com/reader/save_feed_order' + params = urllib.urlencode({'folders':folders}) + return urllib.urlopen(url,params).read() + + + def classifier(self, id_no): + ''' + + Get the intelligence classifiers for a user's site. + Only includes the user's own classifiers. + Use /reader/feeds_trainer for popular classifiers. + + ''' + + url = 'http://www.newsblur.com/classifier/%d' % id_no + return urllib.urlopen(url).read() + + + def classifier_save(self, like_type,dislike_type,remove_like_type,remove_dislike_type): + ''' + + Save intelligence classifiers (tags, titles, authors, and the feed) for a feed. + + ''' + url = 'http://www.newsblur.com/classifier/save' + params = urllib.urlencode({'like_[TYPE]':like_type, + 'dislike_[TYPE]':dislike_type, + 'remove_like_[TYPE]':remove_like_type, + 'remove_dislike_[TYPE]':remove_dislike_type}) + return urllib.urlopen(url,params).read() + + + def opml_export(self): + ''' + + Download a backup of feeds and folders as an OPML file. + Contains folders and feeds in XML; useful for importing in another RSS reader. + + ''' + url = 'http://www.newsblur.com/import/opml_export' + return urllib.urlopen(url).read() + + + + def opml_upload(self, opml_file): + ''' + + Upload an OPML file. + + ''' + url = 'http://www.newsblur.com/import/opml_upload' + f = open(opml_file) + params = urllib.urlencode({'file':f}) + f.close() + return urllib.urlopen(url,params).read() + +