/
Ponpon1228
/
Project
Обзор
Документация
Войти
/
Ponpon1228
/
Project
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
server/server.js
133 строки
4 KB
xomimishka
Initial commit
24 ноя 2025, 15:54
24 ноя 2025, 15:54
d23c86f
Код
Авторство
О чём код?
require("dotenv").config(); const express = require("express"); const cors = require("cors"); const axios = require("axios"); const pool = require("./db"); const app = express(); app.use(cors()); app.use(express.json()); function normalizeWeatherDesc(code) { if ([113].includes(code)) return "Clear"; if ([116, 119, 122].includes(code)) return "Clouds"; if ([176, 293, 296, 299, 302, 308, 353, 356, 359].includes(code)) return "Rain"; if ([311, 314].includes(code)) return "Drizzle"; if ([386, 389].includes(code)) return "Thunderstorm"; if ([323, 326, 329, 332, 335, 368, 371, 374, 377].includes(code)) return "Snow"; if ([143, 248, 260].includes(code)) return "Mist"; return "Clear"; } app.get("/find-city", async (req, res) => { const { name } = req.query; if (!name || !name.trim()) return res.status(400).json({ error: "Не указано название" }); const qName = name.trim(); try { const dbRes = await pool.query( `SELECT * FROM cities WHERE name ILIKE $1 OR name ILIKE $2`, [qName, `%${qName}%`] ); if (dbRes.rows.length === 1) { return res.json({ status: "single", city: dbRes.rows[0] }); } if (dbRes.rows.length > 1) { return res.json({ status: "multiple", cities: dbRes.rows }); } const api = await axios.get("https://api.weatherapi.com/v1/search.json", { params: { key: process.env.WEATHERAPI_KEY, q: qName, } }); if (!Array.isArray(api.data) || api.data.length === 0) { return res.json({ status: "not_found", candidates: [] }); } const candidates = api.data.map(c => ({ name: c.name, country: c.country, lat: c.lat, lon: c.lon })); return res.json({ status: "not_found", candidates }); } catch (err) { console.error("FIND CITY ERROR:", err.response?.data || err.message || err); return res.status(500).json({ error: "Ошибка поиска города" }); } }); app.post("/add-city", async (req, res) => { const { name, country, lat, lon } = req.body; if (!name || !country || typeof lat !== "number" || typeof lon !== "number") { return res.status(400).json({ error: "Нужно name,country,lat,lon" }); } try { const insert = await pool.query( `INSERT INTO cities(name, country, lat, lon) VALUES($1,$2,$3,$4) ON CONFLICT (name, country) DO UPDATE SET lat = EXCLUDED.lat, lon = EXCLUDED.lon RETURNING *`, [name, country, lat, lon] ); return res.json(insert.rows[0]); } catch (err) { console.error("ADD CITY ERROR:", err.response?.data || err.message || err); return res.status(500).json({ error: "Ошибка добавления города" }); } }); app.get("/forecast", async (req, res) => { const { id } = req.query; if (!id) return res.status(400).json({ error: "ID не указан" }); try { const cityRes = await pool.query("SELECT * FROM cities WHERE id=$1", [id]); if (!cityRes.rows.length) return res.status(404).json({ error: "Город не найден" }); const city = cityRes.rows[0]; const api = await axios.get("https://api.weatherapi.com/v1/current.json", { params: { key: process.env.WEATHERAPI_KEY, q: `${city.lat},${city.lon}`, lang: "ru" } }); const data = api.data; const forecast = { temperature: data.current.temp_c, feels_like: data.current.feelslike_c, humidity: data.current.humidity, wind_speed: data.current.wind_kph / 3.6, wind_dir: data.current.wind_dir, cloud: data.current.cloud, visibility: data.current.vis_km, description: normalizeWeatherDesc(data.current.condition.code), condition_text: data.current.condition.text, icon: data.current.condition.icon, pressure: data.current.pressure_mb, precip: data.current.precip_mm, uv: data.current.uv, gust_speed: data.current.gust_kph / 3.6 }; return res.json({ city, forecast }); } catch (err) { console.error("FORECAST ERROR:", err.response?.data || err.message || err); return res.status(500).json({ error: "Ошибка получения погоды" }); } }); const PORT = process.env.PORT || 5000; app.listen(PORT, () => console.log(`✔ Server running on port ${PORT}`));