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