updated weather alerts

This commit is contained in:
Alexander Karpov 2023-05-28 13:42:20 +03:00
parent dff6a050ea
commit 097c39b494
7 changed files with 111 additions and 16 deletions

View File

@ -8,3 +8,4 @@ orconfig
.readthedocs.yml
.travis.yml
venv
data

View File

@ -172,7 +172,7 @@ class InputRouteSerializer(serializers.Serializer):
class ListUserRouteSerializer(serializers.ModelSerializer):
class Meta:
model = UserRoute
fields = ["id", "created"]
fields = ["id", "name", "description", "created"]
class UserRouteDateSerializer(serializers.ModelSerializer):

View File

@ -0,0 +1,25 @@
# Generated by Django 4.2.1 on 2023-05-28 10:08
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("events", "0027_city_temperature_city_weather_condition"),
]
operations = [
migrations.AddField(
model_name="userroute",
name="description",
field=models.TextField(default="описание"),
preserve_default=False,
),
migrations.AddField(
model_name="userroute",
name="title",
field=models.CharField(default="маршрут", max_length=250),
preserve_default=False,
),
]

View File

@ -238,6 +238,8 @@ class RestaurantType(models.TextChoices):
class UserRoute(models.Model):
title = models.CharField(max_length=250)
description = models.TextField()
user = models.ForeignKey(
"users.User", related_name="routes", on_delete=models.CASCADE
)

View File

@ -5,15 +5,17 @@
api_url = "https://api.weather.yandex.ru/v2/forecast"
def get_position_weather(lat: float, lon: float) -> (int, str):
url = api_url + f"?lat={lat}&lon={lon}&lang=ru_RU&limit=1&hours=false"
def get_position_weather(lat: float, lon: float) -> list[(str, str)]:
url = api_url + f"?lat={lat}&lon={lon}&lang=ru_RU&limit=3&hours=false"
response = requests.get(
url=url, headers={"X-Yandex-API-Key": settings.YANDEX_TOKEN}
)
temp_feels = 20
weather = "clear"
if response.status_code == 200:
data = response.json()
temp_feels = data["forecasts"][0]["parts"]["day"]["feels_like"]
weather = data["forecasts"][0]["parts"]["day_short"]["condition"]
return temp_feels, weather
days = []
for d in data["forecasts"]:
days.append((d["date"], d["parts"]["day_short"]["condition"]))
return days
return []

View File

@ -1,15 +1,72 @@
from celery import shared_task
from datetime import timedelta
from passfinder.events.models import City
from celery import shared_task
from django.conf import settings
from django.core.mail import send_mail
from django.template.loader import render_to_string
from django.utils.timezone import now
from django.utils.dateparse import parse_date
from passfinder.events.models import City, UserRoute
from passfinder.events.services import get_position_weather
api_url = "https://api.weather.yandex.ru/v2/forecast"
weathers_labels = {
"drizzle": "морось",
"light-rain": "небольшой дождь",
"rain": "дождь",
"moderate-rain": "дождь",
"heavy-rain": "сильный дождь",
"continuous-heavy-rain": "сильный дождь",
"showers": "ливень",
"wet-snow": "дождь со снегом",
"snow-showers": "снегопад",
"hail": "град",
"thunderstorm": "гроза",
"thunderstorm-with-rain": "дождь с грозой",
"thunderstorm-with-hail": "дождь с грозой",
}
@shared_task
def check_temperature():
for city in City.objects.all():
temperature, weather_condition = get_position_weather(city.lat, city.lon)
city.temperature = temperature
city.weather_condition = weather_condition
city.save()
cities_temp = {}
for route in UserRoute.objects.filter(
dates__date__gte=now().date(), dates__date__lte=now().date() + timedelta(days=3)
):
points = route.dates.objects.get(date=now().date()).points.all()
cities = points.values_list("city_id").distinct()
alerts = []
for city in cities:
if city:
city = City.objects.get(oid=city)
if city in cities_temp:
weather_conditions = cities_temp[city]
else:
weather_conditions = get_position_weather(city.lat, city.lon)
weather_conditions = [
(parse_date(x[0]), x[1]) for x in weather_conditions
]
cities_temp[city] = weather_conditions
for date, weather in weather_conditions:
if weather in weathers_labels:
alerts.append(
f"В городе {city.title} {date.strftime('%d.%m.%Y')} предстоит {weathers_labels[weather]}"
)
if alerts:
context = {
"user": route.user,
"route": route,
"alerts": alerts,
# TODO: change to frontend link
"link": f"http://127.0.0.1:8000/path/{route.id}/change",
}
email_plaintext_message = render_to_string("weather_alert.txt", context)
send_mail(
"Предупреждение о погоде",
email_plaintext_message,
settings.DEFAULT_FROM_EMAIL,
[route.user.email],
)

View File

@ -0,0 +1,8 @@
Доброе утро, {{ user.username }}!
Уведомляем вас, что во время вашей поездки в {{ route.title }} ожидаются осадки:
{% for alert in alerts %}
- {{ alert }}
{% endfor %}
Вы можете изменить маршрут по ссылке: {{ link }}