def get(self): user = users.get_current_user() if user: error = self.request.get('error') template_values = {'nickname': user.nickname(), 'authorized': True} url = self.request.get('url') template_values['url'] = url if error: if error == 'login_required': template_values[ 'error_message'] = 'This story (or one of the chapters) requires you to be logged in.' elif error == 'bad_url': template_values[ 'error_message'] = 'Unsupported URL: ' + url elif error == 'custom': template_values[ 'error_message'] = 'Error happened: ' + self.request.get( 'errtext') elif error == 'configsaved': template_values['error_message'] = 'Configuration Saved' elif error == 'recentcleared': template_values[ 'error_message'] = 'Your Recent Downloads List has been Cleared' filename = self.request.get('file') if len(filename) > 1: template_values[ 'yourfile'] = '''<div id='yourfile'><a href='/file?id=%s'>"%s" by %s</a></div>''' % ( filename, self.request.get('name'), self.request.get('author')) self.response.headers['Content-Type'] = 'text/html' path = os.path.join(os.path.dirname(__file__), 'index.html') else: logging.debug(users.create_login_url('/')) url = users.create_login_url(self.request.uri) template_values = {'login_url': url, 'authorized': False} path = os.path.join(os.path.dirname(__file__), 'index.html') template_values['supported_sites'] = '<dl>\n' for (site, examples) in adapters.getSiteExamples(): template_values[ 'supported_sites'] += "<dt>%s</dt>\n<dd>Example Story URLs:<br>" % site for u in examples: template_values[ 'supported_sites'] += "<a href='%s'>%s</a><br>\n" % (u, u) template_values['supported_sites'] += "</dd>\n" template_values['supported_sites'] += '</dl>\n' self.response.out.write(template.render(path, template_values))
def get(self): user = users.get_current_user() if user: error = self.request.get("error") template_values = {"nickname": user.nickname(), "authorized": True} url = self.request.get("url") template_values["url"] = url if error: if error == "login_required": template_values[ "error_message" ] = "This story (or one of the chapters) requires you to be logged in." elif error == "bad_url": template_values["error_message"] = "Unsupported URL: " + url elif error == "custom": template_values["error_message"] = "Error happened: " + self.request.get("errtext") elif error == "configsaved": template_values["error_message"] = "Configuration Saved" elif error == "recentcleared": template_values["error_message"] = "Your Recent Downloads List has been Cleared" filename = self.request.get("file") if len(filename) > 1: template_values["yourfile"] = """<div id='yourfile'><a href='/file?id=%s'>"%s" by %s</a></div>""" % ( filename, self.request.get("name"), self.request.get("author"), ) self.response.headers["Content-Type"] = "text/html" path = os.path.join(os.path.dirname(__file__), "index.html") else: logging.debug(users.create_login_url("/")) url = users.create_login_url(self.request.uri) template_values = {"login_url": url, "authorized": False} path = os.path.join(os.path.dirname(__file__), "index.html") template_values["supported_sites"] = "<dl>\n" for (site, examples) in adapters.getSiteExamples(): template_values["supported_sites"] += "<dt>%s</dt>\n<dd>Example Story URLs:<br>" % site for u in examples: template_values["supported_sites"] += "<a href='%s'>%s</a><br>\n" % (u, u) template_values["supported_sites"] += "</dd>\n" template_values["supported_sites"] += "</dl>\n" self.response.out.write(template.render(path, template_values))
def get(self): user = users.get_current_user() if user: error = self.request.get('error') template_values = {'nickname' : user.nickname(), 'authorized': True} url = self.request.get('url') template_values['url'] = url if error: if error == 'login_required': template_values['error_message'] = 'This story (or one of the chapters) requires you to be logged in.' elif error == 'bad_url': template_values['error_message'] = 'Unsupported URL: ' + url elif error == 'custom': template_values['error_message'] = 'Error happened: ' + self.request.get('errtext') elif error == 'configsaved': template_values['error_message'] = 'Configuration Saved' elif error == 'recentcleared': template_values['error_message'] = 'Your Recent Downloads List has been Cleared' filename = self.request.get('file') if len(filename) > 1: template_values['yourfile'] = '''<div id='yourfile'><a href='/file?id=%s'>"%s" by %s</a></div>''' % (filename, self.request.get('name'), self.request.get('author')) self.response.headers['Content-Type'] = 'text/html' path = os.path.join(os.path.dirname(__file__), 'index.html') else: logging.debug(users.create_login_url('/')) url = users.create_login_url(self.request.uri) template_values = {'login_url' : url, 'authorized': False} path = os.path.join(os.path.dirname(__file__), 'index.html') template_values['supported_sites'] = '<dl>\n' for (site,examples) in adapters.getSiteExamples(): template_values['supported_sites'] += "<dt>%s</dt>\n<dd>Example Story URLs:<br>"%site for u in examples: template_values['supported_sites'] += "<a href='%s'>%s</a><br>\n"%(u,u) template_values['supported_sites'] += "</dd>\n" template_values['supported_sites'] += '</dl>\n' self.response.out.write(template.render(path, template_values))
def main(argv=None, parser=None, passed_defaultsini=None, passed_personalini=None): if argv is None: argv = sys.argv[1:] # read in args, anything starting with -- will be treated as --<varible>=<value> if not parser: parser = OptionParser('usage: %prog [options] [STORYURL]...') parser.add_option( '-f', '--format', dest='format', default='epub', help='Write story as FORMAT, epub(default), mobi, txt or html.', metavar='FORMAT') if passed_defaultsini: config_help = 'calibre plugin defaults.ini, calibre plugin personal.ini' else: config_help = '~/.fanficfare/defaults.ini, $XDG_CONFIG_HOME/fanficfare/defaults.ini, ./defaults.ini' parser.add_option( '-c', '--config', action='append', dest='configfile', default=None, help= ('Read config from specified file(s) in addition to (ordered lowest to highest priority): ' + config_help + ', ~/.fanficfare/personal.ini, $XDG_CONFIG_HOME/fanficfare/personal.ini, and ./personal.ini. -c/--config files take highest priority' ), metavar='CONFIG') range_help = ' --begin and --end will be overridden by a chapter range on the STORYURL like STORYURL[1-2], STORYURL[-3], STORYURL[3-] or STORYURL[3]' parser.add_option('-b', '--begin', dest='begin', default=None, help='Begin story with Chapter START.' + range_help, metavar='START') parser.add_option('-e', '--end', dest='end', default=None, help='End story with Chapter END.' + range_help, metavar='END') parser.add_option( '-o', '--option', action='append', dest='options', help='Set config option NAME=VALUE Overrides config file setting.', metavar='NAME=VALUE') parser.add_option( '-m', '--meta-only', action='store_true', dest='metaonly', help= 'Retrieve and write metadata to stdout without downloading or saving chapters; saves story file with titlepage only. (See also --json-meta)', ) parser.add_option( '-z', '--no-meta-chapters', action='store_true', dest='nometachapters', help= 'Exclude list of chapters("zchapters") from metadata stdout output. No effect without --meta-only or --json-meta flags', ) parser.add_option( '-j', '--json-meta', action='store_true', dest='jsonmeta', help= 'Output metadata as JSON with download, or with --meta-only flag. (Only JSON will be output with --meta-only flag.) Also now series name and desc if available with --list', ) parser.add_option( '--json-meta-file', action='store_true', dest='jsonmetafile', help= 'Similar to --json-meta, but output metadata for each download as JSON to an individual file named by appending ".json" to the output_filename.', ) parser.add_option( '--no-output', action='store_true', dest='nooutput', help= 'Do not download chapters and do not write output file. Intended for testing and with --meta-only.', ) parser.add_option( '-u', '--update-epub', action='store_true', dest='update', help= 'Update an existing epub(if present) with new chapters. Give either epub filename or story URL.', ) parser.add_option( '-U', '--update-epub-always', action='store_true', dest='updatealways', help= "Update an existing epub(if present) even if there aren't new chapters. Give either epub filename or story URL.", ) parser.add_option( '--update-cover', action='store_true', dest='updatecover', help= 'Update cover in an existing epub, otherwise existing cover (if any) is used on update. Only valid with --update-epub.', ) parser.add_option( '--unnew', action='store_true', dest='unnew', help='Remove (new) chapter marks left by mark_new_chapters setting.', ) parser.add_option( '--force', action='store_true', dest='force', help= 'Force overwrite of an existing epub, download and overwrite all chapters.', ) parser.add_option( '-i', '--infile', help= 'Give a filename to read for URLs (and/or existing EPUB files with --update-epub).', dest='infile', default=None, metavar='INFILE') parser.add_option( '-l', '--list', dest='list', default=None, metavar='URL', help='Get list of valid story URLs from page given.', ) parser.add_option( '-n', '--normalize-list', dest='normalize', default=None, metavar='URL', help= 'Get list of valid story URLs from page given, but normalized to standard forms.', ) parser.add_option( '--download-list', dest='downloadlist', default=None, metavar='URL', help= 'Download story URLs retrieved from page given. Update existing EPUBs if used with --update-epub.', ) parser.add_option( '--imap', action='store_true', dest='imaplist', help= 'Get list of valid story URLs from unread email from IMAP account configured in ini.', ) parser.add_option( '--download-imap', action='store_true', dest='downloadimap', help= 'Download valid story URLs from unread email from IMAP account configured in ini. Update existing EPUBs if used with --update-epub.', ) parser.add_option( '-s', '--sites-list', action='store_true', dest='siteslist', default=False, help='Get list of valid story URLs examples.', ) parser.add_option( '--non-interactive', action='store_false', dest='interactive', default=sys.stdin.isatty() and sys.stdout.isatty(), help='Prevent interactive prompts (for scripting).', ) parser.add_option( '-d', '--debug', action='store_true', dest='debug', help='Show debug and notice output.', ) parser.add_option( '-p', '--progressbar', action='store_true', dest='progressbar', help= 'Display a simple progress bar while downloading--one dot(.) per network fetch.', ) parser.add_option( '--color', action='store_true', dest='color', help= 'Display a errors and warnings in a contrasting color. Requires package colorama on Windows.', ) parser.add_option( '-v', '--version', action='store_true', dest='version', help='Display version and quit.', ) ## undocumented feature for development use. Save page cache and ## cookies between runs. Saves in PWD as files global_cache and ## global_cookies parser.add_option( '--save-cache', '--save_cache', action='store_true', dest='save_cache', help=SUPPRESS_HELP, ) ## 'undocumented' feature to allow expired/unverified SSL certs pass. ## removed in favor of use_ssl_unverified_context ini setting. parser.add_option( '--unverified_ssl', action='store_true', dest='unverified_ssl', help=SUPPRESS_HELP, ) options, args = parser.parse_args(argv) if options.unverified_ssl: print( "Option --unverified_ssl removed.\nSet use_ssl_unverified_context:true in ini file or --option instead." ) return if not options.debug: logger.setLevel(logging.WARNING) else: logger.debug(" OS Version:%s" % platform.platform()) logger.debug("Python Version:%s" % sys.version) logger.debug(" FFF Version:%s" % version) if options.version: print("Version: %s" % version) return if options.color: if 'Windows' in platform.platform(): try: from colorama import init as colorama_init colorama_init() except ImportError: print( "Option --color will not work on Windows without installing Python package colorama.\nContinue? (y/n)?" ) if options.interactive: if not sys.stdin.readline().strip().lower().startswith( 'y'): return else: # for non-interactive, default the response to yes and continue processing print('y') def warn(t): print("\033[{}m{}\033[0m".format(34, t)) # blue def fail(t): print("\033[{}m{}\033[0m".format(31, t)) # red else: warn = fail = print list_only = any(( options.imaplist, options.siteslist, options.list, options.normalize, )) if list_only and (args or any( (options.downloadimap, options.downloadlist))): parser.error( 'Incorrect arguments: Cannot download and list URLs at the same time.' ) if options.siteslist: for site, examples in adapters.getSiteExamples(): print('\n#### %s\nExample URLs:' % site) for u in examples: print(' * %s' % u) return # options.updatealways should also invoke most options.update logic. if options.updatealways: options.update = True if options.update and options.format != 'epub': parser.error( '-u/--update-epub/-U/--update-epub-always only work with epub') if options.unnew and options.format != 'epub': parser.error('--unnew only works with epub') urls = args if not list_only and not (args or any( (options.infile, options.downloadimap, options.downloadlist))): parser.print_help() return if options.list: configuration = get_configuration(options.list, passed_defaultsini, passed_personalini, options) frompage = get_urls_from_page(options.list, configuration) if options.jsonmeta: import json print( json.dumps(frompage, sort_keys=True, indent=2, separators=(',', ':'))) else: retlist = frompage.get('urllist', []) print('\n'.join(retlist)) if options.normalize: configuration = get_configuration(options.normalize, passed_defaultsini, passed_personalini, options) retlist = get_urls_from_page(options.normalize, configuration, normalize=True).get('urllist', []) print('\n'.join(retlist)) if options.downloadlist: configuration = get_configuration(options.downloadlist, passed_defaultsini, passed_personalini, options) retlist = get_urls_from_page(options.downloadlist, configuration).get('urllist', []) urls.extend(retlist) if options.imaplist or options.downloadimap: # list doesn't have a supported site. configuration = get_configuration('test1.com', passed_defaultsini, passed_personalini, options) markread = configuration.getConfig('imap_mark_read') == 'true' or \ (configuration.getConfig('imap_mark_read') == 'downloadonly' and options.downloadimap) retlist = get_urls_from_imap(configuration.getConfig('imap_server'), configuration.getConfig('imap_username'), configuration.getConfig('imap_password'), configuration.getConfig('imap_folder'), markread) if options.downloadimap: urls.extend(retlist) else: print('\n'.join(retlist)) # for passing in a file list if options.infile: with open(options.infile, "r") as infile: #print("file exists and is readable") for url in infile: if '#' in url: url = url[:url.find('#')].strip() url = url.strip() if len(url) > 0: #print("url: (%s)"%url) urls.append(url) if not list_only: if len(urls) < 1: print("No valid story URLs found") else: for url in urls: try: do_download(url, options, passed_defaultsini, passed_personalini, warn, fail) except Exception as e: if len(urls) == 1: raise fail( "URL(%s) Failed: Exception (%s). Run URL individually for more detail." % (url, e))
def sitesList(*args): for site, examples in adapters.getSiteExamples(): print('\n#### %s\nExample URLs:' % site) for u in examples: print(' * %s' % u) sys.exit()