mirror of
https://github.com/chubin/wttr.in
synced 2025-01-12 20:18:46 +00:00
856a67a474
The postprocessing method assumes that the sout data is always delivered in the same format. If the location is not found, the passed format deviates and this then leads to an incorrect behavior => incorrect return value. Close #729 Close #728
187 lines
6 KiB
Python
187 lines
6 KiB
Python
# vim: set encoding=utf-8
|
|
# pylint: disable=wrong-import-position
|
|
|
|
"""
|
|
Main view (wttr.in) implementation.
|
|
The module is a wrapper for the modified Wego program.
|
|
"""
|
|
|
|
import sys
|
|
import re
|
|
|
|
from gevent.subprocess import Popen, PIPE
|
|
|
|
sys.path.insert(0, "..")
|
|
from translations import get_message, SUPPORTED_LANGS
|
|
from globals import WEGO, NOT_FOUND_LOCATION, DEFAULT_LOCATION, ANSI2HTML, \
|
|
error, remove_ansi
|
|
|
|
|
|
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
|
|
|
|
def _wego_wrapper(location, parsed_query):
|
|
|
|
lang = parsed_query['lang']
|
|
if location == DEFAULT_LOCATION:
|
|
location_name = DEFAULT_LOCATION.capitalize()
|
|
else:
|
|
location_name = parsed_query['override_location_name']
|
|
|
|
cmd = [WEGO, '--city=%s' % location]
|
|
|
|
if parsed_query.get('inverted_colors'):
|
|
cmd += ['-inverse']
|
|
|
|
if parsed_query.get('use_ms_for_wind'):
|
|
cmd += ['-wind_in_ms']
|
|
|
|
if parsed_query.get('narrow'):
|
|
cmd += ['-narrow']
|
|
|
|
if lang and lang in SUPPORTED_LANGS:
|
|
cmd += ['-lang=%s'%lang]
|
|
|
|
if parsed_query.get('use_imperial', False):
|
|
cmd += ['-imperial']
|
|
|
|
if location_name:
|
|
cmd += ['-location_name', location_name]
|
|
|
|
proc = Popen(cmd, stdout=PIPE, stderr=PIPE)
|
|
stdout, stderr = proc.communicate()
|
|
stdout = stdout.decode("utf-8")
|
|
stderr = stderr.decode("utf-8")
|
|
|
|
return stdout, stderr, proc.returncode
|
|
|
|
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
|
|
|
|
def _htmlize(ansi_output, title, parsed_query):
|
|
"""Return HTML representation of `ansi_output`.
|
|
Use `title` as the title of the page.
|
|
Format page according to query parameters from `parsed_query`."""
|
|
|
|
cmd = ["bash", ANSI2HTML, "--palette=solarized"]
|
|
if not parsed_query.get('inverted_colors'):
|
|
cmd += ["--bg=dark"]
|
|
|
|
proc = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
|
|
stdout, stderr = proc.communicate(ansi_output.encode("utf-8"))
|
|
stdout = stdout.decode("utf-8")
|
|
stderr = stderr.decode("utf-8")
|
|
if proc.returncode != 0:
|
|
error(stdout + stderr)
|
|
|
|
if parsed_query.get('inverted_colors'):
|
|
stdout = stdout.replace(
|
|
'<body class="">', '<body class="" style="background:white;color:#777777">')
|
|
|
|
title = "<title>%s</title>" % title
|
|
opengraph = _get_opengraph(parsed_query)
|
|
stdout = re.sub("<head>", "<head>" + title + opengraph, stdout)
|
|
return stdout
|
|
|
|
def _get_opengraph(parsed_query):
|
|
"""Return OpenGraph data for `parsed_query`"""
|
|
|
|
url = parsed_query['request_url'] or ""
|
|
pic_url = url.replace('?', '_')
|
|
|
|
return (
|
|
'<meta property="og:image" content="%(pic_url)s_0pq.png" />'
|
|
'<meta property="og:site_name" content="wttr.in" />'
|
|
'<meta property="og:type" content="profile" />'
|
|
'<meta property="og:url" content="%(url)s" />'
|
|
) % {
|
|
'pic_url': pic_url,
|
|
'url': url,
|
|
}
|