From 8cb2843fd022fb6f77e45936e41402e1ddebcde6 Mon Sep 17 00:00:00 2001 From: yogurtmenn Date: Tue, 25 Mar 2025 12:29:50 +0000 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20bot-tg.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bot-tg.py | 158 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 81 insertions(+), 77 deletions(-) diff --git a/bot-tg.py b/bot-tg.py index a958d4b..5c1c7dd 100644 --- a/bot-tg.py +++ b/bot-tg.py @@ -6,18 +6,30 @@ import requests import asyncio from config import BOT_TOKEN, WEATHER_API_KEY -# Настройка логирования +# настройка логирования logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' -) + level=logging.INFO, + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' + ) logger = logging.getLogger(__name__) -# Инициализация бота +# пасхалочка +CUSTOM_CITY_PHOTOS = { + "киев": { + "photo_url": "https://imgur.com/a/jzVHNoF", + "author": "Wikipedia" + }, + "kyiv": { + "photo_url": "https://imgur.com/a/jzVHNoF", + "author": "Wikipedia" + } + } + +# инициализация бота bot = Bot(token=BOT_TOKEN) dp = Dispatcher() -# Клавиатура +# клавиатура def get_keyboard(): builder = ReplyKeyboardBuilder() builder.button(text="🌤️ Узнать погоду") @@ -25,10 +37,10 @@ def get_keyboard(): return builder.as_markup(resize_keyboard=True) async def get_coordinates(city: str): - """Получение координат города через Nominatim""" + """Получение координат города""" url = f"https://nominatim.openstreetmap.org/search?city={city}&format=json" headers = {"User-Agent": "CityPhotoBot/1.0"} - + try: response = requests.get(url, headers=headers, timeout=10) if response.status_code == 200: @@ -45,27 +57,34 @@ async def get_coordinates(city: str): async def get_weather(lat: float, lon: float, city_name: str) -> str: """Получение данных о погоде""" url = f"https://api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lon}&appid={WEATHER_API_KEY}&units=metric&lang=ru" - + try: response = requests.get(url, timeout=10) if response.status_code == 200: data = response.json() weather_info = ( - f"🌆 Город: {city_name}\n" - f"🌡 Температура: {data['main']['temp']:.1f}°C\n" - f"🧭 Ощущается как: {data['main']['feels_like']:.1f}°C\n" - f"💨 Ветер: {data['wind']['speed']} м/с\n" - f"☁️ Погода: {data['weather'][0]['description'].capitalize()}\n" - f"💧 Влажность: {data['main']['humidity']}%" - ) + f"🌆 Город: {city_name}\n" + f"🌡 Температура: {data['main']['temp']:.1f}°C\n" + f"🧭 Ощущается как: {data['main']['feels_like']:.1f}°C\n" + f"💨 Ветер: {data['wind']['speed']} м/с\n" + f"☁️ Погода: {data['weather'][0]['description'].capitalize()}\n" + f"💧 Влажность: {data['main']['humidity']}%" + ) return weather_info except Exception as e: logger.error(f"Weather API error: {e}") return "Не удалось получить данные о погоде" -async def get_city_photo(city: str, lat: float = None, lon: float = None): - """Поиск фотографии города через Wikipedia и другие источники""" - # 1. Попробуем Wikipedia +async def get_city_photo(city: str): + """Получение фото города с приоритетом ваших собственных фото""" + city_lower = city.lower() + + # проверочка посхалки + if city_lower in CUSTOM_CITY_PHOTOS: + custom = CUSTOM_CITY_PHOTOS[city_lower] + return custom["photo_url"], custom["author"] + + # генерация фото по городам wikipedia_url = f"https://ru.wikipedia.org/w/api.php?action=query&prop=pageimages&titles={city}&pithumbsize=800&format=json" try: response = requests.get(wikipedia_url, timeout=10) @@ -78,45 +97,21 @@ async def get_city_photo(city: str, lat: float = None, lon: float = None): except Exception as e: logger.error(f"Wikipedia API error: {e}") - # 2. Попробуем Wikimedia Commons - wikimedia_url = f"https://commons.wikimedia.org/w/api.php?action=query&generator=images&titles={city}&prop=imageinfo&iiprop=url&iiurlwidth=800&format=json" - try: - response = requests.get(wikimedia_url, timeout=10) - if response.status_code == 200: - data = response.json() - pages = data.get('query', {}).get('pages', {}) - for page in pages.values(): - if 'imageinfo' in page: - return page['imageinfo'][0]['thumburl'], "Wikimedia Commons" - except Exception as e: - logger.error(f"Wikimedia API error: {e}") - - # 3. Для российских городов попробуем PhotoBank RG - if "россия" in city.lower() or any(city.lower().endswith(x) for x in ["ск", "ов", "ев", "ин"]): - try: - photobank_url = f"https://rusneb.ru/api/v1/photos?query={city}&limit=1" - response = requests.get(photobank_url, timeout=10) - if response.status_code == 200: - data = response.json() - if data.get('results'): - return data['results'][0]['image_url'], "PhotoBank RG" - except Exception as e: - logger.error(f"PhotoBank error: {e}") - return None, None +# ответ на /start + @dp.message(Command("start", "help")) async def cmd_start(message: types.Message): await message.answer( - "🏙️ Бот Погоды с фотографиями городов\n\n" - "Отправьте мне название города или поделитесь геопозицией, " - "и я покажу погоду и фото города:", - reply_markup=get_keyboard() - ) + "🏙️ Бот Погоды с фотографиями городов\n\n" + "Отправьте мне название города или поделитесь геопозицией:", + reply_markup=get_keyboard() + ) @dp.message(F.text == "🌤️ Узнать погоду") async def weather_button(message: types.Message): - await message.answer("Введите точное название города:") + await message.answer("Введите название города:") @dp.message(F.location) async def handle_location(message: types.Message): @@ -124,26 +119,26 @@ async def handle_location(message: types.Message): try: lat = message.location.latitude lon = message.location.longitude - - # Получаем название города + + # принятие названия города url = f"https://nominatim.openstreetmap.org/reverse?lat={lat}&lon={lon}&format=json" headers = {"User-Agent": "CityPhotoBot/1.0"} - + response = requests.get(url, headers=headers, timeout=10) if response.status_code == 200: data = response.json() city_name = data.get('address', {}).get('city', - data.get('address', {}).get('town', - data.get('address', {}).get('village', "это место"))) - + data.get('address', {}).get('town', + data.get('address', {}).get('village', "это место"))) + weather_data = await get_weather(lat, lon, city_name) - photo_url, source = await get_city_photo(city_name, lat, lon) - + photo_url, author = await get_city_photo(city_name) + if photo_url: - caption = f"{weather_data}\n\n📷 Источник: {source}" if source else weather_data + caption = f"{weather_data}\n\n📷 Фото: {author}" if author else weather_data await message.answer_photo(photo_url, caption=caption) else: - await message.answer(f"{weather_data}\n\n(Не удалось найти фото города)") + await message.answer(weather_data) except Exception as e: logger.error(f"Location error: {e}") await message.answer("Ошибка обработки местоположения") @@ -152,32 +147,40 @@ async def handle_location(message: types.Message): async def city_handler(message: types.Message): """Обработка текстовых запросов""" city = message.text.strip() - + if city.startswith('/'): return - + logger.info(f"Processing city: {city}") - + try: + # проверка не киев ли это + city_lower = city.lower() + if city_lower in CUSTOM_CITY_PHOTOS: + custom = CUSTOM_CITY_PHOTOS[city_lower] + weather_data = await get_weather(50.45, 30.52, "Киев") # корды киева + await message.answer_photo( + custom["photo_url"], + caption=f"{weather_data}\n\n📷 Фото: {custom['author']}" + ) + return + + # обработка других городов coords = await get_coordinates(city) if not coords: await message.answer("Город не найден. Попробуйте уточнить название") return - + lon, lat = coords weather_data = await get_weather(lat, lon, city) - - # Пробуем получить фото с 3 попытками - for attempt in range(3): - photo_url, source = await get_city_photo(city, lat, lon) - if photo_url: - caption = f"{weather_data}\n\n📷 Источник: {source}" if source else weather_data - await message.answer_photo(photo_url, caption=caption) - return - await asyncio.sleep(1) - - await message.answer(f"{weather_data}\n\n(Не удалось найти фото города)") - + photo_url, author = await get_city_photo(city) + + if photo_url: + caption = f"{weather_data}\n\n📷 Фото: {author}" if author else weather_data + await message.answer_photo(photo_url, caption=caption) + else: + await message.answer(weather_data) + except Exception as e: logger.error(f"City handler error: {e}") await message.answer("Произошла ошибка при обработке запроса") @@ -186,4 +189,5 @@ async def main(): await dp.start_polling(bot) if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file + asyncio.run(main()) +