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)
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, fmt = get_answer_language_and_format(request) query = parse_query.parse_query(request.args) html_output = get_output_format(request, query) user_agent = request.headers.get('User-Agent', '').lower() # generating cache signature cache_signature = cache.get_signature(user_agent, request.url, ip_addr, lang) answer = cache.get(cache_signature) if answer: return _wrap_response(answer, html_output) 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 fmt or 'format' in query: response_text = wttr_line(location, override_location_name, full_address, query, lang, fmt) fmt = fmt or query.get('format') response_text = cache.store(cache_signature, response_text) return _wrap_response(response_text, html_output) if png_filename: options = {'ip_addr': ip_addr, '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 orig_location and (orig_location.lower() == 'moon' or orig_location.lower().startswith('moon@')): output = get_moon(orig_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 Exception 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)