Skip to content

Commit

Permalink
Use yr.no as weather source
Browse files Browse the repository at this point in the history
  • Loading branch information
Erb3 committed Nov 5, 2023
1 parent e047f47 commit 5c389ed
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 65 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@ env:
UPSTASH_REDIS_REST_URL: ${{secrets.UPSTASH_REDIS_REST_URL}}
UPSTASH_REDIS_REST_TOKEN: ${{secrets.UPSTASH_REDIS_REST_TOKEN}}

# Openweather
OPENWEATHER_API_KEY: ${{secrets.OPENWEATHER_API_KEY}}

jobs:
main:
name: CI
Expand Down
7 changes: 3 additions & 4 deletions src/app/(dashboard)/app/_components/weather.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,9 @@ export const WeatherData: FC = () => {

return (
<span className="text-tiny text-default-500">
You can expect a 👆 high of {weatherData.main.temp_max.toFixed()}º and a
👇 low of {weatherData.main.temp_min.toFixed()}º with{" "}
{getFormattedWeatherDescription(weatherData.weather[0]?.description)}{" "}
today.
You can expect a high of {weatherData.temp_max.toFixed()}º 👆 and a
low of {weatherData.temp_min.toFixed()}º 👇
{getFormattedWeatherDescription(weatherData.summary)} today.
</span>
);
};
2 changes: 0 additions & 2 deletions src/env.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ export const env = createEnv({
UPSTASH_REDIS_REST_URL: z.string().optional(),
UPSTASH_REDIS_REST_TOKEN: z.string().optional(),
CLERK_SECRET_KEY: z.string().min(1),
OPENWEATHER_API_KEY: z.string().min(1),
},
client: {
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: z.string().min(1),
Expand All @@ -26,7 +25,6 @@ export const env = createEnv({
process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY,
UPSTASH_REDIS_REST_TOKEN: process.env.UPSTASH_REDIS_REST_TOKEN,
UPSTASH_REDIS_REST_URL: process.env.UPSTASH_REDIS_REST_URL,
OPENWEATHER_API_KEY: process.env.OPENWEATHER_API_KEY,
},
skipValidation: !!process.env.SKIP_ENV_VALIDATION,
});
62 changes: 50 additions & 12 deletions src/server/api/routers/weather.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
import { TRPCError } from "@trpc/server";
import fetch from "node-fetch";
import { z } from "zod";

import { env } from "@/env.mjs";

import { createTRPCRouter, protectedProcedure } from "../trpc";

type RawWeatherData = {
properties: {
timeseries: {
data: {
next_12_hours: {
summary: {
symbol_code: string;
}
},
instant: {
details: {
air_temperature: number;
}
}
}
}[]
}
}

type WeatherData = {
main: {
temp_max: number;
temp_min: number;
};
weather: {
description: string;
}[];
temp_max: number;
temp_min: number;
summary: string;
};

export const weatherRouter = createTRPCRouter({
Expand All @@ -28,7 +40,12 @@ export const weatherRouter = createTRPCRouter({
const { latitude, longitude } = input;

const response = await fetch(
`https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${env.OPENWEATHER_API_KEY}&units=metric`,
`https://api.met.no/weatherapi/locationforecast/2.0/compact?lat=${latitude}&lon=${longitude}`,
{
headers: {
"User-Agent": `noodle.run (https://github.com/noodle-run/noodle)`
}
}
);

if (!response.ok) {
Expand All @@ -38,6 +55,27 @@ export const weatherRouter = createTRPCRouter({
});
}

return response.json() as Promise<WeatherData>;
const rawWeatherData: RawWeatherData = await response.json() as RawWeatherData;

if (rawWeatherData.properties.timeseries.length < 12) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: "Partial weather data"
})
}

const temperatures = [];

for (const timeseries of rawWeatherData.properties.timeseries) {
temperatures.push(timeseries.data.instant.details.air_temperature);
}

const weatherData: WeatherData = {
summary: rawWeatherData.properties.timeseries[0]!.data.next_12_hours.summary.symbol_code,
temp_max: Math.max(...temperatures),
temp_min: Math.min(...temperatures)
}

return weatherData;
}),
});
90 changes: 46 additions & 44 deletions src/utils/getFormattedWeatherDescription.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,50 @@
const weatherCodeToEnglish: Record<string, string> = {
"clearsky": "a clear sky",
"cloudy": "clouds",
"fair": "fair",
"fog": "fog",
"heavyrain": "heavy rain",
"heavyrainandthunder": "heavy rain and thunder",
"heavyrainshowers": "heavy rain showers",
"heavyrainshowersandthunder": "heavy rain showers and thunder",
"heavysleet": "heavy sleet",
"heavysleetandthunder": "heavy sleet and thunder",
"heavysleetshowers": "heavy sleet showers",
"heavysleetshowersandthunder": "heavy sleet showers and thunder",
"heavysnow": "heavy snow",
"heavysnowandthunder": "heavy snow and thunder",
"heavysnowshowers": "heavy snow showers",
"heavysnowshowersandthunder": "heavy snow showers and thunder",
"lightrain": "light rain",
"lightrainandthunder": "light rain and thunder",
"lightrainshowers": "light rain showers",
"lightrainshowersandthunder": "light rain showers and thunder",
"lightsleet": "light sleet",
"lightsleetandthunder": "light sleet and thunder",
"lightsleetshowers": "light sleet showers",
"lightsnow": "light snow",
"lightsnowandthunder": "light snow and thunder",
"lightsnowshowers": "light snow showers",
"lightssleetshowersandthunder": "light sleet showers and thunder",
"lightssnowshowersandthunder": "light snow showers and thunder",
"partlycloudy": "some clouds",
"rain": "rain",
"rainandthunder": "rain and thunder",
"rainshowers": "rain showers",
"rainshowersandthunder": "rain showers and thunder",
"sleet": "sleet",
"sleetandthunder": "sleet and thunder",
"sleetshowers": "sleet showers",
"sleetshowersandthunder": "sleet showers and thunder",
"snow": "snow",
"snowandthunder": "snow and thunder",
"snowshowers": "snow showers",
"snowshowersandthunder": "snow showers and thunder",
};

