diff --git a/resources/images/news/fstream.png b/resources/images/news/fstream.png new file mode 100644 index 0000000000..a9fc6b4aae Binary files /dev/null and b/resources/images/news/fstream.png differ diff --git a/resources/recipes/fstream.recipe b/resources/recipes/fstream.recipe new file mode 100644 index 0000000000..f6d56042d1 --- /dev/null +++ b/resources/recipes/fstream.recipe @@ -0,0 +1,64 @@ +from calibre.web.feeds.news import BasicNewsRecipe + +class FIELDSTREAM(BasicNewsRecipe): + title = 'Field and Stream' + __author__ = 'Starson17 and Tonythebookworm' + description = 'Hunting and Fishing and Gun Talk' + language = 'en' + no_stylesheets = True + publisher = 'Starson17 and Tonythebookworm' + category = 'food recipes, hunting, fishing, guns' + use_embedded_content= False + no_stylesheets = True + oldest_article = 24 + remove_javascript = True + remove_empty_feeds = True + masthead_url = 'http://www.fieldandstream.com/sites/all/themes/fs/logo.png' + cover_url = 'http://www.arrowheadflyangler.com/Portals/1/Articles/FieldStream/Field%20and%20Stream%20March%20Fishing%20Edition%20Article%20Cover.jpg' + # recursions = 0 + max_articles_per_feed = 10 + INDEX = 'http://www.fieldandstream.com' + + keep_only_tags = [dict(name='div', attrs={'class':['interior-main']}) + ] + remove_tags = [dict(name='div', attrs={'id':['comments']})] + + def parse_index(self): + feeds = [] + for title, url in [ + (u"Wild Chef", u"http://www.fieldandstream.com/blogs/wild-chef"), + (u"The Gun Nut", u"http://www.fieldandstream.com/blogs/gun-nut"), + (u"Whitetail 365", u"http://www.fieldandstream.com/blogs/whitetail-365"), + (u"Fly Talk", u"http://www.fieldandstream.com/blogs/flytalk"), + (u"Generation Wild", u"http://www.fieldandstream.com/blogs/generation-wild"), + (u"Conservationist", u"http://www.fieldandstream.com/blogs/conservationist"), + (u"Honest Angler", u"http://www.fieldandstream.com/blogs/honest-angler"), + (u"Mans Best Friend", u"http://www.fieldandstream.com/blogs/mans-best-friend"), + + ]: + articles = self.make_links(url) + if articles: + feeds.append((title, articles)) + return feeds + + def make_links(self, url): + title = 'Temp' + current_articles = [] + soup = self.index_to_soup(url) + print 'The soup is: ', soup + for item in soup.findAll('h2'): + print 'item is: ', item + link = item.find('a') + print 'the link is: ', link + if link: + url = self.INDEX + link['href'] + title = self.tag_to_string(link) + print 'the title is: ', title + print 'the url is: ', url + print 'the title is: ', title + current_articles.append({'title': title, 'url': url, 'description':'', 'date':''}) # append all this + return current_articles + + + + diff --git a/resources/recipes/winnipeg_free_press.recipe b/resources/recipes/winnipeg_free_press.recipe new file mode 100644 index 0000000000..8c59dff645 --- /dev/null +++ b/resources/recipes/winnipeg_free_press.recipe @@ -0,0 +1,30 @@ +from calibre.web.feeds.news import BasicNewsRecipe + +class WinnipegFreePress(BasicNewsRecipe): + title = u'Winnipeg Free Press' + __author__ = 'buyo' + description = 'News from Winnipeg, Manitoba, Canada' + oldest_article = 1 + max_articles_per_feed = 15 + category = 'News, Winnipeg, Canada' + cover_url = 'http://media.winnipegfreepress.com/designimages/winnipegfreepress_WFP.gif' + no_stylesheets = True + encoding = 'UTF-8' + remove_javascript = True + use_embedded_content = False + language = 'en_CA' + + feeds = [(u'Breaking News', u'http://www.winnipegfreepress.com/rss?path=/breakingnews'), + (u'Local News',u'http://www.winnipegfreepress.com/rss?path=/local'), + (u'Breaking Business News',u'http://www.winnipegfreepress.com/rss?path=/business/finance'), + (u'Business',u'http://www.winnipegfreepress.com/rss?path=/business'), + (u'Editorials',u'http://www.winnipegfreepress.com/rss?path=/opinion/editorials'), + (u'Views from the West',u'http://www.winnipegfreepress.com/rss?path=/opinion/westview'), + (u'Life & Style',u'http://www.winnipegfreepress.com/rss?path=/life'), + (u'Food & Drink',u'http://www.winnipegfreepress.com/rss?path=/life/food') + ] + + keep_only_tags = [ + dict(name='div', attrs={'id':'article_header'}), + dict(name='div', attrs={'class':'article'}), + ] diff --git a/src/calibre/gui2/library/views.py b/src/calibre/gui2/library/views.py index 389208fdcd..966180467c 100644 --- a/src/calibre/gui2/library/views.py +++ b/src/calibre/gui2/library/views.py @@ -229,6 +229,8 @@ class BooksView(QTableView): # {{{ def cleanup_sort_history(self, sort_history): history = [] for col, order in sort_history: + if col == 'date': + col = 'timestamp' if col in self.column_map and (not history or history[0][0] != col): history.append([col, order]) return history diff --git a/src/calibre/library/server/opds.py b/src/calibre/library/server/opds.py index 87a0fecee3..c3a1d68749 100644 --- a/src/calibre/library/server/opds.py +++ b/src/calibre/library/server/opds.py @@ -19,6 +19,7 @@ from calibre.ebooks.metadata import fmt_sidx from calibre.library.comments import comments_to_html from calibre import guess_type from calibre.utils.ordered_dict import OrderedDict +from calibre.utils.date import format_date BASE_HREFS = { 0 : '/stanza', @@ -130,7 +131,7 @@ def CATALOG_GROUP_ENTRY(item, category, base_href, version, updated): link ) -def ACQUISITION_ENTRY(item, version, FM, updated): +def ACQUISITION_ENTRY(item, version, FM, updated, CFM, CKEYS): title = item[FM['title']] if not title: title = _('Unknown') @@ -153,6 +154,21 @@ def ACQUISITION_ENTRY(item, version, FM, updated): extra.append(_('SERIES: %s [%s]
')%\ (series, fmt_sidx(float(item[FM['series_index']])))) + for key in CKEYS: + val = item[CFM[key]['rec_index']] + if val is not None: + name = CFM[key]['name'] + datatype = CFM[key]['datatype'] + if datatype == 'text' and CFM[key]['is_multiple']: + extra.append('%s: %s
'%(name, ', '.join(val.split('|')))) + elif datatype == 'series': + extra.append('%s: %s [%s]
'%(name, val, + fmt_sidx(item[CFM.cc_series_index_column_for(key)]))) + elif datatype == 'datetime': + extra.append('%s: %s
'%(name, + format_date(val, CFM[key]['display'].get('date_format','dd MMM yyyy')))) + else: + extra.append('%s: %s
' % (CFM[key]['name'], val)) comments = item[FM['comments']] if comments: comments = comments_to_html(comments) @@ -260,10 +276,14 @@ class NavFeed(Feed): class AcquisitionFeed(NavFeed): def __init__(self, updated, id_, items, offsets, page_url, up_url, version, - FM): + FM, CFM): NavFeed.__init__(self, id_, updated, version, offsets, page_url, up_url) + CKEYS = [key for key in sorted(CFM.get_custom_fields(), + cmp=lambda x,y: cmp(CFM[x]['name'].lower(), + CFM[y]['name'].lower()))] for item in items: - self.root.append(ACQUISITION_ENTRY(item, version, FM, updated)) + self.root.append(ACQUISITION_ENTRY(item, version, FM, updated, + CFM, CKEYS)) class CategoryFeed(NavFeed): @@ -360,7 +380,7 @@ class OPDSServer(object): cherrypy.response.headers['Last-Modified'] = self.last_modified(updated) cherrypy.response.headers['Content-Type'] = 'application/atom+xml;profile=opds-catalog' return str(AcquisitionFeed(updated, id_, items, offsets, - page_url, up_url, version, self.db.FIELD_MAP)) + page_url, up_url, version, self.db.FIELD_MAP, self.db.field_metadata)) def opds_search(self, query=None, version=0, offset=0): try: @@ -568,7 +588,10 @@ class OPDSServer(object): (_('Newest'), _('Date'), 'Onewest'), (_('Title'), _('Title'), 'Otitle'), ] - for category in categories: + def getter(x): + return category_meta[x]['name'].lower() + for category in sorted(categories, + cmp=lambda x,y: cmp(getter(x), getter(y))): if len(categories[category]) == 0: continue if category == 'formats':