diff --git a/app.yaml b/app.yaml index 25ba5a28..8bc22b1a 100644 --- a/app.yaml +++ b/app.yaml @@ -1,6 +1,6 @@ # ffd-retief-hrd fanfictiondownloader application: fanfictiondownloader -version: 4-4-25 +version: 4-4-26 runtime: python27 api_version: 1 threadsafe: true diff --git a/calibre-plugin/__init__.py b/calibre-plugin/__init__.py index 7226d5b8..05cccb3c 100644 --- a/calibre-plugin/__init__.py +++ b/calibre-plugin/__init__.py @@ -27,7 +27,7 @@ class FanFictionDownLoaderBase(InterfaceActionBase): description = 'UI plugin to download FanFiction stories from various sites.' supported_platforms = ['windows', 'osx', 'linux'] author = 'Jim Miller' - version = (1, 6, 9) + version = (1, 6, 10) minimum_calibre_version = (0, 8, 57) #: This field defines the GUI plugin class that contains all the code diff --git a/calibre-plugin/config.py b/calibre-plugin/config.py index 59ad45e4..f3422d47 100644 --- a/calibre-plugin/config.py +++ b/calibre-plugin/config.py @@ -64,6 +64,7 @@ default_prefs['countpagesstats'] = [] default_prefs['errorcol'] = '' default_prefs['custom_cols'] = {} default_prefs['custom_cols_newonly'] = {} +default_prefs['allow_custcol_from_ini'] = True default_prefs['std_cols_newonly'] = {} @@ -258,7 +259,7 @@ class ConfigWidget(QWidget): # error column prefs['errorcol'] = unicode(self.cust_columns_tab.errorcol.itemData(self.cust_columns_tab.errorcol.currentIndex()).toString()) - # cust cols + # cust cols tab colsmap = {} for (col,combo) in self.cust_columns_tab.custcol_dropdowns.iteritems(): val = unicode(combo.itemData(combo.currentIndex()).toString()) @@ -272,6 +273,8 @@ class ConfigWidget(QWidget): colsnewonly[col] = checkbox.isChecked() prefs['custom_cols_newonly'] = colsnewonly + prefs['allow_custcol_from_ini'] = self.cust_columns_tab.allow_custcol_from_ini.isChecked() + prefs.save_to_db() def edit_shortcuts(self): @@ -437,7 +440,7 @@ class PersonalIniTab(QWidget): self.ini.setText(prefs['personal.ini']) self.l.addWidget(self.ini) - self.defaults = QPushButton('View Defaults', self) + self.defaults = QPushButton('View Defaults (plugin-defaults.ini)', self) self.defaults.setToolTip("View all of the plugin's configurable settings\nand their default settings.") self.defaults.clicked.connect(self.show_defaults) self.l.addWidget(self.defaults) @@ -456,7 +459,7 @@ class ShowDefaultsIniDialog(QDialog): self.resize(600, 500) self.l = QVBoxLayout() self.setLayout(self.l) - self.label = QLabel("Plugin Defaults (Read-Only)") + self.label = QLabel("Plugin Defaults (plugin-defaults.ini) (Read-Only)") self.label.setToolTip("These are all of the plugin's configurable options\nand their default settings.") self.setWindowTitle(_('Plugin Defaults')) self.setWindowIcon(icon) @@ -595,6 +598,8 @@ class GenerateCoverTab(QWidget): horz.addWidget(dropdown) self.sl.addLayout(horz) + self.sl.insertStretch(-1) + self.gcnewonly = QCheckBox("Run Generate Cover Only on New Books",self) self.gcnewonly.setToolTip("Default is to run GC any time the calibre metadata is updated.") self.gcnewonly.setChecked(prefs['gcnewonly']) @@ -605,8 +610,6 @@ class GenerateCoverTab(QWidget): self.allow_gc_from_ini.setChecked(prefs['allow_gc_from_ini']) self.l.addWidget(self.allow_gc_from_ini) - self.l.insertStretch(-1) - class CountPagesTab(QWidget): def __init__(self, parent_dialog, plugin_action): @@ -838,11 +841,16 @@ class CustomColumnsTab(QWidget): self.sl.insertStretch(-1) + self.l.addSpacing(5) + self.allow_custcol_from_ini = QCheckBox('Allow custom_columns_settings from personal.ini to override',self) + self.allow_custcol_from_ini.setToolTip("The personal.ini parameter custom_columns_settings allows you to set custom columns to site specific values that aren't common to all sites.
custom_columns_settings is ignored when this is off.") + self.allow_custcol_from_ini.setChecked(prefs['allow_custcol_from_ini']) + self.l.addWidget(self.allow_custcol_from_ini) + self.l.addSpacing(5) label = QLabel("Special column:") label.setWordWrap(True) self.l.addWidget(label) - self.l.addSpacing(5) horz = QHBoxLayout() label = QLabel("Update/Overwrite Error Column:") diff --git a/calibre-plugin/ffdl_plugin.py b/calibre-plugin/ffdl_plugin.py index daad8d29..95d97348 100644 --- a/calibre-plugin/ffdl_plugin.py +++ b/calibre-plugin/ffdl_plugin.py @@ -8,7 +8,6 @@ __copyright__ = '2012, Jim Miller' __docformat__ = 'restructuredtext en' import time, os, copy, threading, re, platform -from ConfigParser import SafeConfigParser from StringIO import StringIO from functools import partial from datetime import datetime @@ -37,7 +36,7 @@ from calibre_plugins.fanfictiondownloader_plugin.common_utils import (set_plugin create_menu_action_unique, get_library_uuid) from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader import adapters, writers, exceptions -#from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader.htmlcleanup import stripHTML +from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader.configurable import Configuration from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader.epubutils import get_dcsource, get_dcsource_chaptercount, get_story_url_from_html from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader.geturls import get_urls_from_page @@ -249,10 +248,13 @@ class FanFictionDownLoaderPlugin(InterfaceAction): return print("get_urls_from_page URL:%s"%d.url.text()) - ffdlconfig = SafeConfigParser() - ffdlconfig.readfp(StringIO(get_resources("plugin-defaults.ini"))) - ffdlconfig.readfp(StringIO(prefs['personal.ini'])) - url_list = get_urls_from_page("%s"%d.url.text(),ffdlconfig) + if 'archiveofourown.org' in url: + configuration = Configuration(adapters.getConfigSectionFor(url),"EPUB") + configuration.readfp(StringIO(get_resources("plugin-defaults.ini"))) + configuration.readfp(StringIO(options['personal.ini'])) + else: + configuration = None + url_list = get_urls_from_page("%s"%d.url.text(),configuration) if url_list: d = ViewLog(_("List of URLs"),"\n".join(url_list),parent=self.gui) @@ -442,12 +444,10 @@ keep_summary_html:true make_firstimage_cover:true ''' + options['personal.ini'] - ## was self.ffdlconfig, but we need to be able to change it - ## when doing epub update. - ffdlconfig = SafeConfigParser() - ffdlconfig.readfp(StringIO(get_resources("plugin-defaults.ini"))) - ffdlconfig.readfp(StringIO(options['personal.ini'])) - adapter = adapters.getAdapter(ffdlconfig,url,fileform) + configuration = Configuration(adapters.getConfigSectionFor(url),fileform) + configuration.readfp(StringIO(get_resources("plugin-defaults.ini"))) + configuration.readfp(StringIO(options['personal.ini'])) + adapter = adapters.getAdapter(configuration,url) ## three tries, that's enough if both user/pass & is_adult needed, ## or a couple tries of one or the other @@ -470,13 +470,13 @@ make_firstimage_cover:true # let other exceptions percolate up. story = adapter.getStoryMetadataOnly() - writer = writers.getWriter(options['fileform'],adapter.config,adapter) + writer = writers.getWriter(options['fileform'],configuration,adapter) book['all_metadata'] = story.getAllMetadata(removeallentities=True) book['title'] = story.getMetadata("title", removeallentities=True) book['author_sort'] = book['author'] = story.getList("author", removeallentities=True) book['publisher'] = story.getMetadata("site") - book['tags'] = writer.getTags(removeallentities=True) # getTags could be moved up into adapter now. Adapter didn't used to know the fileform + book['tags'] = story.getSubjectTags(removeallentities=True) book['comments'] = sanitize_comments_html(story.getMetadata("description")) book['series'] = story.getMetadata("series", removeallentities=True) @@ -913,7 +913,7 @@ make_firstimage_cover:true except AttributeError: print("AttributeError? %s"%col) pass - + db.set_metadata(book_id,mi) # do configured column updates here. @@ -950,6 +950,52 @@ make_firstimage_cover:true val = book['all_metadata']['status'] == 'In-Progress' db.set_custom(book_id, val, label=label, commit=False) + adapter = None + if prefs['allow_custcol_from_ini']: + configuration = Configuration(adapters.getConfigSectionFor(book['url']),options['fileform']) + configuration.readfp(StringIO(get_resources("plugin-defaults.ini"))) + configuration.readfp(StringIO(options['personal.ini'])) + adapter = adapters.getAdapter(configuration,book['url']) + + # meta => custcol[,a|n|r] + # cliches=>\#acolumn,r + for line in adapter.getConfig('custom_columns_settings').splitlines(): + if "=>" in line: + (meta,custcol) = map( lambda x: x.strip(), line.split("=>") ) + flag='r' + if "," in custcol: + (custcol,flag) = map( lambda x: x.strip(), custcol.split(",") ) + + #print("meta:(%s) => custcol:(%s), flag(%s) "%(meta,custcol,flag)) + + if meta not in book['all_metadata']: + print("No value for %s, skipping custom column(%s) update."%(meta,custcol)) + continue + + if custcol not in custom_columns: + print("No custom column(%s), skipping."%(custcol)) + continue + else: + coldef = custom_columns[custcol] + label = coldef['label'] + + if flag == 'r' or book['added']: + db.set_custom(book_id, book['all_metadata'][meta], label=label, commit=False) + + if flag == 'a': + try: + existing=db.get_custom(book_id,label=label,index_is_id=True) + if isinstance(existing,list): + vallist = existing + else : + vallist = [existing] + vallist.append(book['all_metadata'][meta]) + except: + vallist = [book['all_metadata'][meta]] + + db.set_custom(book_id, ", ".join(vallist), label=label, commit=False) + + db.commit() if 'Generate Cover' in self.gui.iactions and (book['added'] or not prefs['gcnewonly']): @@ -961,10 +1007,11 @@ make_firstimage_cover:true gc_plugin = self.gui.iactions['Generate Cover'] setting_name = None if prefs['allow_gc_from_ini']: - ffdlconfig = SafeConfigParser() - ffdlconfig.readfp(StringIO(get_resources("plugin-defaults.ini"))) - ffdlconfig.readfp(StringIO(prefs['personal.ini'])) - adapter = adapters.getAdapter(ffdlconfig,book['url'],options['fileform']) + if not adapter: # might already have it from allow_custcol_from_ini + configuration = Configuration(adapters.getConfigSectionFor(book['url']),options['fileform']) + configuration.readfp(StringIO(get_resources("plugin-defaults.ini"))) + configuration.readfp(StringIO(options['personal.ini'])) + adapter = adapters.getAdapter(configuration,book['url']) # template => regexp to match => GC Setting to use. # generate_cover_settings: @@ -973,7 +1020,7 @@ make_firstimage_cover:true if "=>" in line: (template,regexp,setting) = map( lambda x: x.strip(), line.split("=>") ) value = Template(template).safe_substitute(book['all_metadata']).encode('utf8') - print("%s(%s) => %s => %s"%(template,value,regexp,setting)) + # print("%s(%s) => %s => %s"%(template,value,regexp,setting)) if re.search(regexp,value): setting_name = setting break @@ -1192,11 +1239,11 @@ make_firstimage_cover:true return None def _is_good_downloader_url(self,url): - # this is the accepted way to 'check for existance'? really? + # this is the accepted way to 'check for existance of a class variable'? really? try: self.dummyconfig except AttributeError: - self.dummyconfig = SafeConfigParser() + self.dummyconfig = Configuration("test1.com","EPUB") # pulling up an adapter is pretty low over-head. If # it fails, it's a bad url. try: diff --git a/calibre-plugin/jobs.py b/calibre-plugin/jobs.py index 29ea29bf..a5daeb42 100644 --- a/calibre-plugin/jobs.py +++ b/calibre-plugin/jobs.py @@ -10,7 +10,6 @@ __docformat__ = 'restructuredtext en' import time, os, traceback -from ConfigParser import SafeConfigParser from StringIO import StringIO from calibre.utils.ipc.server import Server @@ -20,6 +19,7 @@ from calibre.utils.logging import Log from calibre_plugins.fanfictiondownloader_plugin.dialogs import (NotGoingToDownload, OVERWRITE, OVERWRITEALWAYS, UPDATE, UPDATEALWAYS, ADDNEW, SKIP, CALIBREONLY) from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader import adapters, writers, exceptions +from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader.configurable import Configuration from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader.epubutils import get_update_data # ------------------------------------------------------------------------------ @@ -114,19 +114,19 @@ def do_download_for_worker(book,options): book['comment'] = 'Download started...' - ffdlconfig = SafeConfigParser() - ffdlconfig.readfp(StringIO(get_resources("plugin-defaults.ini"))) - ffdlconfig.readfp(StringIO(options['personal.ini'])) + configuration = Configuration(adapters.getConfigSectionFor(book['url']),options['fileform']) + configuration.readfp(StringIO(get_resources("plugin-defaults.ini"))) + configuration.readfp(StringIO(options['personal.ini'])) if not options['updateepubcover'] and 'epub_for_update' in book and options['collision'] in (UPDATE, UPDATEALWAYS): - ffdlconfig.set("overrides","never_make_cover","true") + configuration.set("overrides","never_make_cover","true") # images only for epub, even if the user mistakenly turned it # on else where. if options['fileform'] != "epub": - ffdlconfig.set("overrides","include_images","false") + configuration.set("overrides","include_images","false") - adapter = adapters.getAdapter(ffdlconfig,book['url'],options['fileform']) + adapter = adapters.getAdapter(configuration,book['url']) adapter.is_adult = book['is_adult'] adapter.username = book['username'] adapter.password = book['password'] @@ -137,7 +137,7 @@ def do_download_for_worker(book,options): adapter.setSeries(book['calibre_series'][0],book['calibre_series'][1]) # else: # print("no calibre_series") - writer = writers.getWriter(options['fileform'],adapter.config,adapter) + writer = writers.getWriter(options['fileform'],configuration,adapter) outfile = book['outfile'] diff --git a/defaults.ini b/defaults.ini index a3e41780..ce9c5a0b 100644 --- a/defaults.ini +++ b/defaults.ini @@ -18,6 +18,10 @@ ## [defaults] section applies to all formats and sites but may be ## overridden at several levels +## Some sites also require the user to confirm they are adult for +## adult content. Uncomment by removing '#' in front of is_adult. +#is_adult:true + ## All available titlepage_entries and the label used for them: ## _label: