Exemple #1
0
def get_wetter(parsed_query):

    location = parsed_query['location']
    html = parsed_query['html_output']
    lang = parsed_query['lang']

    location_not_found = False
    if location == NOT_FOUND_LOCATION:
        location_not_found = True

    stderr = ""
    returncode = 0
    if not location_not_found:
        stdout, stderr, returncode = _wego_wrapper(location, parsed_query)
        first_line, stdout = _wego_postprocessing(location, parsed_query,
                                                  stdout)

    if location_not_found or \
        (returncode != 0 \
            and ('Unable to find any matching weather'
                 ' location to the parsed_query submitted') in stderr):
        stdout, stderr, returncode = _wego_wrapper(DEFAULT_LOCATION,
                                                   parsed_query)
        location_not_found = True

        not_found_header = """
>>>    _  _    ___  _  _     
>>>   | || |  / _ \| || |      
>>>   | || |_| | | | || |_      
>>>   |__   _| |_| |__   _|      
>>>      |_|  \___/   |_|    
>>>                       
>>>   404 %s: %s
>>>                 
""" % (get_message("UNKNOWN_LOCATION",
                   lang).upper(), parsed_query['override_location_name'])

        not_found_header = "\n".join(
            "\033[48;5;91m" + x + "   \033[0m"
            for x in not_found_header.splitlines()[1:])

        not_found_footer = get_message('NOT_FOUND_MESSAGE', lang)
        not_found_footer = "\n".join("\033[48;5;91m " + x + " \033[0m"
                                     for x in not_found_footer.splitlines()
                                     if x) + "\n"

        first_line, stdout = _wego_postprocessing(location, parsed_query,
                                                  stdout)
        stdout = not_found_header + "\n----\n" + stdout + not_found_footer

    if html:
        return _htmlize(stdout, first_line, parsed_query)
    return stdout
Exemple #2
0
def milestone_handler_func(intent):
    milestones = load_current_milestones_with_locale(intent.request.locale)

    if intent.request.intent.has_slot("activityname"):
        slot_value = intent.request.intent.get_slot("activityname")
        milestone_key = slot_value_to_data_key(slot_value)

        if milestone_key == "XUR":
            if milestones.has_milestone(milestone_key):
                phrase = get_message("xur-phrase",
                                     locale=intent.request.locale)
            else:
                phrase = get_message("no-xur-phrase",
                                     locale=intent.request.locale)

            return build_response({},
                                  build_speechlet_response(
                                      "Xur", phrase, phrase, True))

        if milestones.has_milestone(milestone_key):
            milestone = milestones.get_milestone(milestone_key)

            print milestone_key

            phrase = ""
            if milestone_key in [
                    "CallToArms", "Meditations", "ClanObjectives"
            ]:
                phrase = milestone.description
            else:
                phrase = get_message("milestone-phrase",
                                     locale=intent.request.locale).replace(
                                         "#caption#", slot_value).replace(
                                             "#name#", milestone.name).replace(
                                                 "#description#",
                                                 milestone.description)

            return build_response({},
                                  build_speechlet_response(
                                      milestone_key, phrase, phrase, True))
        else:
            phrase = get_error_message("unknown-milestone",
                                       locale=intent.request.locale).replace(
                                           "#caption#", slot_value)
            return build_response({},
                                  build_speechlet_response(
                                      milestone_key, phrase, phrase, True))
    else:
        phrase = get_error_message("no-milestone",
                                   locale=intent.request.locale)
        return build_response({},
                              build_speechlet_response(":(", phrase, phrase,
                                                       True))
Exemple #3
0
def get_wetter(parsed_query):

    location = parsed_query['location']
    html = parsed_query['html_output']
    lang = parsed_query['lang']

    location_not_found = False
    if location == NOT_FOUND_LOCATION:
        location_not_found = True

    stderr = ""
    returncode = 0
    if not location_not_found:
        stdout, stderr, returncode = _wego_wrapper(location, parsed_query)

    if location_not_found or \
        (returncode != 0 \
            and ('Unable to find any matching weather'
                 ' location to the parsed_query submitted') in stderr):
            stdout, stderr, returncode = _wego_wrapper(NOT_FOUND_LOCATION, parsed_query)
            location_not_found = True
            stdout += get_message('NOT_FOUND_MESSAGE', lang)

    if "\n" in stdout:
        first_line, stdout = _wego_postprocessing(location, parsed_query, stdout)
    else:
        first_line = ""


    if html:
        return _htmlize(stdout, first_line, parsed_query)
    return stdout
Exemple #4
0
def _response(parsed_query, query, fast_mode=False):
    """Create response text based on `parsed_query` and `query` data.
    If `fast_mode` is True, process only requests that can
    be handled very fast (cached and static files).
    """

    answer = None
    cache_signature = cache.get_signature(parsed_query["user_agent"],
                                          parsed_query["request_url"],
                                          parsed_query["ip_addr"],
                                          parsed_query["lang"])
    answer = cache.get(cache_signature)

    if parsed_query['orig_location'] in PLAIN_TEXT_PAGES:
        answer = show_text_file(parsed_query['orig_location'],
                                parsed_query['lang'])
        if parsed_query['html_output']:
            answer = render_template('index.html', body=answer)

    if answer or fast_mode:
        return answer

    # at this point, we could not handle the query fast,
    # so we handle it with all available logic
    loc = (parsed_query['orig_location'] or "").lower()
    if parsed_query.get("view"):
        if not parsed_query.get("location"):
            parsed_query["location"] = loc

        output = wttr_line(query, parsed_query)
    elif loc == 'moon' or loc.startswith('moon@'):
        output = get_moon(parsed_query)
    else:
        output = get_wetter(parsed_query)

    if parsed_query.get('png_filename'):
        if parsed_query.get("view") != "v3":
            # originally it was just a usual function call,
            # but it was a blocking call, so it was moved
            # to separate threads:
            #
            #    output = fmt.png.render_ansi(
            #        output, options=parsed_query)
            result = TASKS.spawn(fmt.png.render_ansi,
                                 cache._update_answer(output),
                                 options=parsed_query)
            output = result.get()
    else:
        if query.get('days', '3') != '0' \
            and not query.get('no-follow-line') \
            and ((parsed_query.get("view") or "v2")[:2] in ["v2", "v3"]):
            if parsed_query['html_output']:
                output = add_buttons(output)
            else:
                message = get_message('FOLLOW_ME', parsed_query['lang'])
                if parsed_query.get('no-terminal', False):
                    message = remove_ansi(message)
                output += '\n' + message + '\n'

    return cache.store(cache_signature, output)
Exemple #5
0
def _wego_postprocessing(location, parsed_query, stdout):
    full_address = parsed_query['full_address']
    lang = parsed_query['lang']

    if 'days' in parsed_query:
        if parsed_query['days'] == '0':
            stdout = "\n".join(stdout.splitlines()[:7]) + "\n"
        if parsed_query['days'] == '1':
            stdout = "\n".join(stdout.splitlines()[:17]) + "\n"
        if parsed_query['days'] == '2':
            stdout = "\n".join(stdout.splitlines()[:27]) + "\n"


    first = stdout.splitlines()[0]
    rest = stdout.splitlines()[1:]
    if parsed_query.get('no-caption', False):
        if ':' in first:
            first = first.split(":", 1)[1]
            stdout = "\n".join([first.strip()] + rest) + "\n"

    if parsed_query.get('no-terminal', False):
        stdout = remove_ansi(stdout)

    if parsed_query.get('no-city', False):
        stdout = "\n".join(stdout.splitlines()[2:]) + "\n"

    if full_address \
        and parsed_query.get('format', 'txt') != 'png' \
        and (not parsed_query.get('no-city')
             and not parsed_query.get('no-caption')
             and not parsed_query.get('days') == '0'):
        line = "%s: %s [%s]\n" % (
            get_message('LOCATION', lang),
            full_address,
            location)
        stdout += line

    if parsed_query.get('padding', False):
        lines = [x.rstrip() for x in stdout.splitlines()]
        max_l = max(len(remove_ansi(x)) for x in lines)
        last_line = " "*max_l + "   .\n"
        stdout = " \n" + "\n".join("  %s  " %x for x in lines) + "\n" + last_line

    return first, stdout
Exemple #6
0
def briefing_handler_func(intent):
    milestones = load_current_milestones_with_locale(intent.request.locale)

    phrase = get_message("briefing-phrase", locale=intent.request.locale)

    if milestones.has_milestone("Trials"):
        phrase = phrase + get_message("trials-phrase",
                                      locale=intent.request.locale)

    if milestones.has_milestone("XUR"):
        phrase = phrase + get_message(
            "xur-phrase", locale=intent.request.locale
        ) + milestones.get_milestone("XUR").description + " "

    if milestones.has_milestone("Nightfall"):
        phrase = phrase + get_message(
            "nightfall-phrase", locale=intent.request.locale).replace(
                "#name#",
                milestones.get_milestone("Nightfall").name)

    if milestones.has_milestone("Hotspot"):
        phrase = phrase + milestones.get_milestone("Hotspot").description + " "

    if milestones.has_milestone("Raid"):
        phrase = phrase + get_message(
            "raid-phrase", locale=intent.request.locale).replace(
                "#name#",
                milestones.get_milestone("Raid").name)

    if milestones.has_milestone("CallToArms"):
        phrase = phrase + milestones.get_milestone(
            "CallToArms").description + " "

    if milestones.has_milestone("ClanObjectives"):
        phrase = phrase + milestones.get_milestone(
            "ClanObjectives").description + " "

    if milestones.has_milestone("Meditations"):
        phrase = phrase + milestones.get_milestone(
            "Meditations").description + "  "

    phrase = phrase + get_message("exit-phrase", locale=intent.request.locale)

    return build_response({},
                          build_speechlet_response("Destiny 2 Briefing",
                                                   phrase, phrase, True))
Exemple #7
0
            output = get_moon(location, html=html_output, lang=lang)
        else:
            output = get_wetter(
                location,
                ip_addr,
                html=html_output,
                lang=lang,
                query=query,
                location_name=override_location_name,
                full_address=full_address,
                url=request.url,
            )

        if html_output:
            output = add_buttons(output)
        else:
            if query.get('days', '3') != '0':
                #output += '\n' + get_message('NEW_FEATURE', lang).encode('utf-8')
                output += '\n' + get_message('FOLLOW_ME',
                                             lang).encode('utf-8') + '\n'
        return output

    except RuntimeError, exception:
        if 'Malformed response' in str(exception) \
                or 'API key has reached calls per day allowed limit' in str(exception):
            if html_output:
                return MALFORMED_RESPONSE_HTML_PAGE
            return get_message('CAPACITY_LIMIT_REACHED', lang).encode('utf-8')
        logging.error("Exception has occured", exc_info=1)
        return "ERROR"
Exemple #8
0
def wttr(location, request):
    """
    Main rendering function, it processes incoming weather queries.
    Depending on user agent it returns output in HTML or ANSI format.

    Incoming data:
        request.args
        request.headers
        request.remote_addr
        request.referrer
        request.query_string
    """
    def _wrap_response(response_text, html_output):
        response = make_response(response_text)
        response.mimetype = 'text/html' if html_output else 'text/plain'
        return response

    if is_location_blocked(location):
        return ""

    ip_addr = client_ip_address(request)

    try:
        LIMITS.check_ip(ip_addr)
    except RuntimeError as exception:
        return str(exception)

    png_filename = None
    if location is not None and location.lower().endswith(".png"):
        png_filename = location
        location = location[:-4]

    lang = get_answer_language(request)
    query = parse_query.parse_query(request.args)
    html_output = get_output_format(request, query)
    user_agent = request.headers.get('User-Agent', '').lower()

    if location in PLAIN_TEXT_PAGES:
        help_ = show_text_file(location, lang)
        if html_output:
            return _wrap_response(render_template('index.html', body=help_),
                                  html_output)
        return _wrap_response(help_, html_output)

    if location and ':' in location:
        location = cyclic_location_selection(location, query.get('period', 1))

    orig_location = location

    if not png_filename:
        location, override_location_name, full_address, country, query_source_location = \
                location_processing(location, ip_addr)

        us_ip = query_source_location[
            1] == 'United States' and 'slack' not in user_agent
        query = parse_query.metric_or_imperial(query, lang, us_ip=us_ip)

        # logging query
        orig_location_utf8 = (orig_location or "").encode('utf-8')
        location_utf8 = location.encode('utf-8')
        use_imperial = query.get('use_imperial', False)
        log(" ".join(
            map(str, [
                ip_addr, user_agent, orig_location_utf8, location_utf8,
                use_imperial, lang
            ])))

        if country and location != NOT_FOUND_LOCATION:
            location = "%s,%s" % (location, country)

    # We are ready to return the answer
    try:
        if 'format' in query:
            return _wrap_response(
                wttr_line(location, override_location_name, query, lang),
                html_output)

        if png_filename:
            options = {'lang': lang, 'location': location}
            options.update(query)

            cached_png_file = wttrin_png.make_wttr_in_png(png_filename,
                                                          options=options)
            response = make_response(
                send_file(cached_png_file,
                          attachment_filename=png_filename,
                          mimetype='image/png'))
            for key, value in {
                    'Cache-Control': 'no-cache, no-store, must-revalidate',
                    'Pragma': 'no-cache',
                    'Expires': '0',
            }.items():
                response.headers[key] = value

            # Trying to disable github caching
            return response

        if location.lower() == 'moon' or location.lower().startswith('moon@'):
            output = get_moon(location,
                              html=html_output,
                              lang=lang,
                              query=query)
        else:
            output = get_wetter(
                location,
                ip_addr,
                html=html_output,
                lang=lang,
                query=query,
                location_name=override_location_name,
                full_address=full_address,
                url=request.url,
            )

        if query.get('days', '3') != '0' and not query.get('no-follow-line'):
            if html_output:
                output = add_buttons(output)
            else:
                #output += '\n' + get_message('NEW_FEATURE', lang).encode('utf-8')
                output += '\n' + get_message('FOLLOW_ME',
                                             lang).encode('utf-8') + '\n'

        return _wrap_response(output, html_output)

    except RuntimeError as exception:
        if 'Malformed response' in str(exception) \
                or 'API key has reached calls per day allowed limit' in str(exception):
            if html_output:
                return _wrap_response(MALFORMED_RESPONSE_HTML_PAGE,
                                      html_output)
            return _wrap_response(
                get_message('CAPACITY_LIMIT_REACHED', lang).encode('utf-8'),
                html_output)
        logging.error("Exception has occured", exc_info=1)
        return "ERROR"
Exemple #9
0
    def save_weather_data(location,
                          filename,
                          lang=None,
                          query=None,
                          location_name=None,
                          full_address=None):
        ansi_escape = re.compile(r'(\x9B|\x1B\[)[0-?]*[ -\/]*[@-~]')

        def remove_ansi(sometext):
            return ansi_escape.sub('', sometext)

        if _is_invalid_location(location):
            error("Invalid location: %s" % location)

        NOT_FOUND_MESSAGE_HEADER = ""
        while True:
            location_not_found = False
            if location in ["test-thunder"]:
                test_name = location[5:]
                test_file = TEST_FILE.replace('NAME', test_name)
                stdout = open(test_file, 'r').read()
                stderr = ""
                break
            print "LOCATION = ", location
            if location == NOT_FOUND_LOCATION:
                location_not_found = True
                location = DEFAULT_LOCATION

            cmd = [WEGO, '--city=%s' % location]

            if query.get('inverted_colors'):
                cmd += ['-inverse']

            if query.get('use_ms_for_wind'):
                cmd += ['-wind_in_ms']

            if query.get('narrow'):
                cmd += ['-narrow']

            if lang and lang in SUPPORTED_LANGS:
                cmd += ['-lang=%s' % lang]

            if query.get('use_imperial', False):
                cmd += ['-imperial']

            if location_name:
                cmd += ['-location_name', location_name]

            p = Popen(cmd, stdout=PIPE, stderr=PIPE)
            stdout, stderr = p.communicate()
            if p.returncode != 0:
                print "ERROR: location not found: %s" % location
                if 'Unable to find any matching weather location to the query submitted' in stderr:
                    if location != NOT_FOUND_LOCATION:
                        NOT_FOUND_MESSAGE_HEADER = u"ERROR: %s: %s\n---\n\n" % (
                            get_message('UNKNOWN_LOCATION', lang), location)
                        location = NOT_FOUND_LOCATION
                        continue
                error(stdout + stderr)
            break

        dirname = os.path.dirname(filename)
        if not os.path.exists(dirname):
            os.makedirs(dirname)

        if location_not_found:
            stdout += get_message('NOT_FOUND_MESSAGE', lang).encode('utf-8')
            stdout = NOT_FOUND_MESSAGE_HEADER.encode('utf-8') + stdout

        if 'days' in query:
            if query['days'] == '0':
                stdout = "\n".join(stdout.splitlines()[:7]) + "\n"
            if query['days'] == '1':
                stdout = "\n".join(stdout.splitlines()[:17]) + "\n"
            if query['days'] == '2':
                stdout = "\n".join(stdout.splitlines()[:27]) + "\n"

        first = stdout.splitlines()[0].decode('utf-8')
        rest = stdout.splitlines()[1:]
        if query.get('no-caption', False):

            separator = None
            if ':' in first:
                separator = ':'
            if u':' in first:
                separator = u':'

            if separator:
                first = first.split(separator, 1)[1]
                stdout = "\n".join([first.strip().encode('utf-8')] +
                                   rest) + "\n"

        if query.get('no-terminal', False):
            stdout = remove_ansi(stdout)

        if query.get('no-city', False):
            stdout = "\n".join(stdout.splitlines()[2:]) + "\n"

        if full_address and query.get('format', 'txt') != 'png':
            line = "%s: %s [%s]\n" % (get_message(
                'LOCATION',
                lang).encode('utf-8'), full_address.encode('utf-8'), location)
            stdout += line

        if query.get('padding', False):
            lines = [x.rstrip() for x in stdout.splitlines()]
            max_l = max(len(remove_ansi(x).decode('utf8')) for x in lines)
            last_line = " " * max_l + "   .\n"
            stdout = " \n" + "\n".join("  %s  " % x
                                       for x in lines) + "\n" + last_line

        open(filename, 'w').write(stdout)

        cmd = ["bash", ANSI2HTML, "--palette=solarized"]
        if not query.get('inverted_colors'):
            cmd += ["--bg=dark"]

        p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
        stdout, stderr = p.communicate(stdout)
        if p.returncode != 0:
            error(stdout + stderr)

        if query.get('inverted_colors'):
            stdout = stdout.replace(
                '<body class="">',
                '<body class="" style="background:white;color:#777777">')

        title = "<title>%s</title>" % first.encode('utf-8')
        opengraph = get_opengraph()
        stdout = re.sub("<head>", "<head>" + title + opengraph, stdout)
        open(filename + '.html', 'w').write(stdout)
