You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
wttr.in/lib/parse_query.py

178 lines
4.3 KiB

import re
import json
import zlib
import base64
def serialize(parsed_query):
return base64.b64encode(
zlib.compress(json.dumps(parsed_query).encode("utf-8")), altchars=b"-_"
).decode("utf-8")
def deserialize(url):
string = url[2:]
extension = None
if "." in string:
string, extension = string.split(".", 1)
try:
result = json.loads(
zlib.decompress(base64.b64decode(string, altchars=b"-_")).decode("utf-8")
)
except zlib.error:
return None
if extension == "png":
result["png_filename"] = url
result["html_output"] = False
return result
def metric_or_imperial(query, lang, us_ip=False):
""" """
# what units should be used
# metric or imperial
# based on query and location source (imperial for US by default)
if query.get("use_metric", False) and not query.get("use_imperial", False):
query["use_imperial"] = False
query["use_metric"] = True
elif query.get("use_imperial", False) and not query.get("use_metric", False):
query["use_imperial"] = True
query["use_metric"] = False
elif lang == "us":
# slack uses m by default, to override it speciy us.wttr.in
query["use_imperial"] = True
query["use_metric"] = False
else:
if us_ip:
query["use_imperial"] = True
query["use_metric"] = False
else:
query["use_imperial"] = False
query["use_metric"] = True
return query
def parse_query(args):
result = {}
reserved_args = ["lang"]
q = ""
for key, val in args.items():
if len(val) == 0:
q += key
continue
if val == "True":
val = True
if val == "False":
val = False
result[key] = val
if q is None:
return result
if "A" in q:
result["force-ansi"] = True
if "d" in q:
result["dumb"] = True
if "n" in q:
result["narrow"] = True
if "m" in q:
result["use_metric"] = True
if "M" in q:
result["use_metric"] = True
result["use_ms_for_wind"] = True
if "u" in q:
result["use_imperial"] = True
if "I" in q:
result["inverted_colors"] = True
if "t" in q:
result["transparency"] = "150"
if "T" in q:
result["no-terminal"] = True
if "p" in q:
result["padding"] = True
for days in "0123":
if days in q:
result["days"] = days
if "q" in q:
result["no-caption"] = True
if "Q" in q:
result["no-city"] = True
if "F" in q:
result["no-follow-line"] = True
for key, val in args.items():
if val == "True":
val = True
if val == "False":
val = False
if val:
result[key] = val
# currently `view` is alias for `format`
if "format" in result and not result.get("view"):
result["view"] = result["format"]
del result["format"]
return result
def parse_wttrin_png_name(name):
"""
Parse the PNG filename and return the result as a dictionary.
For example:
input = City_200x_lang=ru.png
output = {
"lang": "ru",
"width": "200",
"filetype": "png",
"location": "City"
}
"""
parsed = {}
to_be_parsed = {}
if name.lower()[-4:] == ".png":
parsed["filetype"] = "png"
name = name[:-4]
parts = name.split("_")
parsed["location"] = parts[0]
one_letter_options = ""
for part in parts[1:]:
if re.match("(?:[0-9]+)x", part):
parsed["width"] = part[:-1]
elif re.match("x(?:[0-9]+)", part):
parsed["height"] = part[1:]
elif re.match(part, "(?:[0-9]+)x(?:[0-9]+)"):
parsed["width"], parsed["height"] = part.split("x", 1)
elif "=" in part:
arg, val = part.split("=", 1)
to_be_parsed[arg] = val
else:
one_letter_options += part
for letter in one_letter_options:
to_be_parsed[letter] = ""
parsed.update(parse_query(to_be_parsed))
# currently `view` is alias for `format`
if "format" in parsed and not parsed.get("view"):
parsed["view"] = parsed["format"]
del parsed["format"]
return parsed