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 datetime import datetime, timedelta
from PyQt4.Qt import QDialog, QApplication, QLineEdit, QPalette, SIGNAL, QBrush, \ from PyQt4.Qt import QDialog, QApplication, QLineEdit, QPalette, SIGNAL, QBrush, \
QColor, QAbstractListModel, Qt, QVariant, QFont, QIcon, \ QColor, QAbstractListModel, Qt, QVariant, QFont, QIcon, \
QFile, QObject, QTimer, QMutex QFile, QObject, QTimer, QMutex, QMenu, QAction
from calibre import english_sort from calibre import english_sort
from calibre.gui2.dialogs.scheduler_ui import Ui_Dialog 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.utils.pyparsing import ParseException
from calibre.gui2 import NONE, error_dialog from calibre.gui2 import NONE, error_dialog
from calibre.utils.config import DynamicConfig from calibre.utils.config import DynamicConfig
from calibre.gui2.dialogs.user_profiles import UserProfiles
config = DynamicConfig('scheduler') config = DynamicConfig('scheduler')
@ -307,6 +308,23 @@ class Scheduler(QObject):
self.dirtied = False self.dirtied = False
self.connect(self.timer, SIGNAL('timeout()'), self.check) self.connect(self.timer, SIGNAL('timeout()'), self.check)
self.timer.start(int(self.INTERVAL * 60000)) 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): def debug(self, *args):
if self.verbose: if self.verbose:
@ -387,7 +405,7 @@ class Scheduler(QObject):
def refresh_schedule(self, recipes): def refresh_schedule(self, recipes):
self.recipes = recipes self.recipes = recipes
def show_dialog(self): def show_dialog(self, *args):
self.lock.lock() self.lock.lock()
try: try:
d = SchedulerDialog(self.main.library_view.model().db) 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 import sys, os, logging
from calibre.web.feeds.recipes import get_builtin_recipe, compile_recipe, titles 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.fetch.simple import option_parser as _option_parser
from calibre.web.feeds.news import Profile2Recipe, BasicNewsRecipe from calibre.web.feeds.news import BasicNewsRecipe
from calibre.ebooks.lrf.web.profiles import DefaultProfile, FullContentProfile
from calibre.utils.config import Config, StringConfig from calibre.utils.config import Config, StringConfig
def config(defaults=None): 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) pb = ProgressBar(term, _('Fetching feeds...'), no_progress_bar=opts.no_progress_bar)
notification = pb.update notification = pb.update
recipe, is_profile = None, False recipe = None
if opts.feeds is not None: if opts.feeds is not None:
recipe = BasicNewsRecipe recipe = BasicNewsRecipe
else: else:
try: try:
if os.access(recipe_arg, os.R_OK): if os.access(recipe_arg, os.R_OK):
recipe = compile_recipe(open(recipe_arg).read()) recipe = compile_recipe(open(recipe_arg).read())
is_profile = DefaultProfile in recipe.__bases__ or \
FullContentProfile in recipe.__bases__
else: else:
raise Exception('not file') raise Exception('not file')
except: except:
recipe, is_profile = get_builtin_recipe(recipe_arg) recipe = get_builtin_recipe(recipe_arg)
if recipe is None: if recipe is None:
recipe = compile_recipe(recipe_arg) recipe = compile_recipe(recipe_arg)
is_profile = DefaultProfile in recipe.__bases__ or \
FullContentProfile in recipe.__bases__
if recipe is None: if recipe is None:
raise RecipeError(recipe_arg+ ' is an invalid recipe') 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 handler.setFormatter(ColoredFormatter('%(levelname)s: %(message)s\n')) # The trailing newline is need because of the progress bar
logging.getLogger('feeds2disk').addHandler(handler) logging.getLogger('feeds2disk').addHandler(handler)
if is_profile: recipe = recipe(opts, parser, notification)
recipe = Profile2Recipe(recipe, opts, parser, notification)
else:
recipe = recipe(opts, parser, notification)
if not os.path.exists(recipe.output_dir): if not os.path.exists(recipe.output_dir):
os.makedirs(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 option_parser as web2disk_option_parser
from calibre.web.fetch.simple import RecursiveFetcher from calibre.web.fetch.simple import RecursiveFetcher
from calibre.utils.threadpool import WorkRequest, ThreadPool, NoResultsPending from calibre.utils.threadpool import WorkRequest, ThreadPool, NoResultsPending
from calibre.ebooks.lrf.web.profiles import FullContentProfile
from calibre.ptempfile import PersistentTemporaryFile from calibre.ptempfile import PersistentTemporaryFile
@ -359,19 +358,19 @@ class BasicNewsRecipe(object, LoggingInterface):
''' '''
if re.match(r'\w+://', url_or_raw): if re.match(r'\w+://', url_or_raw):
f = self.browser.open(url_or_raw) f = self.browser.open(url_or_raw)
raw = f.read() _raw = f.read()
f.close() f.close()
if not raw: if not _raw:
raise RuntimeError('Could not fetch index from %s'%url_or_raw) raise RuntimeError('Could not fetch index from %s'%url_or_raw)
else: else:
raw = url_or_raw _raw = url_or_raw
if raw: if raw:
return raw return _raw
if not isinstance(raw, unicode) and self.encoding: if not isinstance(_raw, unicode) and self.encoding:
raw = raw.decode(self.encoding) _raw = _raw.decode(self.encoding)
massage = list(BeautifulSoup.MARKUP_MASSAGE) massage = list(BeautifulSoup.MARKUP_MASSAGE)
massage.append((re.compile(r'&(\S+?);'), lambda match: entity_to_unicode(match, encoding=self.encoding))) 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): def sort_index_by(self, index, weights):
@ -943,34 +942,6 @@ class BasicNewsRecipe(object, LoggingInterface):
nmassage.extend(entity_replace) nmassage.extend(entity_replace)
return BeautifulSoup(raw, markupMassage=nmassage) 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): class CustomIndexRecipe(BasicNewsRecipe):
def custom_index(self): def custom_index(self):

View File

@ -12,13 +12,13 @@ recipe_modules = [
'discover_magazine', 'scientific_american', 'new_york_review_of_books', 'discover_magazine', 'scientific_american', 'new_york_review_of_books',
'daily_telegraph', 'guardian', 'el_pais', 'new_scientist', 'b92', 'daily_telegraph', 'guardian', 'el_pais', 'new_scientist', 'b92',
'politika', 'moscow_times', 'latimes', 'japan_times', 'san_fran_chronicle', '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 import re, imp, inspect, time, os
from calibre.web.feeds.news import BasicNewsRecipe, CustomIndexRecipe, AutomaticNewsRecipe from calibre.web.feeds.news import BasicNewsRecipe, CustomIndexRecipe, AutomaticNewsRecipe
from calibre.ebooks.lrf.web.profiles import DefaultProfile, FullContentProfile 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.ebooks.BeautifulSoup import BeautifulSoup
from calibre.path import path from calibre.path import path
from calibre.ptempfile import PersistentTemporaryDirectory from calibre.ptempfile import PersistentTemporaryDirectory
@ -95,13 +95,10 @@ def get_builtin_recipe(title):
''' '''
for r in recipes: for r in recipes:
if r.title == title: if r.title == title:
return r, False return r
for p in builtin_profiles: return None
if p.title == title:
return p, True
return None, False
_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.sort(cmp=english_sort)
titles = _titles 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', '')