From 7a9341fbd729558cf5456f3409f003b9ce4da504 Mon Sep 17 00:00:00 2001 From: Vlad Date: Fri, 11 Jul 2025 12:55:37 +0300 Subject: [PATCH] =?UTF-8?q?=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE:=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=20=D1=81=D0=BE?= =?UTF-8?q?=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20config.yaml?= =?UTF-8?q?=20=D0=B3=D0=BB=D0=B0=D0=B2=D0=BD=D0=B0=D1=8F=20=D1=81=D1=82?= =?UTF-8?q?=D1=80=D0=B0=D0=BD=D0=B8=D1=86=D0=B0=20=D1=81=D1=80=D0=B0=D0=B7?= =?UTF-8?q?=D1=83=20=D0=BE=D1=82=D0=BE=D0=B1=D1=80=D0=B0=D0=B6=D0=B0=D0=B5?= =?UTF-8?q?=D1=82=20=D0=B0=D0=BA=D1=82=D1=83=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D0=B5=20(=D0=BA=D0=BE?= =?UTF-8?q?=D0=BD=D1=84=D0=B8=D0=B3=20=D0=BF=D0=B5=D1=80=D0=B5=D1=87=D0=B8?= =?UTF-8?q?=D1=82=D1=8B=D0=B2=D0=B0=D0=B5=D1=82=D1=81=D1=8F=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=20=D0=BA=D0=B0=D0=B6=D0=B4=D0=BE=D0=BC=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D1=81=D0=B5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog.md | 5 +++- main.py | 75 +++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 72 insertions(+), 8 deletions(-) diff --git a/changelog.md b/changelog.md index c301ce5..a08c835 100644 --- a/changelog.md +++ b/changelog.md @@ -18,4 +18,7 @@ - Создана структура каталогов: templates/, static/ - Вынесены данные Applications и Bookmarks в config.yaml - Добавлен базовый шаблон для главной страницы -- Перенесены ассеты из example/home_files в static/ \ No newline at end of file +- Перенесены ассеты из example/home_files в static/ + +## [fix] Мгновенное применение изменений config.yaml на главной странице +- Исправлено: после сохранения config.yaml главная страница теперь сразу отображает актуальные данные (конфиг перечитывается при каждом запросе, кэш убран) \ No newline at end of file diff --git a/main.py b/main.py index ce40e9b..d1b8cd4 100644 --- a/main.py +++ b/main.py @@ -13,6 +13,9 @@ CONFIG_PATH = 'config.yaml' # Кэш для погоды weather_cache = {'data': None, 'ts': 0} +# Кэш для прогноза +weather_forecast_cache = {'data': None, 'ts': 0} + def load_config(): with open(CONFIG_PATH, encoding='utf-8') as f: return yaml.safe_load(f) @@ -51,12 +54,56 @@ def get_weather(): data = resp.json() temp = data['current']['temp_c'] cloud = data['current']['cloud'] - result = {'temp': temp, 'cloud': cloud} + condition = data['current'].get('condition', {}) + icon = condition.get('icon', '') + text = condition.get('text', '') + result = {'temp': temp, 'cloud': cloud, 'icon': icon, 'text': text} weather_cache = {'data': result, 'ts': now} return result except Exception: return None +def get_weather_forecast(): + global weather_forecast_cache + now = time.time() + WEATHER_CACHE_TTL = get_weather_cache_ttl() + if weather_forecast_cache['data'] and now - weather_forecast_cache['ts'] < WEATHER_CACHE_TTL: + return weather_forecast_cache['data'] + config = load_config() + w = config.get('weather', {}) + api_key = w.get('api_key') + lat = w.get('lat') + lon = w.get('lon') + if not api_key or not lat or not lon: + raise Exception('Не заданы api_key, lat или lon') + url = f"https://api.weatherapi.com/v1/forecast.json?key={api_key}&q={lat},{lon}&days=10&lang=ru" + try: + resp = requests.get(url, timeout=5) + resp.raise_for_status() + data = resp.json() + forecast = [] + for day in data['forecast']['forecastday']: + d = day['day'] + temp = d.get('avgtemp_c') + if temp is None: + temp = d.get('maxtemp_c') + cloud = d.get('cloud', 0) + condition = d.get('condition', {}) + forecast.append({ + 'date': day['date'], + 'temp': temp, + 'cloud': cloud, + 'text': condition.get('text', ''), + 'icon': condition.get('icon', '') + }) + weather_forecast_cache = {'data': forecast, 'ts': now} + return forecast + except Exception as e: + try: + return {'_error': resp.text} + except: + return {'_error': str(e)} + @app.route('/api/config', methods=['GET']) def get_config(): try: @@ -78,18 +125,32 @@ def update_config(): except Exception as e: return make_response(jsonify({'error': str(e)}), 400) -config = load_config() +@app.route('/api/weather-forecast', methods=['GET']) +def api_weather_forecast(): + forecast = get_weather_forecast() + if forecast is None: + return {'error': 'Ошибка получения прогноза'}, 500 + if isinstance(forecast, dict) and '_error' in forecast: + return {'error': forecast['_error']}, 500 + return {'forecast': forecast} + +# config = load_config() # Удаляем глобальную переменную @app.route('/') def index(): - try: - locale.setlocale(locale.LC_TIME, 'ru_RU.UTF-8') - except: - pass + # Словари для русских дат + days = ['Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота', 'Воскресенье'] + months = [ + '', 'января', 'февраля', 'марта', 'апреля', 'мая', 'июня', + 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря' + ] now = datetime.now() - now_str = now.strftime('%A, %d %B %Y').capitalize() + day = days[now.weekday()] + month = months[now.month] + now_str = f"{day}, {now.day} {month} {now.year}" current_time = now.strftime('%H:%M:%S') weather = get_weather() + config = load_config() # Загружаем актуальный конфиг при каждом запросе return render_template('index.html', applications=config['applications'], bookmarks=config['bookmarks'], now=now_str, current_time=current_time, weather=weather) if __name__ == '__main__':