IGN:Migrate all remaining profiles to recipes

This commit is contained in:
Kovid Goyal 2008-11-21 14:57:41 -08:00
parent c597cb136c
commit 6c307c1b83
19 changed files with 1298 additions and 155 deletions

View File

@ -11,7 +11,7 @@ import sys, copy
from datetime import datetime, timedelta
from PyQt4.Qt import QDialog, QApplication, QLineEdit, QPalette, SIGNAL, QBrush, \
QColor, QAbstractListModel, Qt, QVariant, QFont, QIcon, \
QFile, QObject, QTimer, QMutex
QFile, QObject, QTimer, QMutex, QMenu, QAction
from calibre import english_sort
from calibre.gui2.dialogs.scheduler_ui import Ui_Dialog
@ -20,6 +20,7 @@ from calibre.utils.search_query_parser import SearchQueryParser
from calibre.utils.pyparsing import ParseException
from calibre.gui2 import NONE, error_dialog
from calibre.utils.config import DynamicConfig
from calibre.gui2.dialogs.user_profiles import UserProfiles
config = DynamicConfig('scheduler')
@ -307,6 +308,23 @@ class Scheduler(QObject):
self.dirtied = False
self.connect(self.timer, SIGNAL('timeout()'), self.check)
self.timer.start(int(self.INTERVAL * 60000))
self.news_menu = QMenu()
self.news_icon = QIcon(':/images/news.svg')
self.scheduler_action = QAction(QIcon(':/images/scheduler.svg'), _('Schedule news download'), self)
self.news_menu.addAction(self.scheduler_action)
self.connect(self.scheduler_action, SIGNAL('triggered(bool)'), self.show_dialog)
self.cac = QAction(QIcon(':/images/user_profile.svg'), _('Add a custom news source'), self)
self.connect(self.cac, SIGNAL('triggered(bool)'), self.customize_feeds)
self.news_menu.addAction(self.cac)
def customize_feeds(self, *args):
main = self.main
d = UserProfiles(main, main.library_view.model().db.get_feeds())
if d.exec_() == QDialog.Accepted:
feeds = tuple(d.profiles())
main.library_view.model().db.set_feeds(feeds)
def debug(self, *args):
if self.verbose:
@ -387,7 +405,7 @@ class Scheduler(QObject):
def refresh_schedule(self, recipes):
self.recipes = recipes
def show_dialog(self):
def show_dialog(self, *args):
self.lock.lock()
try:
d = SchedulerDialog(self.main.library_view.model().db)

View File

