auto-sync: 2026-04-21 01:30:01

This commit is contained in:
Stream
2026-04-21 01:30:01 +03:00
parent 8696a05670
commit 7eb1b2c43e
2 changed files with 71 additions and 8 deletions

View File

@@ -14,6 +14,57 @@ import psycopg2
import psycopg2.extras
from flask import Flask, jsonify, request, send_from_directory, Response
# ── IATA → город маппинг ──────────────────────────────────────────────────────
IATA_CITY = {
"AAQ": "Анапа", "ABA": "Абакан", "ADB": "Измир", "ADD": "Аддис-Абеба",
"AER": "Сочи", "AKX": "Актобе", "ALA": "Алматы", "AMM": "Амман",
"AMS": "Амстердам", "ARH": "Архангельск", "ARN": "Стокгольм", "ASB": "Ашхабад",
"ASF": "Астрахань", "ATH": "Афины", "AUH": "Абу-Даби", "AYT": "Анталья",
"AZN": "Андижан", "BAX": "Барнаул", "BCN": "Барселона", "BEG": "Белград",
"BER": "Берлин", "BEY": "Бейрут", "BJV": "Бодрум", "BKK": "Бангкок",
"BNE": "Брисбен", "BOG": "Богота", "BOM": "Мумбаи", "BQS": "Благовещенск",
"BRU": "Брюссель", "BTK": "Братск", "BUS": "Батуми", "BXK": "Бухара",
"BZK": "Брянск", "CAI": "Каир", "CCJ": "Кожикоде", "CEK": "Челябинск",
"CGK": "Джакарта", "CGN": "Кёльн", "CMN": "Касабланка", "CMB": "Коломбо",
"CSY": "Чебоксары", "CXI": "Кашгар", "CZM": "Косумель", "DEL": "Дели",
"DME": "Домодедово", "DMJ": "Домодедово", "DOH": "Доха", "DSS": "Дакар",
"DXB": "Дубай", "EGO": "Белгород", "EKB": "Екатеринбург", "EVN": "Ереван",
"FRA": "Франкфурт", "FRU": "Бишкек", "GDZ": "Геленджик", "GDX": "Магадан",
"GIF": "Гифу", "GOI": "Гоа", "GOJ": "Нижний Новгород", "GRV": "Грозный",
"GRZ": "Грац", "GYD": "Баку", "HAD": "Ханчжоу", "HAM": "Гамбург",
"HEL": "Хельсинки", "HMA": "Ханты-Мансийск", "HRB": "Харбин",
"HRG": "Хургада", "HKT": "Пхукет", "HYD": "Хайдарабад", "IKT": "Иркутск",
"IKA": "Тегеран", "IST": "Стамбул", "IXC": "Чандигарх", "JED": "Джидда",
"JFK": "Нью-Йорк", "KGD": "Калининград", "KGV": "Когалым",
"KHV": "Хабаровск", "KJA": "Красноярск", "KLO": "Калининград",
"KRR": "Краснодар", "KUF": "Самара", "KUL": "Куала-Лумпур",
"KZN": "Казань", "LAX": "Лос-Анджелес", "LED": "Санкт-Петербург",
"LHR": "Лондон", "LPK": "Липецк", "MIA": "Майами", "MLE": "Мале",
"MMK": "Мурманск", "MRV": "Минеральные Воды", "MSQ": "Минск",
"MUC": "Мюнхен", "NBO": "Найроби", "NJC": "Нижневартовск",
"NNM": "Нарьян-Мар", "NQZ": "Астана", "NSK": "Норильск", "NVR": "Набережные Челны",
"NVT": "Новороссийск", "OVB": "Новосибирск", "OMS": "Омск",
"OSL": "Осло", "OSS": "Ош", "OZH": "Ургенч", "PEE": "Пермь",
"PEK": "Пекин", "PKC": "Петропавловск-Камчатский", "PRG": "Прага",
"PSA": "Пиза", "PUY": "Пула", "PUS": "Пусан", "REN": "Оренбург",
"RGK": "Горно-Алтайск", "RIX": "Рига", "ROV": "Ростов-на-Дону",
"RTW": "Саратов", "SAW": "Стамбул (Сабиха)", "SGB": "Балаково",
"SGC": "Сургут", "SIP": "Симферополь", "SKG": "Салоники", "SLY": "Салехард",
"SIN": "Сингапур", "SJJ": "Сараево", "SKZ": "Сыктывкар",
"SVO": "Шереметьево", "SVX": "Екатеринбург", "SWT": "Стрежевой",
"SYD": "Сидней", "TAS": "Ташкент", "TBS": "Тбилиси", "TJM": "Тюмень",
"TKM": "Туркменбаши", "TLL": "Таллин", "TLS": "Тулуза", "TSE": "Астана",
"TSQ": "Тамбов", "TXL": "Берлин", "ULV": "Ульяновск", "UFA": "Уфа",
"UJD": "Усть-Каменогорск", "VOG": "Волгоград", "VOZ": "Воронеж",
"VNO": "Вильнюс", "VVO": "Владивосток", "VKO": "Внуково", "WAW": "Варшава",
"WLG": "Веллингтон", "XRY": "Херес", "YKS": "Якутск", "YYZ": "Торонто",
"ZIA": "Жуковский", "ZRH": "Цюрих", "ZYR": "Зырянка",
}
def _city(iata: str) -> str:
"""IATA code → human-readable city name."""
return IATA_CITY.get(iata.strip() if iata else "", iata or "")
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [api] %(levelname)s %(message)s",
@@ -439,8 +490,10 @@ def schedule_data():
"airline": r["airline_name"],
"airport": r["airport_iata"],
"direction": r["direction"],
"origin": r["origin_iata"],
"destination": r["destination_iata"],
"origin": _city(r["origin_iata"]) or r["origin_iata"] or "",
"destination": _city(r["destination_iata"]) or r["destination_iata"] or "",
"origin_iata": r["origin_iata"] or "",
"destination_iata": r["destination_iata"] or "",
"scheduled_at": sched.isoformat() if sched else None,
"actual_at": actual.isoformat() if actual else None,
"delay_min": delay_min,
@@ -494,8 +547,8 @@ def schedule_export():
r["airline_name"] or "",
r["airport_iata"],
r["direction"],
r["origin_iata"] or "",
r["destination_iata"] or "",
_city(r["origin_iata"]) or r["origin_iata"] or "",
_city(r["destination_iata"]) or r["destination_iata"] or "",
sched.isoformat() if sched else "",
actual.isoformat() if actual else "",
delay,

View File

@@ -184,10 +184,20 @@ function exportCsv() {
function routeStr(f) {
const o = f.origin || "";
const d = f.destination || "";
if (!o && !d) return "";
if (!o) return `${d}`;
if (!d) return `${o}`;
return `${o}${d}`;
const oi = f.origin_iata || "";
const di = f.destination_iata || "";
function fmt(city, iata) {
if (!city && !iata) return "";
if (!city) return iata;
if (city === iata) return city;
return city;
}
const from = fmt(o, oi);
const to = fmt(d, di);
if (!from && !to) return "—";
if (!from) return `${to}`;
if (!to) return `${from}`;
return `${from}${to}`;
}
function statusBadge(status) {