workspace: initial commit - MEMORY, tasks, skills, memory

This commit is contained in:
Stream
2026-04-12 21:46:09 +03:00
parent 84cd63ce70
commit 256086e73e
224 changed files with 31654 additions and 0 deletions

View File

@@ -0,0 +1,226 @@
#!/usr/bin/env python3
"""
Скрипт для проверки API ключа и доступности Flightradar24 API
"""
import os
import sys
import json
import requests
from datetime import datetime
def check_api_key(api_key):
"""Проверка валидности API ключа"""
print("🔑 Проверка API ключа Flightradar24...")
print(f" Ключ: {api_key[:10]}...{api_key[-4:] if len(api_key) > 14 else '***'}")
print()
# Базовый URL API
base_url = "https://api.flightradar24.com/common/v1"
# Подготовка заголовков
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
# Тестовые запросы (минимальные по кредитам)
test_endpoints = [
("/airport/light/SVO", "Аэропорт Шереметьево (light)"),
("/airline/light/AFL", "Авиакомпания Аэрофлот (light)"),
("/usage", "Отчет об использовании API"),
]
results = []
total_credits_used = 0
for endpoint, description in test_endpoints:
try:
url = base_url + endpoint
print(f"🔍 Тест: {description}")
print(f" Endpoint: {endpoint}")
response = requests.get(url, headers=headers, timeout=10)
if response.status_code == 200:
data = response.json()
# Проверка структуры ответа
if endpoint == "/usage":
credits_used = data.get("credits_used", 0)
credits_total = data.get("credits_total", 60000)
total_credits_used = credits_used
print(f" ✅ Успешно (кредитов использовано: {credits_used:,}/{credits_total:,})")
# Определение типа подписки
if credits_total >= 1000000:
subscription = "Advanced или выше"
elif credits_total >= 100000:
subscription = "Essential"
elif credits_total >= 60000:
subscription = "Explorer (промо до 120k)"
else:
subscription = "Неизвестный тариф"
print(f" 💳 Тариф: {subscription} ({credits_total:,} кредитов/месяц)")
else:
# Для других endpoints проверяем наличие данных
if data.get("data") or "name" in data:
print(f" ✅ Успешно (данные получены)")
else:
print(f" ⚠️ Ответ получен, но данных нет")
results.append((endpoint, True, response.status_code, None))
elif response.status_code == 401:
print(f" ❌ Ошибка 401: Неавторизован (неверный API ключ)")
results.append((endpoint, False, response.status_code, "Invalid API key"))
break
elif response.status_code == 403:
print(f" ❌ Ошибка 403: Доступ запрещен (недостаточно прав или кредитов)")
results.append((endpoint, False, response.status_code, "Access denied"))
elif response.status_code == 404:
print(f" ⚠️ Ошибка 404: Endpoint не найден (возможно устаревший)")
results.append((endpoint, False, response.status_code, "Not found"))
elif response.status_code == 429:
print(f" ⚠️ Ошибка 429: Слишком много запросов (лимит rate limiting)")
results.append((endpoint, False, response.status_code, "Rate limited"))
else:
print(f" ❌ Ошибка {response.status_code}: {response.text[:100]}")
results.append((endpoint, False, response.status_code, response.text[:100]))
except requests.exceptions.Timeout:
print(f" ❌ Таймаут соединения")
results.append((endpoint, False, "Timeout", "Connection timeout"))
except requests.exceptions.ConnectionError:
print(f" ❌ Ошибка соединения")
results.append((endpoint, False, "ConnectionError", "Network error"))
except Exception as e:
print(f" ❌ Неожиданная ошибка: {e}")
results.append((endpoint, False, "Exception", str(e)))
print()
# Сводка результатов
print("=" * 60)
print("📊 Сводка проверки API:")
print()
successful_tests = sum(1 for _, success, _, _ in results if success)
total_tests = len(results)
print(f"✅ Успешных тестов: {successful_tests}/{total_tests}")
if successful_tests > 0:
print("🎉 API ключ валиден и работает!")
# Дополнительная информация
print()
print("📈 Информация о подписке:")
# Проверка типа подписки через usage endpoint
try:
response = requests.get(base_url + "/usage", headers=headers, timeout=5)
if response.status_code == 200:
usage_data = response.json()
credits_total = usage_data.get("credits_total", 0)
# Определение тарифа
if credits_total >= 1000000:
tariff = "Advanced или Business"
features = "Полный доступ ко всем endpoints"
elif credits_total >= 100000:
tariff = "Essential"
features = "Расширенный доступ, но без некоторых count endpoints"
elif credits_total >= 60000:
tariff = "Explorer"
features = "Базовый доступ (60k кредитов/мес)"
if credits_total >= 120000:
tariff += " (промо до 120k)"
else:
tariff = "Неизвестный тариф"
features = "Проверьте документацию"
print(f" 💳 Тариф: {tariff}")
print(f" 🎯 Кредитов в месяц: {credits_total:,}")
print(f" 📋 Возможности: {features}")
# Рекомендации по использованию кредитов
print()
print("💡 Рекомендации по использованию:")
print(f" - Средний запрос: 5-50 кредитов")
print(f" - Примерное количество запросов: {credits_total // 50:,} в месяц")
print(f" - Экономьте кредиты: используйте light endpoints и кэширование")
except:
print(" ⚠️ Не удалось получить детальную информацию о тарифе")
else:
print("❌ API ключ не работает. Возможные причины:")
print(" - Неверный API ключ")
print(" - Подписка не активирована")
print(" - Закончились кредиты")
print(" - Проблемы с сетью")
print()
print("🔧 Решение:")
print(" 1. Проверьте правильность API ключа")
print(" 2. Убедитесь, что подписка Explorer активна")
print(" 3. Проверьте баланс кредитов в личном кабинете")
print()
print("🔗 Полезные ссылки:")
print(" - Документация API: https://fr24api.flightradar24.com/")
print(" - Подписки и кредиты: https://fr24api.flightradar24.com/subscriptions-and-credits")
print(" - Поддержка: https://support.fr24.com/")
return successful_tests > 0
def main():
print("=== Flightradar24 API Validator ===")
print("Проверка валидности API ключа и доступности сервиса")
print()
# Получение API ключа
api_key = os.getenv("FLIGHTRADAR24_API_KEY")
if not api_key:
print("❌ Переменная окружения FLIGHTRADAR24_API_KEY не установлена")
print()
print("Установите API ключ командой:")
print(" export FLIGHTRADAR24_API_KEY='your_api_key_here'")
print()
print("Или запустите скрипт с ключом:")
print(" FLIGHTRADAR24_API_KEY='your_key' python3 check_api.py")
sys.exit(1)
# Проверка формата ключа (базовая)
if len(api_key) < 20:
print("⚠️ API ключ слишком короткий. Убедитесь в правильности.")
# Выполнение проверки
is_valid = check_api_key(api_key)
# Возвращаем соответствующий код выхода
if is_valid:
print("\n✅ Проверка завершена успешно")
sys.exit(0)
else:
print("\n❌ Проверка не пройдена")
sys.exit(1)
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\n\n⏹ Проверка прервана пользователем")
sys.exit(1)
except Exception as e:
print(f"\n❌ Неожиданная ошибка: {e}")
sys.exit(2)