@ -0,0 +1,302 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://web.resource.org/cc/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="128"
height="128"
id="svg1307"
sodipodi:version="0.32"
inkscape:version="0.43"
version="1.0"
sodipodi:docbase="/home/pinheiro/Documents/pics/new oxygen/svg"
sodipodi:docname="love.svg">
<defs
id="defs1309">
<linearGradient
inkscape:collect="always"
id="linearGradient2231">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop2233" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop2235" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient2341">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop2343" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop2345" />
</linearGradient>
<linearGradient
id="linearGradient2346">
<stop
style="stop-color:#740000;stop-opacity:1;"
offset="0"
id="stop2348" />
<stop
style="stop-color:#de0000;stop-opacity:1;"
offset="1"
id="stop2350" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient3920">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3922" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop3924" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient3291">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop3293" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop3295" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3291"
id="radialGradient3297"
cx="63.912209"
cy="115.70919"
fx="64.281197"
fy="122.79655"
r="63.912209"
gradientTransform="matrix(1,0,0,0.197802,0,92.82166)"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3920"
id="linearGradient2329"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.206628,0,0,1.077152,-12.11992,-1.687958)"
x1="55.403236"
y1="-10.92763"
x2="38.105381"
y2="73.298271" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3920"
id="linearGradient2331"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.206628,0,0,1.077152,-12.11992,-1.687958)"
x1="55.403236"
y1="-10.92763"
x2="51.263126"
y2="75.70253" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2346"
id="radialGradient2335"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.889512,1.116406,-0.648339,0.415783,49.78673,-44.12721)"
cx="73.892921"
cy="68.238869"
fx="113.793"
fy="80.440765"
r="55.221321" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3920"
id="linearGradient2337"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.206628,0,0,1.077152,-12.11992,-1.687958)"
x1="55.403236"
y1="-10.92763"
x2="38.105381"
y2="73.298271" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2341"
id="radialGradient2347"
cx="59.546715"
cy="28.174582"
fx="59.546715"
fy="28.174582"
r="26.231683"
gradientTransform="matrix(-2.168694,-0.188332,3.730754e-2,-0.384145,188.3757,35.26743)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2341"
id="radialGradient2357"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-1.200784,-1.060566,0.288936,-0.294487,193.2397,94.74366)"
cx="66.450279"
cy="21.283276"
fx="66.450279"
fy="21.283276"
r="26.231683" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3291"
id="linearGradient2379"
x1="46.890835"
y1="117.57981"
x2="39.447845"
y2="-0.39157665"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.039896,0,0,0.983324,-2.59869,1.904676)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2231"
id="linearGradient2239"
x1="61.962692"
y1="28.706591"
x2="104.65211"
y2="4.5699611"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="7.851329"
inkscape:cx="92.691163"
inkscape:cy="92.473338"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:document-units="px"
inkscape:grid-bbox="true"
guidetolerance="0.1px"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1106"
inkscape:window-height="958"
inkscape:window-x="597"
inkscape:window-y="25">
<sodipodi:guide
orientation="horizontal"
position="32.487481"
id="guide2204" />
</sodipodi:namedview>
<metadata
id="metadata1312">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<cc:license
rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
<dc:contributor>
<cc:Agent>
<dc:title>Oxygen team</dc:title>
</cc:Agent>
</dc:contributor>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/LGPL/2.1/">
<cc:permits
rdf:resource="http://web.resource.org/cc/Reproduction" />
<cc:permits
rdf:resource="http://web.resource.org/cc/Distribution" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Notice" />
<cc:permits
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
<cc:requires
rdf:resource="http://web.resource.org/cc/ShareAlike" />
<cc:requires
rdf:resource="http://web.resource.org/cc/SourceCode" />
</cc:License>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<path
id="path2279"
d="M 35.325003,6.2016212 C 32.278855,6.2210343 29.04554,6.6687797 25.645659,7.6089396 C 5.9380676,13.058621 0.4047081,29.342118 5.3805919,48.506884 C 12.126039,74.487173 35.002511,100.01571 64.150772,115.92897 C 64.150772,115.92897 64.214086,115.96222 64.218699,115.92897 C 88.214151,102.82886 116.24344,74.487173 122.98888,48.506884 C 127.96476,29.342118 122.43142,13.058621 102.72381,7.6089396 C 83.422212,2.2715254 69.549743,12.840103 64.184735,27.183813 C 59.764745,15.366677 49.572277,6.1108182 35.325003,6.2016212 z "
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#850000;stroke-width:3.27651024;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
sodipodi:nodetypes="cssccsscc" />
<path
sodipodi:nodetypes="ccc"
id="path2276"
d="M 50.892799,3.2812959 L 50.892799,0.48658747 L 50.892799,3.2812959 z "
style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" />
<path
sodipodi:type="arc"
style="opacity:0.38139535;fill:url(#radialGradient3297);fill-opacity:1.0;fill-rule:nonzero;stroke:none;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1"
id="path3289"
sodipodi:cx="63.912209"
sodipodi:cy="115.70919"
sodipodi:rx="63.912209"
sodipodi:ry="12.641975"
d="M 127.82442 115.70919 A 63.912209 12.641975 0 1 1 0,115.70919 A 63.912209 12.641975 0 1 1 127.82442 115.70919 z"
transform="matrix(1,0,0,0.416667,0,74.87151)" />
<path
style="fill:url(#radialGradient2335);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 35.325021,6.2016208 C 32.278871,6.2210338 29.045555,6.6687791 25.645673,7.6089386 C 5.9380713,13.058619 0.404709,29.342113 5.3805953,48.506873 C 12.126047,74.487157 36.855395,101.02725 64.150803,115.92895 L 64.150803,116.02417 C 64.162016,116.00826 64.173539,115.99248 64.184766,115.97656 C 64.195995,115.99248 64.207516,116.00826 64.218732,116.02417 L 64.218732,115.92895 C 90.473794,101.59521 116.24349,74.487157 122.98895,48.506873 C 127.96481,29.342113 122.43148,13.058619 102.72386,7.6089386 C 83.422254,2.2715258 69.549778,12.840101 64.184766,27.183808 C 59.764775,15.366673 49.572303,6.1108179 35.325021,6.2016208 z "
id="path2245"
sodipodi:nodetypes="cssccsccsscc" />
<path
id="path2369"
d="M 35.325021,6.2016208 C 32.278871,6.2210338 29.045555,6.6687791 25.645673,7.6089386 C 5.9380713,13.058619 0.404709,29.342113 5.3805953,48.506873 C 12.126047,74.487157 37.113186,101.16799 64.150803,115.92895 L 64.150803,116.02417 C 64.162016,116.00826 64.173539,115.99248 64.184766,115.97656 C 64.195995,115.99248 64.207516,116.00826 64.218732,116.02417 L 64.218732,115.92895 C 90.398445,101.63635 116.24349,74.487157 122.98895,48.506873 C 127.96481,29.342113 122.43148,13.058619 102.72386,7.6089386 C 83.422254,2.2715258 69.549778,12.840101 64.184766,27.183808 C 59.764775,15.366673 49.572303,6.1108179 35.325021,6.2016208 z "
style="opacity:0.4713115;fill:url(#linearGradient2379);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
sodipodi:nodetypes="cssccsccsscc" />
<path
style="opacity:0.1762295;fill:url(#linearGradient2331);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.29999995;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 34.451605,6.2067207 C 31.659392,6.2976073 28.7301,6.7682297 25.648957,7.6202497 C 7.7889432,12.559022 1.5815371,26.389172 4.2759909,43.204304 C 27.13595,75.72273 65.297627,95.42612 91.41193,91.971053 C 105.43169,77.948778 119.04939,63.70497 122.99185,48.520401 C 127.96773,29.355639 122.42255,13.069929 102.71494,7.6202497 C 83.413331,2.2828362 69.546961,12.850845 64.181949,27.194552 C 59.761957,15.377418 49.555176,6.1159177 35.307894,6.2067207 C 35.022317,6.2085406 34.740456,6.1973187 34.451605,6.2067207 z "
id="path2294" />
<path
style="opacity:0.295082;fill:url(#linearGradient2329);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.29999995;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 34.074837,6.2067207 C 31.40123,6.327282 28.585673,6.8081683 25.648957,7.6202497 C 7.7889432,12.559022 1.5815371,26.389172 4.2759909,43.204304 C 14.203158,57.32576 27.021171,69.025987 40.479876,77.467016 C 43.278422,54.386594 50.897047,36.716838 62.332365,23.015423 C 57.238336,13.260857 47.82992,6.1269134 35.307894,6.2067207 C 35.022317,6.2085406 34.740456,6.1973187 34.451605,6.2067207 C 34.32072,6.210981 34.206328,6.2007914 34.074837,6.2067207 z M 110.62705,10.754597 C 75.197142,25.69524 62.754479,52.64697 57.126131,86.132562 C 69.30317,91.173302 81.267624,93.3132 91.41193,91.971053 C 105.43169,77.948778 119.04939,63.70497 122.99185,48.520401 C 127.22314,32.223444 123.85068,17.994994 110.62705,10.754597 z "
id="path2317" />
<path
id="path2333"
d="M 34.074837,6.2067207 C 31.40123,6.327282 28.585673,6.8081683 25.648957,7.6202497 C 7.7889432,12.559022 1.5815371,26.389172 4.2759909,43.204304 C 31.184915,85.018489 49.453727,34.774522 60.889046,21.073107 C 55.795017,11.318541 47.82992,6.1269134 35.307894,6.2067207 C 35.022317,6.2085406 34.740456,6.1973187 34.451605,6.2067207 C 34.32072,6.210981 34.206328,6.2007914 34.074837,6.2067207 z M 113.51368,12.049474 C 78.08378,26.990118 48.987828,102.16944 91.41193,91.971053 C 105.43169,77.948778 119.04939,63.70497 122.99185,48.520401 C 127.22314,32.223444 124.21152,18.318712 113.51368,12.049474 z "
style="opacity:0.24590167;fill:url(#linearGradient2337);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.29999995;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
sodipodi:nodetypes="csccsscccsc" />
<path
style="fill:url(#radialGradient2347);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 63.954616,25.504463 C 57.619126,11.654419 44.510629,4.3305657 32.757755,5.3620381 C 24.89537,6.0520678 15.05624,11.243628 9.3982031,16.837515 C 15.483601,12.606739 24.500634,8.0843617 32.104855,7.8046225 C 49.170935,7.1839257 60.368466,19.421544 63.954616,25.504463 z "
id="path2339"
sodipodi:nodetypes="cscsc" />
<path
sodipodi:nodetypes="cscsc"
id="path2353"
d="M 125.3599,32.972374 C 123.23625,18.461964 112.55683,8.350014 100.74319,6.375337 C 92.84014,5.0543307 81.674925,7.4407888 74.485767,11.247741 C 81.691818,8.8198624 91.854785,6.8525175 99.384132,8.4919449 C 116.28001,12.177956 123.64021,26.398573 125.3599,32.972374 z "
style="fill:url(#radialGradient2357);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
style="fill:url(#linearGradient2239);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;opacity:0.2295082"
d="M 64.304303,24.878953 C 68.517595,15.711767 74.72671,8.2984861 86.819816,6.0559851 C 76.460541,10.617845 69.900776,17.459411 64.304303,24.878953 z "
id="path1348"
sodipodi:nodetypes="ccc" />
<path
sodipodi:nodetypes="ccc"
id="path2241"
d="M 64.124179,26.905349 C 64.509834,18.368597 74.72671,9.919603 86.639692,6.7764815 C 76.280417,11.338341 67.739287,20.971831 64.124179,26.905349 z "
style="fill:url(#linearGradient2239);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;opacity:0.2295082" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,389 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="128"
height="128"
id="svg2"
sodipodi:version="0.32"
inkscape:version="0.45+devel"
version="1.0"
sodipodi:docbase="/Users/david/Progetti/oxygen-svn/theme/svg/actions"
sodipodi:docname="dialog-close.svgz"
inkscape:output_extension="org.inkscape.output.svgz.inkscape"
inkscape:export-filename="/home/pinheiro/pics/oxygen/scalable/actions/dialog-close.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4">
<linearGradient
id="linearGradient4296">
<stop
id="stop4298"
offset="0"
style="stop-color:#ff0000;stop-opacity:1;" />
<stop
id="stop4300"
offset="1"
style="stop-color:#650000;stop-opacity:1;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4296"
id="linearGradient4272"
gradientUnits="userSpaceOnUse"
x1="328.12448"
y1="120.81158"
x2="336.98077"
y2="87.759453" />
<linearGradient
id="linearGradient7321">
<stop
style="stop-color:#8c0000;stop-opacity:1;"
offset="0"
id="stop7323" />
<stop
style="stop-color:#650000;stop-opacity:1;"
offset="1"
id="stop7325" />
</linearGradient>
<linearGradient
id="linearGradient6740">
<stop
style="stop-color:#4d0000;stop-opacity:0;"
offset="0"
id="stop6742" />
<stop
id="stop6748"
offset="0.5"
style="stop-color:#4d0000;stop-opacity:1;" />
<stop
style="stop-color:#4d0000;stop-opacity:0;"
offset="1"
id="stop6744" />
</linearGradient>
<linearGradient
gradientTransform="matrix(0,1,-1,0,-39.9985,140.0029)"
y2="-383.9971"
x2="-12.0029"
y1="-383.9971"
x1="-84.002403"
gradientUnits="userSpaceOnUse"
id="linearGradient5958">
<stop
id="stop5960"
style="stop-color:#8c0000;stop-opacity:1;"
offset="0" />
<stop
id="stop5962"
style="stop-color:#bf0000;stop-opacity:1;"
offset="1" />
</linearGradient>
<linearGradient
gradientTransform="matrix(0,1,-1,0,-39.9985,140.0029)"
y2="-383.9971"
x2="-12.0029"
y1="-383.9971"
x1="-84.002403"
gradientUnits="userSpaceOnUse"
id="linearGradient4770">
<stop
id="stop4772"
style="stop-color:#ffbe00;stop-opacity:1"
offset="0" />
<stop
id="stop4774"
style="stop-color:#f5d600;stop-opacity:0;"
offset="1" />
</linearGradient>
<linearGradient
gradientTransform="matrix(0,1,-1,0,-39.9985,140.0029)"
y2="-383.9975"
x2="-23.516129"
y1="-383.9971"
x1="-84.002403"
gradientUnits="userSpaceOnUse"
id="linearGradient3711">
<stop
id="stop3713"
style="stop-color:white;stop-opacity:1;"
offset="0" />
<stop
id="stop3715"
style="stop-color:white;stop-opacity:0;"
offset="1" />
</linearGradient>
<linearGradient
id="linearGradient3290">
<stop
style="stop-color:yellow;stop-opacity:1;"
offset="0"
id="stop3292" />
<stop
style="stop-color:#ffb66d;stop-opacity:1;"
offset="1"
id="stop3294" />
</linearGradient>
<linearGradient
id="linearGradient1563">
<stop
id="stop1565"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop1567"
offset="1"
style="stop-color:white;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient3273">
<stop
id="stop3275"
offset="0"
style="stop-color:#ffffff;stop-opacity:0.55035973;" />
<stop
id="stop3277"
offset="1"
style="stop-color:#ffffff;stop-opacity:0;" />
</linearGradient>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath5163">
<circle
sodipodi:ry="36"
sodipodi:rx="36"
sodipodi:cy="92"
sodipodi:cx="343.99899"
style="fill:url(#linearGradient5167);fill-opacity:1"
r="36"
rx="8.0010004"
cx="343.99899"
cy="92"
ry="8.0010004"
id="circle5165" />
</clipPath>
<filter
inkscape:collect="always"
id="filter5943">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="1.04"
id="feGaussianBlur5945" />
</filter>
<filter
inkscape:collect="always"
id="filter7317">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="2.8805897"
id="feGaussianBlur7319" />
</filter>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient7321"
id="linearGradient8922"
gradientUnits="userSpaceOnUse"
x1="351.02234"
y1="65.788521"
x2="309.21854"
y2="82.680611" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4296"
id="linearGradient2390"
gradientUnits="userSpaceOnUse"
x1="328.12448"
y1="120.81158"
x2="336.98077"
y2="87.759453" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4296"
id="linearGradient2997"
gradientUnits="userSpaceOnUse"
x1="328.12448"
y1="120.81158"
x2="336.98077"
y2="87.759453" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3711"
id="linearGradient3003"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0,1.3460321,-1.3460321,0,-112.6741,119.24399)"
x1="-80.00296"
y1="-131.93112"
x2="-45.096584"
y2="-131.93112" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient6740"
id="linearGradient3008"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(20.000035,-56.000003)"
x1="117.81589"
y1="103.01254"
x2="90.537666"
y2="76.633896" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4296"
id="linearGradient3010"
gradientUnits="userSpaceOnUse"
x1="328.12448"
y1="120.81158"
x2="336.98077"
y2="87.759453" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4770"
id="radialGradient3012"
gradientUnits="userSpaceOnUse"
cx="345.80753"
cy="85.250488"
fx="345.80753"
fy="85.250488"
r="36"
gradientTransform="matrix(0.6662862,-0.6560105,0.9893764,1.0048737,31.05592,226.43791)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5958"
id="linearGradient3014"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0,1,-1,0,-39.9985,140.0029)"
x1="-86.120354"
y1="-381.09921"
x2="-56.357521"
y2="-373.1243" />
<filter
inkscape:collect="always"
id="filter3138">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="5.6513927"
id="feGaussianBlur3140" />
</filter>
<filter
inkscape:collect="always"
id="filter3162">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.96794009"
id="feGaussianBlur3164" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4142136"
inkscape:cx="-20.087878"
inkscape:cy="68.366751"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:window-width="1024"
inkscape:window-height="697"
inkscape:window-x="557"
inkscape:window-y="23"
showgrid="true"
gridspacingx="4px"
gridspacingy="4px"
gridempspacing="0"
inkscape:grid-points="true"
showguides="true"
inkscape:guide-bbox="true" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
sodipodi:type="arc"
style="opacity:0.50271737999999999;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.13749998999999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4.15000000000000036;stroke-opacity:1;filter:url(#filter3138)"
id="path2396"
sodipodi:cx="15.5"
sodipodi:cy="20"
sodipodi:rx="100"
sodipodi:ry="100"
d="M 115.5,20 A 100,100 0 1 1 -84.5,20 A 100,100 0 1 1 115.5,20 z"
transform="matrix(0.5662048,0,0,0.5662048,55.73989,54.555422)" />
<circle
sodipodi:ry="36"
sodipodi:rx="36"
sodipodi:cy="92"
sodipodi:cx="343.99899"
style="fill:url(#linearGradient3014);fill-opacity:1"
r="36"
rx="8.0010004"
cx="343.99899"
cy="92"
ry="8.0010004"
id="circle3581_2_"
transform="matrix(-1.5639433,0.4190574,-0.4190574,-1.5639433,641.54821,62.027543)" />
<circle
transform="matrix(-1.1729576,0.3142929,-0.3142929,-1.1729576,497.41122,62.095683)"
id="circle4383"
ry="8.0010004"
cy="92"
cx="343.99899"
rx="8.0010004"
r="36"
style="fill:url(#radialGradient3012);fill-opacity:1;filter:url(#filter3162)"
sodipodi:cx="343.99899"
sodipodi:cy="92"
sodipodi:rx="36"
sodipodi:ry="36" />
<circle
clip-path="url(#clipPath5163)"
transform="matrix(-1.5639433,-0.4190574,-0.4190574,1.5639433,641.54821,62.572542)"
id="circle4776"
ry="8.0010004"
cy="92"
cx="343.99899"
rx="8.0010004"
r="36"
style="opacity:0.8;fill:none;fill-opacity:1;stroke:url(#linearGradient3010);stroke-width:6.75138187;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter7317)"
sodipodi:cx="343.99899"
sodipodi:cy="92"
sodipodi:rx="36"
sodipodi:ry="36" />
<path
style="opacity:0.8;fill:url(#linearGradient3003);fill-opacity:1"
d="M 65.000079,11.557516 C 44.329599,11.557516 27.057531,26.153664 22.894511,45.586895 C 31.192535,53.322386 46.937604,58.542449 65.000079,58.542449 C 83.062575,58.542449 98.807623,53.322386 107.10564,45.586895 C 102.94264,26.153664 85.670553,11.557516 65.000079,11.557516 z"
id="circle16776" />
<g
id="g6850"
transform="matrix(1.2882604,1.2882604,-1.2882604,1.2882604,-45.790405,-141.24514)">
<path
sodipodi:nodetypes="ccccccccccccc"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3008);stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;filter:url(#filter5943)"
d="M 118.00003,15.999997 L 118.00003,31.999997 L 102.00003,31.999997 L 102.00003,39.999997 L 118.00003,39.999997 L 118.00003,55.999997 L 126.00003,55.999997 L 126.00003,39.999997 L 142.00003,39.999997 L 142.00003,31.999997 L 126.00003,31.999997 L 126.00003,15.999997 L 118.00003,15.999997 z"
id="path4123" />
<path
sodipodi:nodetypes="ccccccccccccc"
id="rect3232"
d="M 118.00003,15.999997 L 118.00003,31.999997 L 102.00003,31.999997 L 102.00003,39.999997 L 118.00003,39.999997 L 118.00003,55.999997 L 126.00003,55.999997 L 126.00003,39.999997 L 142.00003,39.999997 L 142.00003,31.999997 L 126.00003,31.999997 L 126.00003,15.999997 L 118.00003,15.999997 z"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,96 +0,0 @@
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
from PyQt4.QtCore import QObject, SIGNAL, QFile
from PyQt4.QtGui import QMenu, QIcon, QDialog, QAction
from calibre.gui2.dialogs.password import PasswordDialog
from calibre.web.feeds.recipes import titles, get_builtin_recipe, compile_recipe
class NewsAction(QAction):
def __init__(self, recipe, parent):
self.recipe = recipe
self.module = recipe.__module__.rpartition('.')[-1]
if QFile(':/images/news/'+self.module+'.png').exists():
ic = QIcon(':/images/news/'+self.module+'.png')
else:
ic = QIcon(':/images/news.svg')
QAction.__init__(self, ic, recipe.title, parent)
QObject.connect(self, SIGNAL('triggered(bool)'), self.fetch_news)
QObject.connect(self, SIGNAL('start_news_fetch(PyQt_PyObject, PyQt_PyObject)'),
parent.fetch_news)
def fetch_news(self, checked):
self.emit(SIGNAL('start_news_fetch(PyQt_PyObject, PyQt_PyObject)'),
self.recipe, self.module)
class NewsMenu(QMenu):
def __init__(self, customize_feeds_func):
QMenu.__init__(self)
self.scheduler = QAction(QIcon(':/images/scheduler.svg'), _('Schedule news download'), self)
self.addAction(self.scheduler)
self.cac = QAction(QIcon(':/images/user_profile.svg'), _('Add a custom news source'), self)
self.connect(self.cac, SIGNAL('triggered(bool)'), customize_feeds_func)
self.addAction(self.cac)
self.addSeparator()
self.custom_menu = CustomNewsMenu()
self.addMenu(self.custom_menu)
self.connect(self.custom_menu, SIGNAL('start_news_fetch(PyQt_PyObject, PyQt_PyObject)'),
self.fetch_news)
self.dmenu = QMenu(self)
self.dmenu.setTitle(_('Download news'))
self.dmenu.setIcon(QIcon(':/images/news.svg'))
self.addMenu(self.dmenu)
for title in titles:
recipe = get_builtin_recipe(title)[0]
self.dmenu.addAction(NewsAction(recipe, self))
def fetch_news(self, recipe, module):
username = password = None
fetch = True
if recipe.needs_subscription:
name = module if module else recipe.title
d = PasswordDialog(self, name + ' info dialog',
_('<p>Please enter your username and password for %s<br>If you do not have one, please subscribe to get access to the articles.<br/> Click OK to proceed.')%(recipe.title,))
d.exec_()
if d.result() == QDialog.Accepted:
username, password = d.username(), d.password()
else:
fetch = False
if fetch:
data = dict(title=recipe.title, username=username, password=password,
script=getattr(recipe, 'gui_recipe_script', None))
self.emit(SIGNAL('fetch_news(PyQt_PyObject)'), data)
def set_custom_feeds(self, feeds):
self.custom_menu.set_feeds(feeds)
class CustomNewMenuItem(QAction):
def __init__(self, title, script, parent):
QAction.__init__(self, QIcon(':/images/user_profile.svg'), title, parent)
self.title = title
self.recipe = compile_recipe(script)
self.recipe.gui_recipe_script = script
class CustomNewsMenu(QMenu):
def __init__(self):
QMenu.__init__(self)
self.setTitle(_('Download custom news'))
self.connect(self, SIGNAL('triggered(QAction*)'), self.launch)
def launch(self, action):
self.emit(SIGNAL('start_news_fetch(PyQt_PyObject, PyQt_PyObject)'),
action.recipe, None)
def set_feeds(self, feeds):
self.clear()
for title, src in feeds:
self.addAction(CustomNewMenuItem(title, src, self))

View File

@ -8,8 +8,7 @@ CLI for downloading feeds.
import sys, os, logging
from calibre.web.feeds.recipes import get_builtin_recipe, compile_recipe, titles
from calibre.web.fetch.simple import option_parser as _option_parser
from calibre.web.feeds.news import Profile2Recipe, BasicNewsRecipe
from calibre.ebooks.lrf.web.profiles import DefaultProfile, FullContentProfile
from calibre.web.feeds.news import BasicNewsRecipe
from calibre.utils.config import Config, StringConfig
def config(defaults=None):
@ -119,23 +118,19 @@ def run_recipe(opts, recipe_arg, parser, notification=None, handler=None):
pb = ProgressBar(term, _('Fetching feeds...'), no_progress_bar=opts.no_progress_bar)
notification = pb.update
recipe, is_profile = None, False
recipe = None
if opts.feeds is not None:
recipe = BasicNewsRecipe
else:
try:
if os.access(recipe_arg, os.R_OK):
recipe = compile_recipe(open(recipe_arg).read())
is_profile = DefaultProfile in recipe.__bases__ or \
FullContentProfile in recipe.__bases__
recipe = compile_recipe(open(recipe_arg).read())
else:
raise Exception('not file')
except:
recipe, is_profile = get_builtin_recipe(recipe_arg)
recipe = get_builtin_recipe(recipe_arg)
if recipe is None:
recipe = compile_recipe(recipe_arg)
is_profile = DefaultProfile in recipe.__bases__ or \
FullContentProfile in recipe.__bases__
if recipe is None:
raise RecipeError(recipe_arg+ ' is an invalid recipe')
@ -148,10 +143,7 @@ def run_recipe(opts, recipe_arg, parser, notification=None, handler=None):
handler.setFormatter(ColoredFormatter('%(levelname)s: %(message)s\n')) # The trailing newline is need because of the progress bar
logging.getLogger('feeds2disk').addHandler(handler)
if is_profile:
recipe = Profile2Recipe(recipe, opts, parser, notification)
else:
recipe = recipe(opts, parser, notification)
recipe = recipe(opts, parser, notification)
if not os.path.exists(recipe.output_dir):
os.makedirs(recipe.output_dir)

View File

@ -22,7 +22,6 @@ from calibre.web.feeds import feed_from_xml, templates, feeds_from_index, Feed
from calibre.web.fetch.simple import option_parser as web2disk_option_parser
from calibre.web.fetch.simple import RecursiveFetcher
from calibre.utils.threadpool import WorkRequest, ThreadPool, NoResultsPending
from calibre.ebooks.lrf.web.profiles import FullContentProfile
from calibre.ptempfile import PersistentTemporaryFile
@ -359,19 +358,19 @@ class BasicNewsRecipe(object, LoggingInterface):
'''
if re.match(r'\w+://', url_or_raw):
f = self.browser.open(url_or_raw)
raw = f.read()
_raw = f.read()
f.close()
if not raw:
if not _raw:
raise RuntimeError('Could not fetch index from %s'%url_or_raw)
else:
raw = url_or_raw
_raw = url_or_raw
if raw:
return raw
if not isinstance(raw, unicode) and self.encoding:
raw = raw.decode(self.encoding)
return _raw
if not isinstance(_raw, unicode) and self.encoding:
_raw = _raw.decode(self.encoding)
massage = list(BeautifulSoup.MARKUP_MASSAGE)
massage.append((re.compile(r'&(\S+?);'), lambda match: entity_to_unicode(match, encoding=self.encoding)))
return BeautifulSoup(raw, markupMassage=massage)
return BeautifulSoup(_raw, markupMassage=massage)
def sort_index_by(self, index, weights):
@ -943,34 +942,6 @@ class BasicNewsRecipe(object, LoggingInterface):
nmassage.extend(entity_replace)
return BeautifulSoup(raw, markupMassage=nmassage)
class Profile2Recipe(BasicNewsRecipe):
'''
Used to migrate the old news Profiles to the new Recipes. Uses the settings
from the old Profile to populate the settings in the Recipe. Also uses, the
Profile's get_browser and parse_feeds.
'''
def __init__(self, profile_class, options, parser, progress_reporter):
self.old_profile = profile_class(logging.getLogger('feeds2disk'),
username=options.username,
password=options.password,
lrf=options.lrf)
for attr in ('preprocess_regexps', 'oldest_article', 'delay', 'timeout',
'match_regexps', 'filter_regexps', 'html2lrf_options',
'timefmt', 'needs_subscription', 'summary_length',
'max_articles_per_feed', 'title','no_stylesheets', 'encoding'):
setattr(self, attr, getattr(self.old_profile, attr))
self.simultaneous_downloads = 1
BasicNewsRecipe.__init__(self, options, parser, progress_reporter)
self.browser = self.old_profile.browser
self.use_embedded_content = isinstance(self.old_profile, FullContentProfile)
def parse_index(self):
feeds = []
for key, val in self.old_profile.parse_feeds().items():
feeds.append((key, val))
return feeds
class CustomIndexRecipe(BasicNewsRecipe):
def custom_index(self):

View File

@ -12,13 +12,13 @@ recipe_modules = [
'discover_magazine', 'scientific_american', 'new_york_review_of_books',
'daily_telegraph', 'guardian', 'el_pais', 'new_scientist', 'b92',
'politika', 'moscow_times', 'latimes', 'japan_times', 'san_fran_chronicle',
'demorgen_be', 'de_standaard'
'demorgen_be', 'de_standaard', 'ap', 'barrons', 'chr_mon', 'cnn', 'faznet',
'jpost', 'jutarnji', 'nasa', 'reuters', 'spiegelde', 'wash_post', 'zeitde',
]
import re, imp, inspect, time, os
from calibre.web.feeds.news import BasicNewsRecipe, CustomIndexRecipe, AutomaticNewsRecipe
from calibre.ebooks.lrf.web.profiles import DefaultProfile, FullContentProfile
from calibre.ebooks.lrf.web import builtin_profiles
from calibre.ebooks.BeautifulSoup import BeautifulSoup
from calibre.path import path
from calibre.ptempfile import PersistentTemporaryDirectory
@ -95,13 +95,10 @@ def get_builtin_recipe(title):
'''
for r in recipes:
if r.title == title:
return r, False
for p in builtin_profiles:
if p.title == title:
return p, True
return None, False
return r
return None
_titles = list(frozenset([r.title for r in recipes] + [p.title for p in builtin_profiles]))
_titles = [r.title for r in recipes]
_titles.sort(cmp=english_sort)
titles = _titles

View File

@ -0,0 +1,39 @@
import re
from calibre.web.feeds.news import BasicNewsRecipe
class AssociatedPress(BasicNewsRecipe):
title = u'Associated Press'
description = 'Global news'
__author__ = 'Kovid Goyal'
use_embedded_content = False
max_articles_per_feed = 15
html2lrf_options = ['--force-page-break-before-tag="chapter"']
preprocess_regexps = [ (re.compile(i[0], re.IGNORECASE | re.DOTALL), i[1]) for i in
[
(r'<HEAD>.*?</HEAD>' , lambda match : '<HEAD></HEAD>'),
(r'<body class="apple-rss-no-unread-mode" onLoad="setup(null)">.*?<!-- start Entries -->', lambda match : '<body>'),
(r'<!-- end apple-rss-content-area -->.*?</body>', lambda match : '</body>'),
(r'<script.*?>.*?</script>', lambda match : ''),
(r'<body.*?>.*?<span class="headline">', lambda match : '<body><span class="headline"><chapter>'),
(r'<tr><td><div class="body">.*?<p class="ap-story-p">', lambda match : '<p class="ap-story-p">'),
(r'<p class="ap-story-p">', lambda match : '<p>'),
(r'Learn more about our <a href="http://apdigitalnews.com/privacy.html">Privacy Policy</a>.*?</body>', lambda match : '</body>'),
]
]
feeds = [ ('AP Headlines', 'http://hosted.ap.org/lineups/TOPHEADS-rss_2.0.xml?SITE=ORAST&SECTION=HOME'),
('AP US News', 'http://hosted.ap.org/lineups/USHEADS-rss_2.0.xml?SITE=CAVIC&SECTION=HOME'),
('AP World News', 'http://hosted.ap.org/lineups/WORLDHEADS-rss_2.0.xml?SITE=SCAND&SECTION=HOME'),
('AP Political News', 'http://hosted.ap.org/lineups/POLITICSHEADS-rss_2.0.xml?SITE=ORMED&SECTION=HOME'),
('AP Washington State News', 'http://hosted.ap.org/lineups/WASHINGTONHEADS-rss_2.0.xml?SITE=NYPLA&SECTION=HOME'),
('AP Technology News', 'http://hosted.ap.org/lineups/TECHHEADS-rss_2.0.xml?SITE=CTNHR&SECTION=HOME'),
('AP Health News', 'http://hosted.ap.org/lineups/HEALTHHEADS-rss_2.0.xml?SITE=FLDAY&SECTION=HOME'),
('AP Science News', 'http://hosted.ap.org/lineups/SCIENCEHEADS-rss_2.0.xml?SITE=OHCIN&SECTION=HOME'),
('AP Strange News', 'http://hosted.ap.org/lineups/STRANGEHEADS-rss_2.0.xml?SITE=WCNC&SECTION=HOME'),
]

View File

@ -0,0 +1,91 @@
##
## web2lrf profile to download articles from Barrons.com
## can download subscriber-only content if username and
## password are supplied.
##
'''
'''
import re
from calibre.web.feeds.news import BasicNewsRecipe
class Barrons(BasicNewsRecipe):
title = 'Barron\'s'
max_articles_per_feed = 50
needs_subscription = True
__author__ = 'Kovid Goyal'
description = 'Weekly publication for investors from the publisher of the Wall Street Journal'
timefmt = ' [%a, %b %d, %Y]'
use_embedded_content = False
no_stylesheets = False
match_regexps = ['http://online.barrons.com/.*?html\?mod=.*?|file:.*']
html2lrf_options = [('--ignore-tables'),('--base-font-size=10')]
##delay = 1
## Don't grab articles more than 7 days old
oldest_article = 7
preprocess_regexps = [(re.compile(i[0], re.IGNORECASE | re.DOTALL), i[1]) for i in
[
## Remove anything before the body of the article.
(r'<body.*?<!-- article start', lambda match: '<body><!-- article start'),
## Remove any insets from the body of the article.
(r'<div id="inset".*?</div>.?</div>.?<p', lambda match : '<p'),
## Remove any reprint info from the body of the article.
(r'<hr size.*?<p', lambda match : '<p'),
## Remove anything after the end of the article.
(r'<!-- article end.*?</body>', lambda match : '</body>'),
]
]
def get_browser(self):
br = BasicNewsRecipe.get_browser()
if self.username is not None and self.password is not None:
br.open('http://commerce.barrons.com/auth/login')
br.select_form(name='login_form')
br['user'] = self.username
br['password'] = self.password
br.submit()
return br
## Use the print version of a page when available.
def print_version(self, url):
return url.replace('/article/', '/article_print/')
## Comment out the feeds you don't want retrieved.
## Because these feeds are sorted alphabetically when converted to LRF, you may want to number them to put them in the order you desire
def get_feeds(self):
return [
('This Week\'s Magazine', 'http://online.barrons.com/xml/rss/3_7510.xml'),
('Online Exclusives', 'http://online.barrons.com/xml/rss/3_7515.xml'),
('Companies', 'http://online.barrons.com/xml/rss/3_7516.xml'),
('Markets', 'http://online.barrons.com/xml/rss/3_7517.xml'),
('Technology', 'http://online.barrons.com/xml/rss/3_7518.xml'),
('Funds/Q&A', 'http://online.barrons.com/xml/rss/3_7519.xml'),
]
## Logout of website
## NOT CURRENTLY WORKING
# def cleanup(self):
# try:
# self.browser.set_debug_responses(True)
# import sys, logging
# logger = logging.getLogger("mechanize")
# logger.addHandler(logging.StreamHandler(sys.stdout))
# logger.setLevel(logging.INFO)
# res = self.browser.open('http://online.barrons.com/logout')
# except:
# import traceback
# traceback.print_exc()

View File

@ -0,0 +1,44 @@
import re
from calibre.web.feeds.news import BasicNewsRecipe
class ChristianScienceMonitor(BasicNewsRecipe):
title = 'Christian Science Monitor'
description = 'Providing context and clarity on national and international news, peoples and cultures'
max_articles_per_feed = 20
__author__ = 'Kovid Goyal'
no_stylesheets = True
use_embedded_content = False
preprocess_regexps = [ (re.compile(i[0], re.IGNORECASE | re.DOTALL), i[1]) for i in
[
(r'<body.*?<div id="story"', lambda match : '<body><div id="story"'),
(r'<div class="pubdate">.*?</div>', lambda m: ''),
(r'Full HTML version of this story which may include photos, graphics, and related links.*</body>',
lambda match : '</body>'),
]]
def parse_index(self):
soup = self.index_to_soup('http://www.csmonitor.com/textedition')
feeds = []
for tag in soup.findAll(['h2', 'p']):
if tag.name == 'h2':
title = self.tag_to_string(tag)
feeds.append((title, []))
elif tag.has_key('class') and tag['class'] == 'story' and feeds:
a = tag.find('a')
if a is not None and a.has_key('href'):
art = {
'title': self.tag_to_string(a),
'url' : 'http://www.csmonitor.com'+a['href'],
'date' : '',
}
a.extract()
art['description'] = self.tag_to_string(tag).strip()
feeds[-1][1].append(art)
return feeds

View File

@ -0,0 +1,51 @@
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
'''
Profile to download CNN
'''
import re
from calibre.web.feeds.news import BasicNewsRecipe
class CNN(BasicNewsRecipe):
title = 'CNN'
description = 'Global news'
timefmt = ' [%d %b %Y]'
__author__ = 'Kovid Goyal'
no_stylesheets = True
use_embedded_content = False
oldest_article = 15
preprocess_regexps = [(re.compile(i[0], re.IGNORECASE | re.DOTALL), i[1]) for i in [
(r'<head>.*?<title', lambda match : '<head><title'),
(r'</title>.*?</head>', lambda match : '</title></head>'),
(r'<body.*?<\!\-\-Article.*?>', lambda match : ''),
(r'<\!\-\-Article End\-\->.*?</body>', lambda match : '</body>'),
(r'(</h\d>)<ul>.*?</ul>', lambda match : match.group(1)), # drop story highlights
(r'<h2>(.*?)</h2><h1>(.*?)</h1>', lambda match : '<h1>' + match.group(1) + '</h1><h2>' + match.group(2) + '</h2>'), # sports uses h2 for main title and h1 for subtitle (???) switch these around
(r'<span class="cnnEmbeddedMosLnk">.*?</span>', lambda match : ''), # drop 'watch more' links
(r'(<div class="cnnstorybody">).*?(<p)', lambda match : match.group(1) + match.group(2)), # drop sports photos
(r'</?table.*?>|</?tr.*?>|</?td.*?>', lambda match : ''), # drop table formatting
(r'<div class="cnnendofstorycontent".*?>.*?</div>', lambda match : ''), # drop extra business links
(r'<a href="#TOP">.*?</a>', lambda match : '') # drop business 'to top' link
] ]
def print_version(self, url):
return 'http://www.printthis.clickability.com/pt/printThis?clickMap=printThis&fb=Y&url=' + url
feeds = [
('Top News', 'http://rss.cnn.com/rss/cnn_topstories.rss'),
('World', 'http://rss.cnn.com/rss/cnn_world.rss'),
('U.S.', 'http://rss.cnn.com/rss/cnn_us.rss'),
('Sports', 'http://rss.cnn.com/rss/si_topstories.rss'),
('Business', 'http://rss.cnn.com/rss/money_latest.rss'),
('Politics', 'http://rss.cnn.com/rss/cnn_allpolitics.rss'),
('Law', 'http://rss.cnn.com/rss/cnn_law.rss'),
('Technology', 'http://rss.cnn.com/rss/cnn_tech.rss'),
('Science & Space', 'http://rss.cnn.com/rss/cnn_space.rss'),
('Health', 'http://rss.cnn.com/rss/cnn_health.rss'),
('Entertainment', 'http://rss.cnn.com/rss/cnn_showbiz.rss'),
('Education', 'http://rss.cnn.com/rss/cnn_education.rss'),
('Offbeat', 'http://rss.cnn.com/rss/cnn_offbeat.rss'),
('Most Popular', 'http://rss.cnn.com/rss/cnn_mostpopular.rss')
]

View File

@ -0,0 +1,28 @@
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
'''
Profile to download FAZ.net
'''
import re
from calibre.web.feeds.news import BasicNewsRecipe
class FazNet(BasicNewsRecipe):
title = 'FAZ NET'
__author__ = 'Kovid Goyal'
description = 'News from Germany'
use_embedded_content = False
max_articles_per_feed = 30
preprocess_regexps = [
(re.compile(r'Zum Thema</span>.*?</BODY>', re.IGNORECASE | re.DOTALL),
lambda match : ''),
]
feeds = [ ('FAZ.NET', 'http://www.faz.net/s/Rub/Tpl~Epartner~SRss_.xml') ]
def print_version(self, url):
return url.replace('.html?rss_aktuell', '~Afor~Eprint.html')

View File

@ -0,0 +1,37 @@
import re
from calibre.web.feeds.news import BasicNewsRecipe
class JerusalemPost(BasicNewsRecipe):
title = 'Jerusalem Post'
description = 'News from Israel and the Middle East'
use_embedded_content = False
__author__ = 'Kovid Goyal'
max_articles_per_feed = 10
preprocess_regexps = [ (re.compile(i[0], re.IGNORECASE | re.DOTALL), i[1]) for i in
[
(r'<HEAD>.*?</HEAD>' , lambda match : '<HEAD></HEAD>'),
(r'<BODY.*?>.*?<!-- start Entries -->', lambda match : '<BODY><!-- start Entries -->'),
(r'<!-- end Entries -->.*?</BODY>', lambda match : '</BODY>'),
(r'<script.*?>.*?</script>', lambda match : ''),
(r'<div class="apple-rss-article apple-rss-read" onclick=.*?<div class="apple-rss-article-body">', lambda match : ''),
(r'<img src=\'/images/logo_NWAnews.gif\' alt=\'NWAnews.com :: Northwest Arkansas\' News Source\'.*?>', lambda match : ''),
(r'<img src=\'/images/logo_adg.gif\'.*?>', lambda match : ''),
(r'<P CLASS="smallprint">.*?</body>', lambda match : '</body>'),
]
]
feeds = [ ('Front Page', 'http://www.jpost.com/servlet/Satellite?pagename=JPost/Page/RSS&cid=1123495333346'),
('Israel News', 'http://www.jpost.com/servlet/Satellite?pagename=JPost/Page/RSS&cid=1178443463156'),
('Middle East News', 'http://www.jpost.com/servlet/Satellite?pagename=JPost/Page/RSS&cid=1123495333498'),
('International News', 'http://www.jpost.com/servlet/Satellite?pagename=JPost/Page/RSS&cid=1178443463144'),
('Editorials', 'http://www.jpost.com/servlet/Satellite?pagename=JPost/Page/RSS&cid=1123495333211'),
]
def print_version(self, url):
return ('http://www.jpost.com/servlet/Satellite?cid=' + url.rpartition('&')[2] + '&pagename=JPost%2FJPArticle%2FPrinter')

View File

@ -0,0 +1,45 @@
'''
Profile to download Jutarnji.hr by Valloric
'''
import re
from calibre.web.feeds.news import BasicNewsRecipe
class Jutarnji(BasicNewsRecipe):
title = 'Jutarnji'
description = 'News from Croatia'
__author__ = 'Valloric'
use_embedded_content = False
timefmt = ' [%d %b %Y]'
max_articles_per_feed = 80
html_description = True
no_stylesheets = True
preprocess_regexps = [
(re.compile(r'<body.*?<span class="vijestnaslov">', re.IGNORECASE | re.DOTALL), lambda match : '<body><span class="vijestnaslov">'),
(re.compile(r'</div>.*?</td>', re.IGNORECASE | re.DOTALL), lambda match : '</div></td>'),
(re.compile(r'<a name="addComment.*?</body>', re.IGNORECASE | re.DOTALL), lambda match : '</body>'),
(re.compile(r'<br>', re.IGNORECASE | re.DOTALL), lambda match : ''),
]
## Getting the print version
def print_version(self, url):
return 'http://www.jutarnji.hr/ispis_clanka.jl?artid=' + url[len(url)-9:len(url)-3]
## Comment out the feeds you don't want retrieved.
## Or add any new new RSS feed URL's here, sorted alphabetically when converted to LRF
## If you want one of these at the top, append a space in front of the name.
feeds = [
(' Naslovnica', 'http://www.jutarnji.hr/rss'),
('Sport', 'http://www.jutarnji.hr/sport/rss'),
('Novac', 'http://www.jutarnji.hr/novac/rss'),
('Kultura i zivot', 'http://www.jutarnji.hr/kultura_i_zivot/rss'),
('Automoto', 'http://www.jutarnji.hr/auto_moto/rss'),
('Hi-Tech', 'http://www.jutarnji.hr/kultura_i_zivot/hi-tech/rss'),
('Dom i nekretnine', 'http://www.jutarnji.hr/nekretnine/rss'),
]

View File

@ -0,0 +1,87 @@
## Copyright (C) 2008 B.Scott Wxby [bswxby] &
## Copyright (C) 2007 David Chen SonyReader<at>DaveChen<dot>org
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## Version 0.3-2008_2_28
## Based on WIRED.py by David Chen, 2007, and newsweek.py, bbc.py, nytimes.py by Kovid Goyal
## https://calibre.kovidgoyal.net/wiki/UserProfiles
##
## Usage:
## >web2lrf --user-profile nasa.py
## Comment out the RSS feeds you don't want in the last section below
##
## Output:
## NASA [YearMonthDate Time].lrf
##
'''
Custom User Profile to download RSS News Feeds and Articles from Wired.com
'''
import re
from calibre.web.feeds.news import BasicNewsRecipe
class NASA(BasicNewsRecipe):
title = 'NASA'
timefmt = ' [%Y%b%d %H%M]'
description = 'News from NASA'
__author__ = 'Scott Wxby & David Chen'
no_stylesheets = True
## Don't grab articles more than 30 days old
oldest_article = 30
preprocess_regexps = [(re.compile(i[0], re.IGNORECASE | re.DOTALL), i[1]) for i in
[
## Fix the encoding to UTF-8
(r'<meta http-equiv="Content-Type" content="text/html; charset=(\S+)"', lambda match : match.group().replace(match.group(1), 'UTF-8')),
## Remove any banners/links/ads/cruft before the body of the article.
(r'<body.*?((<div id="article_body">)|(<div id="st-page-maincontent">)|(<div id="containermain">)|(<p class="ap-story-p">)|(<!-- img_nav -->))', lambda match: '<body><div>'),
## Remove any links/ads/comments/cruft from the end of the body of the article.
(r'((<!-- end article content -->)|(<div id="st-custom-afterpagecontent">)|(<p class="ap-story-p">&copy;)|(<div class="entry-footer">)|(<div id="see_also">)|(<p>Via <a href=)|(<div id="ss_nav">)).*?</html>', lambda match : '</div></body></html>'),
## Correctly embed in-line images by removing the surrounding javascript that will be ignored in the conversion
(r'<a.*?onclick.*?>.*?(<img .*?>)', lambda match: match.group(1),),
## This removes header and footer information from each print version.
(re.compile(r'<!-- Top Header starts -->.*?<!-- Body starts -->', re.IGNORECASE | re.DOTALL), lambda match : '<New Stuff>'),
(re.compile(r'<hr align="center" width="200"><p align="center">.*?<!-- Press Release standard text ends -->', re.IGNORECASE | re.DOTALL), lambda match : '<New Stuff>'),
(re.compile(r'<!-- Top Header starts -->.*?<!---->', re.IGNORECASE | re.DOTALL), lambda match : '<New Stuff>'),
## This removes the "download image" of various sizes from the Image of the day.
(re.compile(r'<div id="download_image_box_print">.*?<div id="caption_region_print">', re.IGNORECASE | re.DOTALL), lambda match : '<New Stuff>'),
]
]
## NASA's print pages differ only by the ending "_prt.htm", so I've replaced them below.
def print_version(self, url):
return url.replace('.html', '_prt.htm')
## Comment out the feeds you don't want retrieved.
## Or add any new new RSS feed URL's here, sorted alphabetically when converted to LRF
## If you want one of these at the top, append a space in front of the name.
feeds = [
(' Breaking News', 'http://www.nasa.gov/rss/breaking_news.rss'),
('Image of the Day', 'http://www.nasa.gov/rss/image_of_the_day.rss'),
('Moon and Mars Exploration', 'http://www.nasa.gov/rss/moon_mars.rss'),
('Shuttle and Station News', 'http://www.nasa.gov/rss/shuttle_station.rss'),
('Solar System News', 'http://www.nasa.gov/rss/solar_system.rss'),
('Universe News', 'http://www.nasa.gov/rss/universe.rss'),
('Earth News', 'http://www.nasa.gov/rss/earth.rss'),
('Aeronautics News', 'http://www.nasa.gov/rss/aeronautics.rss'),
]

View File

@ -0,0 +1,40 @@
import re
from calibre.web.feeds.news import BasicNewsRecipe
class Reuters(BasicNewsRecipe):
title = 'Reuters'
description = 'Global news'
__author__ = 'Kovid Goyal'
use_embedded_content = False
max_articles_per_feed = 10
preprocess_regexps = [ (re.compile(i[0], re.IGNORECASE | re.DOTALL), i[1]) for i in
[
##(r'<HEAD>.*?</HEAD>' , lambda match : '<HEAD></HEAD>'),
(r'<div id="apple-rss-sidebar-background">.*?<!-- start Entries -->', lambda match : ''),
(r'<!-- end apple-rss-content-area -->.*?</body>', lambda match : '</body>'),
(r'<script.*?>.*?</script>', lambda match : ''),
(r'<body>.*?<div class="contentBand">', lambda match : '<body>'),
(r'<h3>Share:</h3>.*?</body>', lambda match : '<!-- END:: Shared Module id=36615 --></body>'),
(r'<div id="atools" class="articleTools">.*?<div class="linebreak">', lambda match : '<div class="linebreak">'),
]
]
feeds = [ ('Top Stories', 'http://feeds.reuters.com/reuters/topNews?format=xml'),
('US News', 'http://feeds.reuters.com/reuters/domesticNews?format=xml'),
('World News', 'http://feeds.reuters.com/reuters/worldNews?format=xml'),
('Politics News', 'http://feeds.reuters.com/reuters/politicsNews?format=xml'),
('Science News', 'http://feeds.reuters.com/reuters/scienceNews?format=xml'),
('Environment News', 'http://feeds.reuters.com/reuters/Environment?format=xml'),
('Technology News', 'http://feeds.reuters.com/reuters/technologyNews?format=xml'),
('Oddly Enough News', 'http://feeds.reuters.com/reuters/oddlyEnoughNews?format=xml')
]
def print_version(self, url):
return ('http://www.reuters.com/article/id' + url + '?sp=true')

View File

@ -0,0 +1,37 @@
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
'''
Fetch Spiegel Online.
'''
import re
from calibre.web.feeds.news import BasicNewsRecipe
class SpeigelOnline(BasicNewsRecipe):
title = 'Spiegel Online'
description = 'News from Germany'
__author__ = 'Kovid Goyal'
use_embedded_content = False
timefmt = ' [ %Y-%m-%d %a]'
max_articles_per_feed = 40
no_stylesheets = True
preprocess_regexps = \
[ (re.compile(i[0], re.IGNORECASE | re.DOTALL), i[1]) for i in
[
# Remove Zum Thema footer
(r'<div class="spArticleCredit.*?</body>', lambda match: '</body>'),
]
]
feeds= [ ('Spiegel Online', 'http://www.spiegel.de/schlagzeilen/rss/0,5291,,00.xml') ]
def print_version(self,url):
tokens = url.split(',')
tokens[-2:-2] = ['druck|']
return ','.join(tokens).replace('|,','-')

View File

@ -0,0 +1,44 @@
import re
from calibre.web.feeds.news import BasicNewsRecipe
class WashingtonPost(BasicNewsRecipe):
title = 'Washington Post'
description = 'US political news'
__author__ = 'Kovid Goyal'
use_embedded_content = False
max_articles_per_feed = 20
preprocess_regexps = [ (re.compile(i[0], re.IGNORECASE | re.DOTALL), i[1]) for i in
[
(r'<HEAD>.*?</HEAD>' , lambda match : '<HEAD></HEAD>'),
(r'<div id="apple-rss-sidebar-background">.*?<!-- start Entries -->', lambda match : ''),
(r'<!-- end apple-rss-content-area -->.*?</body>', lambda match : '</body>'),
(r'<script.*?>.*?</script>', lambda match : ''),
(r'<body.*?>.*?.correction {', lambda match : '<body><style>.correction {'),
(r'<span class="display:none;" name="pubDate".*?>.*?</body>', lambda match : '<body>'),
]
]
feeds = [ ('Today\'s Highlights', 'http://www.washingtonpost.com/wp-dyn/rss/linkset/2005/03/24/LI2005032400102.xml'),
('Politics', 'http://www.washingtonpost.com/wp-dyn/rss/politics/index.xml'),
('Nation', 'http://www.www.washingtonpost.com/wp-dyn/rss/nation/index.xml'),
('World', 'http://www.washingtonpost.com/wp-dyn/rss/world/index.xml'),
('Business', 'http://www.washingtonpost.com/wp-dyn/rss/business/index.xml'),
('Technology', 'http://www.washingtonpost.com/wp-dyn/rss/technology/index.xml'),
('Health', 'http://www.washingtonpost.com/wp-dyn/rss/health/index.xml'),
('Education', 'http://www.washingtonpost.com/wp-dyn/rss/education/index.xml'),
('Editorials', 'http://www.washingtonpost.com/wp-dyn/rss/linkset/2005/05/30/LI2005053000331.xml'),
]
def print_version(self, url):
return (url.rpartition('.')[0] + '_pf.html')

View File

@ -0,0 +1,27 @@
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
'''
Fetch Die Zeit.
'''
from calibre.web.feeds.news import BasicNewsRecipe
class ZeitDe(BasicNewsRecipe):
title = 'Die Zeit Nachrichten'
description = 'News from Germany'
__author__ = 'Kovid Goyal'
use_embedded_content = False
timefmt = ' [%d %b %Y]'
max_articles_per_feed = 40
no_stylesheets = True
encoding = 'latin1'
feeds = [ ('Zeit.de', 'http://newsfeed.zeit.de/news/index') ]
def print_version(self,url):
return url.replace('http://www.zeit.de/', 'http://images.zeit.de/text/').replace('?from=rss', '')