├── README.md └── RSS.py /README.md: -------------------------------------------------------------------------------- 1 | PythonistaRSSReader 2 | =================== 3 | 4 | A super simple RSS reader for use with Pythonista on iOS. To use it, just copy and paste the script in RSS.py to Pythonista and tap the "run" botton in the top right. 5 | 6 | Screenshots 7 | ----------- 8 | 9 | ![img_0019](https://cloud.githubusercontent.com/assets/38447/3350366/932f150c-f9a6-11e3-8ffe-a6f96d2e8895.PNG) 10 | 11 | ![img_0018](https://cloud.githubusercontent.com/assets/38447/3350365/932ea0e0-f9a6-11e3-9a96-ef24e7781522.PNG) 12 | 13 | ![img_0017](https://cloud.githubusercontent.com/assets/38447/3350364/932e52fc-f9a6-11e3-9475-80db5eced582.PNG) 14 | -------------------------------------------------------------------------------- /RSS.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | import ui 4 | import sqlite3 5 | import console 6 | import feedparser 7 | import clipboard 8 | import urlparse 9 | from dateutil.parser import parse as parse_date 10 | 11 | conn = sqlite3.connect('feeds.db') 12 | cursor = conn.execute('pragma user_version') 13 | version = cursor.fetchone()[0] 14 | if version == 0: 15 | conn.execute('BEGIN TRANSACTION') 16 | conn.execute('PRAGMA USER_VERSION=1') 17 | conn.execute('CREATE TABLE feeds (title TEXT UNIQUE, url TEXT UNIQUE)') 18 | conn.commit() 19 | 20 | feeds = [] 21 | for title, url in conn.execute('SELECT * FROM feeds ORDER BY title'): 22 | feeds.append({'title': title, 23 | 'url': url }) 24 | 25 | conn.close() 26 | 27 | class FeedListController(object): 28 | def __init__(self, feeds=[]): 29 | self.feeds = feeds 30 | 31 | def tableview_did_select(self, tableview, section, row): 32 | console.show_activity() 33 | feed = feedparser.parse(self.feeds[row]['url']) 34 | 35 | rss_controller = RSSController(feed) 36 | 37 | tv = ui.TableView() 38 | tv.name = self.feeds[row]['title'] 39 | tv.allows_multiple_selection_during_editing = True 40 | tv.data_source = rss_controller 41 | tv.delegate = rss_controller 42 | 43 | table_view.navigation_view.push_view(tv) 44 | console.hide_activity() 45 | 46 | def tableview_number_of_sections(self, tableview): 47 | return 1 48 | 49 | def tableview_number_of_rows(self, tableview, section): 50 | return len(self.feeds) 51 | 52 | def tableview_cell_for_row(self, tableview, section, row): 53 | cell = ui.TableViewCell() 54 | cell.text_label.text = self.feeds[row]['title'] 55 | return cell 56 | 57 | feed_list_controller = FeedListController(feeds) 58 | 59 | @ui.in_background 60 | def add_feed(sender): 61 | url = console.input_alert('', "Enter RSS feed URL:", 'http://www.macstories.net/feed/') 62 | result = urlparse.urlparse(url) 63 | if result.netloc == '': 64 | url = 'http://www.macstories.net/feed/' 65 | 66 | indicator = ui.ActivityIndicator() 67 | indicator.center = navigation_view.center 68 | navigation_view.add_subview(indicator) 69 | indicator.bring_to_front() 70 | indicator.start() 71 | 72 | feed = feedparser.parse(url) 73 | title = feed['feed']['title'] 74 | 75 | conn = sqlite3.connect('feeds.db') 76 | conn.execute('INSERT INTO feeds VALUES (?, ?)', (title, url)) 77 | conn.commit() 78 | 79 | feeds = [] 80 | for title, url in conn.execute('SELECT * FROM feeds ORDER BY title'): 81 | feeds.append({'title': title, 82 | 'url': url }) 83 | 84 | conn.close() 85 | 86 | feed_list_controller.feeds = feeds 87 | table_view.reload() 88 | indicator.stop() 89 | navigation_view.remove_subview(indicator) 90 | 91 | 92 | class RSSController(object): 93 | def __init__(self, feed): 94 | index = 0 95 | self.feed = feed 96 | self.dates = {} 97 | self.date_indices = [] 98 | 99 | if feed is None: 100 | return 101 | 102 | for entry in self.feed['entries']: 103 | dt = parse_date(entry['published']) 104 | if dt.date() in self.dates: 105 | self.dates[dt.date()].append(entry) 106 | else: 107 | self.dates[dt.date()] = [entry] 108 | self.date_indices.append(dt.date()) 109 | index += 1 110 | 111 | def tableview_did_select(self, tableview, section, row): 112 | entry = self.dates[self.date_indices[section]][row] 113 | webview = ui.WebView() 114 | webview.name = entry['title'] 115 | webview.load_url(entry['link']) 116 | 117 | tableview.navigation_view.push_view(webview) 118 | 119 | def tableview_number_of_sections(self, tableview): 120 | return len(self.dates) 121 | 122 | def tableview_number_of_rows(self, tableview, section): 123 | return len(self.dates[self.date_indices[section]]) 124 | 125 | def tableview_cell_for_row(self, tableview, section, row): 126 | cell = ui.TableViewCell() 127 | cell.text_label.text = self.dates[self.date_indices[section]][row]['title'] 128 | return cell 129 | 130 | def tableview_title_for_header(self, tableview, section): 131 | return str(self.date_indices[section]) 132 | 133 | add_button_item = ui.ButtonItem('Add Feed URL', None, add_feed) 134 | 135 | table_view = ui.TableView() 136 | table_view.name = 'Feeds' 137 | table_view.allows_multiple_selection_during_editing = True 138 | table_view.data_source = feed_list_controller 139 | table_view.delegate = feed_list_controller 140 | 141 | navigation_view = ui.NavigationView(table_view) 142 | navigation_view.right_button_items = [add_button_item] 143 | navigation_view.name = 'RSS Reader' 144 | navigation_view.present('fullscreen') 145 | --------------------------------------------------------------------------------