View File

@@ -0,0 +1,210 @@
#!/usr/bin/env python3
"""
Flightradar24 API Client для sandbox и production
Поддержка обоих окружений для разработки прототипа карты шумового загрязнения
"""
import os
import sys
import json
import requests
from datetime import datetime, timedelta
from typing import Optional, Dict, Any, Tuple
class Flightradar24Client:
"""Клиент для работы с Flightradar24 API (sandbox и production)"""
def __init__(self, use_sandbox: bool = True, api_key: Optional[str] = None):
"""
Инициализация клиента
Args:
use_sandbox: Использовать sandbox окружение (True) или production (False)
api_key: Ключ API (если None, берётся из переменных окружения)
"""
self.use_sandbox = use_sandbox
if use_sandbox:
self.base_url = "https://fr24api.flightradar24.com/api"
self.api_key = api_key or os.getenv("FLIGHTRADAR24_SANDBOX_KEY") or os.getenv("FLIGHTRADAR24_API_KEY")
self.default_headers = {
"Accept": "application/json",
"Accept-Version": "v1"
}
else:
self.base_url = "https://api.flightradar24.com/common/v1"
self.api_key = api_key or os.getenv("FLIGHTRADAR24_PRODUCTION_KEY") or os.getenv("FLIGHTRADAR24_API_KEY")
self.default_headers = {
"Content-Type": "application/json"
}
if not self.api_key:
raise ValueError(
"API ключ не предоставлен. Установите переменные окружения:\n"
" - FLIGHTRADAR24_SANDBOX_KEY (для sandbox)\n"
" - FLIGHTRADAR24_PRODUCTION_KEY (для production)\n"
" - Или FLIGHTRADAR24_API_KEY (по умолчанию для sandbox)"
)
self.session = requests.Session()
self.session.headers.update({
"Authorization": f"Bearer {self.api_key}",
**self.default_headers
})
print(f"🔧 Инициализирован клиент для {'sandbox' if use_sandbox else 'production'}")
print(f" Base URL: {self.base_url}")
print(f" Key: {self.api_key[:15]}...{self.api_key[-10:] if len(self.api_key) > 25 else '***'}")
def _make_request(self, endpoint: str, params: Optional[Dict] = None) -> Dict[str, Any]:
"""Базовый метод для выполнения запросов к API"""
url = f"{self.base_url}{endpoint}"
try:
response = self.session.get(url, params=params, timeout=30)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"⚠️ Ошибка при запросе к {url}: {e}")
if hasattr(e, 'response') and e.response:
print(f" Статус: {e.response.status_code}")
print(f" Ответ: {e.response.text[:500]}")
raise
def get_airport_info_light(self, airport_code: str) -> Dict[str, Any]:
"""Получить базовую информацию об аэропорте (light endpoint)"""
return self._make_request(f"/airport/light/{airport_code}")
def get_airline_info_light(self, airline_code: str) -> Dict[str, Any]:
"""Получить базовую информацию об авиакомпании (light endpoint)"""
return self._make_request(f"/airline/light/{airline_code}")
def get_live_flight_positions(self,
bounds: Optional[str] = None,
limit: int = 10) -> Dict[str, Any]:
"""
Получить live позиции самолетов
Args:
bounds: Границы в формате 'lat1,lon1,lat2,lon2' (опционально)
limit: Ограничение количества результатов
"""
params = {"limit": limit}
if bounds:
params["bounds"] = bounds
return self._make_request("/flight/list", params)
def get_flight_details(self, flight_id: str) -> Dict[str, Any]:
"""Получить детальную информацию о конкретном рейсе"""
return self._make_request(f"/flight/{flight_id}")
def get_historical_flight_events(self,
flight_id: str,
start_time: Optional[str] = None,
end_time: Optional[str] = None) -> Dict[str, Any]:
"""
Получить исторические события полета
Args:
flight_id: Идентификатор рейса
start_time: Начальное время в формате ISO (опционально)
end_time: Конечное время в формате ISO (опционально)
"""
params = {}
if start_time:
params["start"] = start_time
if end_time:
params["end"] = end_time
return self._make_request(f"/flight/{flight_id}/history", params)
def get_flight_tracks(self, flight_id: str) -> Dict[str, Any]:
"""Получить треки полета (playback)"""
return self._make_request(f"/flight/{flight_id}/playback")
def get_usage_report(self) -> Dict[str, Any]:
"""Получить отчет об использовании API (использованные кредиты)"""
return self._make_request("/usage")
def search_flights(self,
query: str,
limit: int = 20) -> Dict[str, Any]:
"""
Поиск рейсов по различным критериям
Args:
query: Строка поиска (номер рейса, callsign, регистрация)
limit: Ограничение количества результатов
"""
params = {"query": query, "limit": limit}
return self._make_request("/search", params)
def print_flight_info(flight_data: Dict[str, Any]):
"""Красиво вывести информацию о рейсе"""
if "data" in flight_data and flight_data["data"]:
flight = flight_data["data"][0]
print(f"Рейс: {flight.get('callsign', 'N/A')}")
print(f"Номер: {flight.get('flight', 'N/A')}")
print(f"Самолет: {flight.get('type', 'N/A')} ({flight.get('reg', 'N/A')})")
print(f"Откуда: {flight.get('orig_icao', 'N/A')} -> Куда: {flight.get('dest_icao', 'N/A')}")
print(f"Высота: {flight.get('alt', 'N/A')} ft, Скорость: {flight.get('gspeed', 'N/A')} kts")
if "lat" in flight and "lon" in flight:
print(f"Координаты: {flight['lat']:.4f}, {flight['lon']:.4f}")
print(f"Источник данных: {flight.get('source', 'N/A')}")
print("-" * 50)
def main():
"""Основная функция демонстрации"""
print("=== Flightradar24 Explorer API Demo ===")
print("Тариф Explorer предоставляет доступ к следующим endpoint'ам:")
print("1. Статические данные (аэропорты/авиакомпании light)")
print("2. Live позиции самолетов (light и full)")
print("3. Исторические события полетов")
print("4. Треки полетов (playback)")
print("5. Поиск рейсов")
print("6. Отчет об использовании API")
print()
# Проверка API ключа
api_key = os.getenv("FLIGHTRADAR24_API_KEY")
if not api_key:
print("❌ API ключ не найден в переменных окружения.")
print("Установите его командой: export FLIGHTRADAR24_API_KEY='your_key_here'")
print("Или передайте как аргумент командной строки.")
return
try:
# Инициализация клиента
client = Flightradar24Explorer(api_key)
print("✅ API клиент инициализирован успешно")
# Демонстрация возможностей (закомментирована, т.к. требует реальных запросов)
print("\nДля использования раскомментируйте нужные вызовы в коде:")
print("# 1. Получить информацию об аэропорте")
print("# airport_info = client.get_airport_info_light('SVO')")
print("# print(json.dumps(airport_info, indent=2, ensure_ascii=False))")
print()
print("# 2. Получить live позиции самолетов")
print("# flights = client.get_live_flight_positions(limit=5)")
print("# print_flight_info(flights)")
print()
print("# 3. Поиск рейсов")
print("# results = client.search_flights('SU100')")
print("# print(json.dumps(results, indent=2, ensure_ascii=False))")
print()
print("# 4. Получить отчет об использовании")
print("# usage = client.get_usage_report()")
print("# print(json.dumps(usage, indent=2, ensure_ascii=False))")
print("\n📋 Примеры запросов подготовлены.")
print("Для начала работы укажите конкретные задачи:")
print("- Мониторинг конкретных рейсов")
print("- Анализ маршрутов авиакомпаний")
print("- Построение дашбордов")
print("- Сбор статистики")
except Exception as e:
print(f"❌ Ошибка: {e}")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,195 @@
#!/usr/bin/env python3
"""
Скрипт для проверки обоих API ключей (sandbox и production)
"""
import os
import sys
import json
import requests
def test_api_key(api_key, is_sandbox=True):
"""Проверка API ключа"""
if is_sandbox:
base_url = "https://fr24api.flightradar24.com/api"
headers = {
"Authorization": f"Bearer {api_key}",
"Accept": "application/json",
"Accept-Version": "v1"
}
key_type = "sandbox"
else:
base_url = "https://api.flightradar24.com/common/v1"
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
key_type = "production"
print(f"\n🔑 Тестирование {key_type} ключа...")
print(f" Ключ: {api_key[:15]}...{api_key[-10:] if len(api_key) > 25 else '***'}")
print(f" Base URL: {base_url}")
results = []
# Тестовые endpoints в зависимости от типа
if is_sandbox:
test_endpoints = [
("/static/airlines/AAL/light", "Авиакомпания American Airlines (light)"),
("/live/flight-positions/light?bounds=50.682,46.218,14.422,22.243", "Live позиции (test bounds)"),
]
else:
test_endpoints = [
("/airport/light/SVO", "Аэропорт Шереметьево (light)"),
("/usage", "Отчет об использовании API"),
]
for endpoint, description in test_endpoints:
try:
url = base_url + endpoint if not endpoint.startswith("http") else endpoint
print(f"\n🔍 Тест: {description}")
print(f" Endpoint: {endpoint.split('?')[0]}")
# Обработка параметров в URL
if "?" in endpoint:
url, query_string = url.split("?", 1)
from urllib.parse import parse_qs
params = parse_qs(query_string)
# Преобразуем списки в одиночные значения
params = {k: v[0] if len(v) == 1 else v for k, v in params.items()}
response = requests.get(url, headers=headers, params=params, timeout=10)
else:
response = requests.get(url, headers=headers, timeout=10)
print(f" Статус: {response.status_code}")
if response.status_code == 200:
try:
data = response.json()
print(f" ✅ Успешно")
# Вывод фрагмента данных
if "data" in data:
data_count = len(data.get("data", []))
print(f" 📊 Данных: {data_count} записей")
if data_count > 0:
first_item = data["data"][0]
print(f" 🎯 Пример: {json.dumps(first_item, ensure_ascii=False)[:100]}...")
elif "name" in data:
print(f" 📝 {data.get('name', 'N/A')} ({data.get('iata', 'N/A')}/{data.get('icao', 'N/A')})")
results.append((endpoint, True, response.status_code, None))
except json.JSONDecodeError:
print(f" ⚠️ Ответ не JSON: {response.text[:100]}")
results.append((endpoint, False, response.status_code, "Not JSON"))
elif response.status_code == 400:
print(f" ❌ Ошибка 400: Неверный запрос")
print(f" Детали: {response.text[:200]}")
results.append((endpoint, False, response.status_code, "Bad request"))
elif response.status_code == 401:
print(f" ❌ Ошибка 401: Неавторизован")
results.append((endpoint, False, response.status_code, "Unauthorized"))
elif response.status_code == 403:
print(f" ❌ Ошибка 403: Доступ запрещен")
print(f" Возможно: неверный ключ, нет прав, закончились кредиты")
results.append((endpoint, False, response.status_code, "Forbidden"))
elif response.status_code == 404:
print(f" ⚠️ Ошибка 404: Endpoint не найден")
results.append((endpoint, False, response.status_code, "Not found"))
elif response.status_code == 429:
print(f" ⚠️ Ошибка 429: Слишком много запросов")
results.append((endpoint, False, response.status_code, "Rate limited"))
else:
print(f" ❌ Ошибка {response.status_code}")
print(f" Ответ: {response.text[:200]}")
results.append((endpoint, False, response.status_code, response.text[:100]))
except requests.exceptions.Timeout:
print(f" ⏱️ Таймаут соединения")
results.append((endpoint, False, "Timeout", "Connection timeout"))
except requests.exceptions.ConnectionError:
print(f" 🔌 Ошибка соединения")
results.append((endpoint, False, "ConnectionError", "Network error"))
except Exception as e:
print(f" 💥 Неожиданная ошибка: {e}")
results.append((endpoint, False, "Exception", str(e)))
# Сводка
successful = sum(1 for _, success, _, _ in results if success)
total = len(results)
print(f"\n📊 Сводка {key_type}: {successful}/{total} успешных тестов")
if successful > 0:
print(f"🎉 {key_type.capitalize()} ключ работает!")
return True, key_type
else:
print(f"{key_type.capitalize()} ключ не работает")
return False, key_type
def main():
print("=== Проверка API ключей Flightradar24 ===")
print("Тестирование sandbox и production ключей")
print("=" * 50)
# Ключи из сообщений
sandbox_key = "9d4d192b-8641-4420-b00e-09e3d935badf|fIMdnj8WixjDqyaUTHLKPlgHU9d5JiOZwJJWGiVHdcda602e"
production_key = "019d0c18-2d07-704c-9b3e-af32f2482f79|lDODG5lI4BuOGDaE24TPLqRANiuSLXudbC8VrbCgf351f19f"
# Тестируем sandbox
sandbox_ok, _ = test_api_key(sandbox_key, is_sandbox=True)
# Тестируем production
production_ok, _ = test_api_key(production_key, is_sandbox=False)
print("\n" + "=" * 50)
print("🎯 Итоговые результаты:")
print(f" Sandbox: {'✅ Работает' if sandbox_ok else 'Не работает'}")
print(f" Production: {'✅ Работает' if production_ok else 'Не работает'}")
if sandbox_ok and production_ok:
print("\n🎉 Оба ключа работают! Можно начинать разработку.")
print(" Этап 1: Прототип на sandbox данных")
print(" Этап 2: Переход на production данные после отмашки")
elif sandbox_ok and not production_ok:
print("\n⚠️ Sandbox работает, production нет.")
print(" Можно разрабатывать прототип на sandbox, но нужно проверить production ключ.")
print(" Возможные причины: неактивированная подписка, закончились кредиты.")
elif not sandbox_ok and production_ok:
print("\n⚠️ Production работает, sandbox нет.")
print(" Можно разрабатывать сразу на production (будет расходовать кредиты).")
else:
print("\n❌ Ни один ключ не работает.")
print(" Проверьте правильность ключей и статус подписки.")
# Сохраняем ключи в файл .env для удобства
with open(".env", "w") as f:
f.write(f"FLIGHTRADAR24_SANDBOX_KEY={sandbox_key}\n")
f.write(f"FLIGHTRADAR24_PRODUCTION_KEY={production_key}\n")
f.write(f"FLIGHTRADAR24_API_KEY={sandbox_key} # По умолчанию используем sandbox\n")
print(f"\n💾 Ключи сохранены в .env файл")
print(" Для использования в скриптах:")
print(" - Sandbox: FLIGHTRADAR24_SANDBOX_KEY")
print(" - Production: FLIGHTRADAR24_PRODUCTION_KEY")
print(" - По умолчанию: FLIGHTRADAR24_API_KEY (sandbox)")
return 0 if sandbox_ok else 1
if __name__ == "__main__":
try:
sys.exit(main())
except KeyboardInterrupt:
print("\n\n⏹ Проверка прервана")
sys.exit(1)
except Exception as e:
print(f"\n💥 Критическая ошибка: {e}")
sys.exit(2)