View Single Post
Old 04-11-2010, 06:13 AM   #1767
hansd
Junior Member
hansd began at the beginning.
 
Posts: 5
Karma: 12
Join Date: Apr 2010
Device: dr1000
StandardMedia.ke

My first published custom recipe.

Upd: Better to use the provided zip file with an updated version (see later)

Code:
__license__   = 'GPL v3'
__copyright__ = '2010, Hans Donner <hans.donner at pobox.com>'
'''
www.standardmedia.co.ke
'''

import os
from contextlib import nested, closing
from calibre import strftime, __appname__, __version__
import calibre.utils.PythonMagickWand as pw
from ctypes import byref
from calibre import fit_image

class StandardMediaKeRecipe(BasicNewsRecipe):
    
    __author__ = 'Hans Donner'

    title = u'The Standard'
    description = 'News from Kenia'
    language = 'en'
    country = 'KE'
    publication_type = 'newspaper' 
    publisher = 'standardmedia.co.ke'
    category = 'news, politics, Kenia'

    cover_img_url = 'http://www.standardmedia.co.ke/images/easLogoOther.gif'
    masthead_url = cover_img_url

    max_articles_per_feed = 200
    oldest_article = 3

    use_embedded_content = False
    remove_empty_feeds = True

    no_stylesheets = False

    feeds = [(u'Headlines', u'http://www.standardmedia.co.ke/rss/headlines.php'),
             (u'Business', u'http://www.standardmedia.co.ke/rss/business.php'),
             (u'Politics', u'http://www.standardmedia.co.ke/rss/politics.php'),
             (u'Editorial', u'http://www.standardmedia.co.ke/rss/editorial.php'),
             (u'Columnists', u'http://www.standardmedia.co.ke/rss/columnists.php'),
             (u'Sports', u'http://www.standardmedia.co.ke/rss/sports.php'),
             (u'Entertainment', u'http://www.standardmedia.co.ke/rss/entertain.php')]

    conversion_options = {
                          'comment'   : description
                        , 'tags'      : category
                        , 'publisher' : publisher
                        , 'language'  : language
                        }


    def print_version(self, url):
        import re
        p = re.compile('http://www.standardmedia.co.ke/.*InsidePage.php')
        return p.sub('http://www.standardmedia.co.ke/print.php', url)

    def preprocess_html(self, soup):
        return self.adeify_images(soup)

    def get_cover_img_url(self):
        return getattr(self, 'cover_img_url', None)

    def _download_cover_img(self):
        self.report_progress(1, _('Try downloading cover img %s') % self.get_cover_img_url())

        self.cover_img_path = None
        try:
            cu = self.get_cover_img_url()
        except Exception, err:
            cu = None
            self.log.error(_('Could not download cover: %s')%str(err))
            self.log.debug(traceback.format_exc())
        if cu is not None:
            ext = cu.split('/')[-1].rpartition('.')[-1]
            if '?' in ext:
                ext = ''
            ext = ext.lower() if ext and '/' not in ext else 'jpg'
            cpath = os.path.join(self.output_dir, 'cover_img_tmp.'+ext)
            if os.access(cu, os.R_OK):
                with open(cpath, 'wb') as cfile:
                    cfile.write(open(cu, 'rb').read())
            else:
                self.report_progress(1, _('Downloading cover from %s')%cu)
                with nested(open(cpath, 'wb'), closing(self.browser.open(cu))) as (cfile, r):
                    cfile.write(r.read())
            if ext.lower() == 'pdf':
                from calibre.ebooks.metadata.pdf import get_metadata
                stream = open(cpath, 'rb')
                mi = get_metadata(stream)
                cpath = None
                if mi.cover_data and mi.cover_data[1]:
                    cpath = os.path.join(self.output_dir,
                            'cover_img_tmp.'+mi.cover_data[0])
                    with open(cpath, 'wb') as f:
                        f.write(mi.cover_data[1])
            outfile = os.path.join(self.output_dir, 'cover_img.jpg')
            self.prepare_masthead_image(cpath, outfile) 
            self.cover_img_path = cpath

    def download_cover_img(self):
        try:
            self._download_cover_img()
            self.report_progress(1, _('Downloaded cover to %s') % self.cover_img_path)
        except:
            self.log.exception('Failed to download cover img')
            self.cover_path = None

    
    def prepare_cover_image(self, path_to_image, out_path):
        with pw.ImageMagick():
            img = pw.NewMagickWand()
            if img < 0:
                raise RuntimeError('Out of memory')
            if not pw.MagickReadImage(img, path_to_image):
                severity = pw.ExceptionType(0)
                msg = pw.MagickGetException(img, byref(severity))
                raise IOError('Failed to read image from: %s: %s'
                        %(path_to_image, msg))
            if not pw.MagickWriteImage(img, out_path):
                raise RuntimeError('Failed to save image to %s'%out_path)
            pw.DestroyMagickWand(img)


    def default_cover(self, cover_file):
        '''
        Create a generic cover for recipes that have a special cover img
        '''
        try:
            try:
                from PIL import Image, ImageDraw, ImageFont
                Image, ImageDraw, ImageFont
            except ImportError:
                import Image, ImageDraw, ImageFont
            font_path = P('fonts/liberation/LiberationSerif-Bold.ttf')
            title = self.title if isinstance(self.title, unicode) else \
                    self.title.decode(preferred_encoding, 'replace')
            date = strftime(self.timefmt)
            app = '['+__appname__ +' '+__version__+']'

            COVER_WIDTH, COVER_HEIGHT = 590, 750
            img = Image.new('RGB', (COVER_WIDTH, COVER_HEIGHT), 'white')
            draw = ImageDraw.Draw(img)
            # Title
            font = ImageFont.truetype(font_path, 44)
            width, height = draw.textsize(title, font=font)
            left = max(int((COVER_WIDTH - width)/2.), 0)
            top = 15
            draw.text((left, top), title, fill=(0,0,0), font=font)
            bottom = top + height
            # Date
            font = ImageFont.truetype(font_path, 32)
            width, height = draw.textsize(date, font=font)
            left = max(int((COVER_WIDTH - width)/2.), 0)
            draw.text((left, bottom+15), date, fill=(0,0,0), font=font)
            # Vanity
            font = ImageFont.truetype(font_path, 28)
            width, height = draw.textsize(app, font=font)
            left = max(int((COVER_WIDTH - width)/2.), 0)
            top = COVER_HEIGHT - height - 15
            draw.text((left, top), app, fill=(0,0,0), font=font)

            # Logo
            logo_file = I('library.png')
            self.download_cover_img()
            if getattr(self, 'cover_img_path', None) is not None:
                logo_file = self.cover_img_path
            self.report_progress(1, _('using cover img from %s') % logo_file)
            logo = Image.open(logo_file, 'r')
            width, height = logo.size
            left = max(int((COVER_WIDTH - width)/2.), 0)
            top = max(int((COVER_HEIGHT - height)/2.), 0)
            img.paste(logo, (left, top))
            img = img.convert('RGB').convert('P', palette=Image.ADAPTIVE)
            img.convert('RGB').save(cover_file, 'JPEG')
            cover_file.flush()
        except Exception, e:
            self.log.exception('Failed to generate default cover ', e)
            return False
        return True

Last edited by hansd; 04-12-2010 at 01:11 AM.
hansd is offline