Request admin approval to trust this device for auto-login. Works only for accounts without 2FA enabled.
()
| 10759 | _WEATHER_LOCK = threading.RLock() |
| 10760 | _WEATHER_TTL = 10 * 60 |
| 10761 | _WEATHER_SEARCH_TTL = 60 * 60 |
| 10762 | |
| 10763 | |
| 10764 | def _weather_json(url: str, timeout: int = 12) -> Dict[str, Any]: |
| 10765 | req = urllib.request.Request(url, headers={"User-Agent": "ButSystem/Weather 1.0", "Accept": "application/json"}) |
| 10766 | with urllib.request.urlopen(req, timeout=timeout) as response: |
| 10767 | raw = response.read(4 * 1024 * 1024) |
| 10768 | data = json.loads(raw.decode("utf-8", errors="replace")) |
| 10769 | if not isinstance(data, dict): |
| 10770 | raise ValueError("invalid weather response") |
| 10771 | return data |
| 10772 | |
| 10773 | |
| 10774 | def _weather_code(code: Any, lang: str, is_day: bool = True) -> Tuple[str, str]: |
| 10775 | try: |
| 10776 | code = int(code) |
| 10777 | except Exception: |
| 10778 | code = -1 |
| 10779 | labels_en = { |
| 10780 | 0: "Clear sky", 1: "Mainly clear", 2: "Partly cloudy", 3: "Overcast", |
| 10781 | 45: "Fog", 48: "Rime fog", 51: "Light drizzle", 53: "Drizzle", 55: "Heavy drizzle", |
| 10782 | 56: "Freezing drizzle", 57: "Heavy freezing drizzle", 61: "Light rain", 63: "Rain", 65: "Heavy rain", |
| 10783 | 66: "Freezing rain", 67: "Heavy freezing rain", 71: "Light snow", 73: "Snow", 75: "Heavy snow", |
| 10784 | 77: "Snow grains", 80: "Light showers", 81: "Showers", 82: "Heavy showers", |
| 10785 | 85: "Snow showers", 86: "Heavy snow showers", 95: "Thunderstorm", 96: "Thunderstorm with hail", 99: "Severe thunderstorm with hail", |
| 10786 | } |
| 10787 | labels_el = { |
| 10788 | 0: "Καθαρός ουρανός", 1: "Κυρίως αίθριος", 2: "Λίγες νεφώσεις", 3: "Συννεφιά", |
| 10789 | 45: "Ομίχλη", 48: "Παγωμένη ομίχλη", 51: "Ασθενής ψιχάλα", 53: "Ψιχάλα", 55: "Έντονη ψιχάλα", |
| 10790 | 56: "Παγωμένη ψιχάλα", 57: "Έντονη παγωμένη ψιχάλα", 61: "Ασθενής βροχή", 63: "Βροχή", 65: "Ισχυρή βροχή", |
| 10791 | 66: "Παγωμένη βροχή", 67: "Ισχυρή παγωμένη βροχή", 71: "Ασθενής χιονόπτωση", 73: "Χιονόπτωση", 75: "Ισχυρή χιονόπτωση", |
| 10792 | 77: "Κόκκοι χιονιού", 80: "Ασθενείς μπόρες", 81: "Μπόρες", 82: "Ισχυρές μπόρες", |
| 10793 | 85: "Μπόρες χιονιού", 86: "Ισχυρές μπόρες χιονιού", 95: "Καταιγίδα", 96: "Καταιγίδα με χαλάζι", 99: "Ισχυρή καταιγίδα με χαλάζι", |
| 10794 | } |
| 10795 | if code == 0: |
| 10796 | icon = "☀️" if is_day else "🌙" |
| 10797 | elif code in (1, 2): |
| 10798 | icon = "🌤️" if is_day else "☁️" |
| 10799 | elif code == 3: |
| 10800 | icon = "☁️" |
| 10801 | elif code in (45, 48): |
| 10802 | icon = "🌫️" |
| 10803 | elif code in (51, 53, 55, 56, 57): |
| 10804 | icon = "🌦️" |
| 10805 | elif code in (61, 63, 65, 66, 67, 80, 81, 82): |
| 10806 | icon = "🌧️" |
| 10807 | elif code in (71, 73, 75, 77, 85, 86): |
| 10808 | icon = "🌨️" |
| 10809 | elif code in (95, 96, 99): |
| 10810 | icon = "⛈️" |
| 10811 | else: |
| 10812 | icon = "🌡️" |
| 10813 | labels = labels_el if lang == "el" else labels_en |
| 10814 | return labels.get(code, "Άγνωστες συνθήκες" if lang == "el" else "Unknown conditions"), icon |
| 10815 | |
| 10816 | |
| 10817 | def _weather_daily_rows(raw: Dict[str, Any], lang: str) -> List[Dict[str, Any]]: |
| 10818 | daily = raw.get("daily") if isinstance(raw.get("daily"), dict) else {} |
nothing calls this directly
no test coverage detected