Exemple #10
0
def wttr(location, request):
    """Main rendering function, it processes incoming weather queries,
    and depending on the User-Agent string and other paramters of the query
    it returns output in HTML, ANSI or other format.
    """
    def _wrap_response(response_text, html_output, png_filename=None):
        if not isinstance(response_text, str) and \
           not isinstance(response_text, bytes):
            return response_text

        if png_filename:
            response = make_response(
                send_file(io.BytesIO(response_text),
                          attachment_filename=png_filename,
                          mimetype='image/png'))

            for key, value in {
                    'Cache-Control': 'no-cache, no-store, must-revalidate',
                    'Pragma': 'no-cache',
                    'Expires': '0',
            }.items():
                response.headers[key] = value
        else:
            response = make_response(response_text)
            response.mimetype = 'text/html' if html_output else 'text/plain'
        return response

    if is_location_blocked(location):
        return ("", 403)  # Forbidden

    try:
        LIMITS.check_ip(_client_ip_address(request))
    except RuntimeError as exception:
        return (str(exception), 429)  # Too many requests

    query = parse_query.parse_query(request.args)

    # first, we try to process the query as fast as possible
    # (using the cache and static files),
    # and only if "fast_mode" was unsuccessful,
    # use the full track
    parsed_query = parse_request(location, request, query, fast_mode=True)
    response = _response(parsed_query, query, fast_mode=True)

    http_code = 200
    try:
        if not response:
            parsed_query = parse_request(location, request, query)
            response = _response(parsed_query, query)
    # pylint: disable=broad-except
    except Exception as exception:
        logging.error("Exception has occured", exc_info=1)
        if parsed_query['html_output']:
            response = MALFORMED_RESPONSE_HTML_PAGE
            http_code = 500  # Internal Server Error
        else:
            response = get_message('CAPACITY_LIMIT_REACHED',
                                   parsed_query['lang'])
            http_code = 503  # Service Unavailable

        # if exception is occured, we return not a png file but text
        if "png_filename" in parsed_query:
            del parsed_query["png_filename"]
    return (_wrap_response(response,
                           parsed_query['html_output'],
                           png_filename=parsed_query.get('png_filename')),
            http_code)
Exemple #11
0
def help_handler_func(intent):
    phrase = get_message("help-phrase", locale=intent.request.locale)
    return build_response({},
                          build_speechlet_response("Warmind (Destiny 2)",
                                                   phrase, phrase, True))
Exemple #12
0
def cancel_handler_func(intent):
    phrase = get_message("exit-phrase", locale=intent.request.locale)
    return build_response({},
                          build_speechlet_response("Destiny 2 Briefing",
                                                   phrase, phrase, True))