86 lines
3.0 KiB
Python
86 lines
3.0 KiB
Python
"""
|
||
Вспомогательные функции для работы со справочниками стран, городов и часовых поясов.
|
||
|
||
Пока данные хранятся в JSON-файлах внутри приложения users.
|
||
В будущем можно перенести это в модели БД.
|
||
"""
|
||
|
||
import json
|
||
import os
|
||
from functools import lru_cache
|
||
from typing import List, Dict, Any, Optional
|
||
|
||
|
||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||
DATA_DIR = os.path.join(BASE_DIR, "geo_data")
|
||
|
||
|
||
def _load_json(filename: str) -> Any:
|
||
path = os.path.join(DATA_DIR, filename)
|
||
if not os.path.exists(path):
|
||
return []
|
||
with open(path, "r", encoding="utf-8") as f:
|
||
return json.load(f)
|
||
|
||
|
||
@lru_cache(maxsize=1)
|
||
def get_countries() -> List[Dict[str, Any]]:
|
||
"""
|
||
Получить список стран.
|
||
Формат элементов: { "code": "RU", "name": "Россия" }
|
||
"""
|
||
return _load_json("countries.json")
|
||
|
||
|
||
@lru_cache(maxsize=1)
|
||
def get_timezones() -> List[Dict[str, Any]]:
|
||
"""
|
||
Получить список часовых поясов.
|
||
Формат элементов: { "name": "Europe/Moscow", "offset": "+03:00" }
|
||
"""
|
||
return _load_json("timezones.json")
|
||
|
||
|
||
@lru_cache(maxsize=None)
|
||
def get_cities_for_country(country_code: str) -> List[Dict[str, Any]]:
|
||
"""
|
||
Получить список городов для заданной страны.
|
||
Пока реализовано только для России (RU).
|
||
Формат элементов: { "country_code": "RU", "country_name": "Россия", "city": "Москва", "timezone": "Europe/Moscow" }
|
||
"""
|
||
code = country_code.upper()
|
||
if code == "RU":
|
||
return _load_json("cities_ru.json")
|
||
# Для других стран можно добавить отдельные файлы и условия
|
||
return []
|
||
|
||
|
||
def search_cities(country: Optional[str] = None, query: Optional[str] = None) -> List[Dict[str, Any]]:
|
||
"""
|
||
Поиск городов по стране и части названия.
|
||
"""
|
||
cities: List[Dict[str, Any]] = []
|
||
|
||
if country:
|
||
# Предполагаем, что приходит код страны (RU) или название
|
||
code = country.upper()
|
||
if len(code) == 2:
|
||
cities = get_cities_for_country(code)
|
||
else:
|
||
# Ищем по названию страны в списке стран и берём по коду
|
||
for c in get_countries():
|
||
if c.get("name", "").lower().startswith(country.lower()):
|
||
cities = get_cities_for_country(c.get("code", ""))
|
||
break
|
||
else:
|
||
# Если страна не указана, возвращаем только базовый список популярных городов России
|
||
cities = get_cities_for_country("RU")
|
||
|
||
if query:
|
||
q = query.lower()
|
||
cities = [c for c in cities if q in c.get("city", "").lower()]
|
||
|
||
return cities
|
||
|
||
|