export const getFormattedWeatherDescription = (
condition: string | undefined,
) => {
if (!condition) return;

const weatherToEmoji: Record<string, string> = {
"clear sky": "☀️",
"few clouds": "🌤️",
"scattered clouds": "⛅",
"broken clouds": "☁️",
"overcast clouds": "☁️",
rain: "🌧️",
"light rain": "🌧️",
"moderate rain": "🌧️",
"heavy intensity rain": "🌧️",
"very heavy rain": "🌧️",
"extreme rain": "🌧️",
"freezing rain": "🌨️",
"light intensity shower rain": "🌦️",
"shower rain": "🌧️",
"heavy intensity shower rain": "🌧️",
"ragged shower rain": "🌧️",
"light snow": "❄️",
snow: "❄️",
"heavy snow": "❄️",
sleet: "🌨️",
"shower sleet": "🌨️",
"light rain and snow": "🌨️",
"rain and snow": "🌨️",
"light shower snow": "🌨️",
"shower snow": "🌨️",
"heavy shower snow": "🌨️",
mist: "🌫️",
smoke: "🌫️",
haze: "🌫️",
"sand/ dust whirls": "🌪️",
fog: "🌫️",
sand: "🌫️",
dust: "🌫️",
"volcanic ash": "🌫️",
squalls: "🌬️",
tornado: "🌪️",
clear: "☀️",
clouds: "☁️",
};

return `${weatherToEmoji[condition.toLowerCase()] ?? ""} ${condition}`;
if (!condition || !weatherCodeToEnglish[condition]) return;
return `with ${weatherCodeToEnglish[condition]}`;
};

0 comments on commit 5c389ed

Please sign in to comment.