# -*- coding: iso-8859-1 -*-
# Copyright (C) 2004-2005 Tristan Seligmann and Jonathan Jacobs
import os
import time
try:
from urllib.parse import quote as url_quote
except ImportError:
from urllib import quote as url_quote
import codecs
import json
from . import rss, util, configuration
from .output import out
# Maximum width or height to display an image in exported pages.
# Note that only the displayed size is adjusted, not the image itself.
MaxImageSize = (800, 800)
class EventHandler(object):
"""Base class for writing events to files. The currently defined events are
start(), comicDownloaded() and end()."""
def __init__(self, basepath, baseurl):
"""Initialize base path and url."""
self.basepath = basepath
self.baseurl = baseurl or self.getBaseUrl()
def getBaseUrl(self):
'''Return a file: URL that probably points to the basedir.
This is used as a halfway sane default when the base URL is not
provided; not perfect, but should work in most cases.'''
components = util.splitpath(os.path.abspath(self.basepath))
url = '/'.join([url_quote(component, '') for component in components])
return 'file:///' + url + '/'
def getUrlFromFilename(self, filename):
"""Construct URL from filename."""
components = util.splitpath(util.getRelativePath(self.basepath, filename))
url = '/'.join([url_quote(component, '') for component in components])
return self.baseurl + url
def start(self):
"""Emit a start event. Should be overridden in subclass."""
pass
def comicDownloaded(self, comic, filename, text=None):
"""Emit a comic downloaded event. Should be overridden in subclass."""
pass
def comicPageLink(self, comic, url, prevUrl):
"""Emit an event to inform the handler about links between comic pages. Should be overridden in subclass."""
pass
def end(self):
"""Emit an end event. Should be overridden in subclass."""
pass
class RSSEventHandler(EventHandler):
"""Output in RSS format."""
name = 'rss'
def getFilename(self):
"""Return RSS filename."""
return os.path.abspath(os.path.join(self.basepath, 'dailydose.rss'))
def start(self):
"""Log start event."""
today = time.time()
yesterday = today - 86400
today = time.localtime(today)
yesterday = time.localtime(yesterday)
link = configuration.Url
self.rssfn = self.getFilename()
if os.path.exists(self.rssfn):
self.newfile = False
self.rss = rss.parseFeed(self.rssfn, yesterday)
else:
self.newfile = True
self.rss = rss.Feed('Daily Dosage', link, 'Comics for %s' % time.strftime('%Y/%m/%d', today))
def comicDownloaded(self, comic, filename, text=None):
"""Write RSS entry for downloaded comic."""
imageUrl = self.getUrlFromFilename(filename)
size = getDimensionForImage(filename, MaxImageSize)
title = '%s - %s' % (comic.name, os.path.basename(filename))
pageUrl = comic.referrer
description = ''
if text:
description += '
%s' % text
description += '
View Comic Online' % pageUrl
args = (
title,
imageUrl,
description,
util.rfc822date(time.time())
)
if self.newfile:
self.newfile = False
self.rss.addItem(*args)
else:
self.rss.addItem(*args, append=False)
def end(self):
"""Write RSS data to file."""
self.rss.write(self.rssfn)
def getDimensionForImage(filename, maxsize):
"""Return scaled image size in (width, height) format.
The scaling preserves the aspect ratio.
If PIL is not found returns None."""
try:
from PIL import Image
except ImportError:
return None
img = Image.open(filename)
width, height = img.size
if width > maxsize[0] or height > maxsize[1]:
img.thumbnail(maxsize)
out.info("Downscaled display size from %s to %s" % ((width, height), img.size))
return img.size
class HtmlEventHandler(EventHandler):
"""Output in HTML format."""
name = 'html'
encoding = 'utf-8'
def fnFromDate(self, date):
"""Get filename from date."""
fn = time.strftime('comics-%Y%m%d', date)
fn = os.path.join(self.basepath, 'html', fn + ".html")
fn = os.path.abspath(fn)
return fn
def addNavLinks(self):
if self.yesterdayUrl:
self.html.write(u'Previous Day | ' % self.yesterdayUrl)
self.html.write(u'Next Day\n' % self.tomorrowUrl)
def start(self):
"""Start HTML output."""
today = time.time()
yesterday = today - 86400
tomorrow = today + 86400
today = time.localtime(today)
yesterday = time.localtime(yesterday)
tomorrow = time.localtime(tomorrow)
fn = self.fnFromDate(today)
if os.path.exists(fn):
out.warn('HTML output file %r already exists' % fn)
out.warn('the page link of previous run will skip this file')
out.warn('try to generate HTML output only once per day')
fn = util.getNonexistingFile(fn)
d = os.path.dirname(fn)
if not os.path.isdir(d):
os.makedirs(d)
try:
fn_yesterday = self.fnFromDate(yesterday)
fn_yesterday = util.getExistingFile(fn_yesterday)
self.yesterdayUrl = self.getUrlFromFilename(fn_yesterday)
except ValueError:
self.yesterdayUrl = None
self.tomorrowUrl = self.getUrlFromFilename(self.fnFromDate(tomorrow))
self.html = codecs.open(fn, 'w', self.encoding)
self.html.write(u'''