Пример #1
0
    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))
Пример #2
0
    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))
Пример #3
0
    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))
Пример #4
0
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))
Пример #5
0
 def sitesList(*args):
     for site, examples in adapters.getSiteExamples():
         print('\n#### %s\nExample URLs:' % site)
         for u in examples:
             print('  * %s' % u)
     sys.exit()