Welcome back.
To implement our weather forecast slash
command, we need to be able to make requests from our bot.
We need to integrate with the weather API, which just means using that API to
help us do everything that we need to do in our application.
To implement our weather forecast command, we could take two approaches.
We could take a more top -down approach, starting from the command definition and
the execute function.
Or we could take a more bottom -up
approach, starting from the request to the API and then moving to the command
definition, execution, and testing it with user interactions.
Both of these approaches are correct.
However, since we have the weather API
fresh in our minds, we're going to start there.
From the API request to fetch our weather
forecast data.
From the bottom -up.
In our terminal, we'll start by installing the Axios package, npm install axios.
This is a handy package to help us work with HTTP APIs.
Now, we could use the JavaScript fetch function, which is built into Node, but
Axios is still widely used.
It does things like automatically parsing
JSON, better error handling, and is just overall a bit easier to use.
With Axios installed, let's make a folder in our source folder for all of our requests.
Naturally, we'll call this requests.
And the request that we're working with
is our weather forecast.
So we'll call it forecasts .js.
First things first, we're going to require Axios.
So axios equals require Axios.
And we're going to create an async
function called fetch forecasts.
This is where we're going to make our get
request to the weather API, and we're going to filter out the data that we need
for our Discord bot.
What are the requirements for our function?
Well, at a high level, it needs to take in some location, so that's going to be a
parameter for our function.
And it needs to return the minimum and
maximum temperatures for that location for a specific number of days.
It needs to be able to specify those temperatures in both metric units and imperial.
So in Celsius and in Fahrenheit.
Let's take a look at how we might do this.
If we go to weatherAPI .com, we can go to view the documentation for our API.
And if we scroll down, we can see that this API has a base URL of api
.weatherapi .com slash v1.
So we're using version 1 of this API.
And to get the forecast, we're going to use the flash forecast dot JSON route.
Because we're looking for JSON and not XML, which is the alternative data format.
And the way we specify our location, scrolling down, is through these request parameters.
So our API has two required parameters.
The key, which is the API key, and this Q
value, which is a query parameter for the location.
This can be just a city name.
It can be latitude and longitude, a zip code.
Again, many different formats are accepted.
And if we wanted to, there's a number of different parameters we could pass in.
So days for the forecast is also required.
The API needs to know how much data to
return, how many days worth of data.
And there's several different options
here for air quality information, tide data, language.
But for now, we're ready to start.
We're going to copy this base URL that we found.
And we're going to make a request to that using Axios.
So we're going to say Axios, which is an asynchronous function, so we're going to
await it.
And we're going to pass in this object
where we can specify the URL.
So the URL is going to start with our
base that we just copied, followed by slash forecast dot JSON.
This is going to be a get request.
So we specify the method is get.
And then we can specify the params, which we just saw include q for the location.
And that's going to come through as an argument to our function here.
So we can pass that in right away.
For the forecast, we need a specific
amount of days to forecast.
So that's going to be this days parameter.
Depending on if we're using the free tier or the free trial or one of the paid
options, we can change this value.
But we'll start with, say, three days.
And finally, we need to pass in the API key under this key parameter.
We're going to get this value like anything else populated by the dot env package.
So it's populated on the process dot env object.
And we called it the weather API key.
Finally, the fourth option that we're going to pass into Axios underneath
params is going to be the response type.
We want our response to come back as JSON.
Now let's clean this up a little bit and take these constants like this URL.
And for now, we're just going to save them outside of this function.
So we're going to say const URL equals our weather API URL.
Passing that into our Axios function.
And we're going to do the same for the
amount of days.
We'll call this forecast days.
And we'll set that underneath our URL.
That's a good start.
Now what does our Axios function here return?
It returns a promise that resolves to the
response data.
So inside of a dot then function that we
chain on this promise, we get access to that returned response.
So we can say response and use an arrow function here.
Inside of which we now have access to the response data.
The best way to figure out what this response looks like is to either make the
request and log it.
Or we can go into our API Explorer here
and explore the response here.
So scrolling down, we can see that the
response body to a forecast request includes this location object. Which has
a name, a region, and a country.
This is useful for knowing that the API
understood the location that we're asking for.
And it's also useful for disambiguating,
for differentiating between say London in Canada and London in the United Kingdom.
So we want to include some of this data in our Discord bot.
Then we get this current weather data here. Which we're not really interested
in right now.
We're more interested in the forecast.
So below location we have a forecast object. Which includes this forecast day property.
That contains an array of days.
Each with a date.
And then a day object.
And each day contains a maximum
temperature and a minimum temperature in both Celsius and Fahrenheit.
These are the values we're going to use for our bot.
So going back into our code, let's take these values from the response.
Let's start with the location.
We're going to use the city and the country.
So we're going to say const city equals response .data .location.
So response .data is the object that's returned by the API.
And then we're using the location object.
Which had a name property for the city
name of the location.
For country we'll do the same thing.
Const country equals response .data .location .country.
We'll put these two values together using a template string.
So we're going to say const location name.
The location that we display in our
Discord command.
Is going to include both the city.
Followed by the country.
So let's use a comma and say country.
If we wanted to be even more exact.
We could add the region here as well.
So for example in the United States the region might be the state.
Now what about the weather data?
We're going to create a constant called
weather data.
Where we take response .data .forecast.
And here we had that nested forecast day array.
So what we want to do is we want to take
specific values from each forecast day.
So that our function here fetch forecast
returns only the data required by our bot.
One way we can do this is by mapping over
the forecast day array. And returning specific properties from it.
So we're going to say dot map.
And we're going to take each forecast day.
In this arrow function here.
Where for each forecast day.
We're going to return some properties from that forecast day.
So we're interested in the date of each day in our forecast.
So we can label our data.
That's going to come from forecast day
dot date.
And this should be a comma.
If we go into our API Explorer.
We can see that this is the date from
this forecast day array here.
Now for the temperature we're going to
return these four values.
So we can pick out the appropriate ones.
Based on what the user is asking for.
Do they want the temperature in Celsius
or do they want it in Fahrenheit?
So we're going to say temperature minimum
in Celsius.
Is going to be forecast day dot day.
Dot min temp underscore C.
And then let's copy paste this.
And get the maximum temperature.
So that's going to be temperature max C.
And then we're going to get max temp here from the forecast day.
And then we're going to do the same thing for Fahrenheit.
So let's copy that.
And just change this C to an F. Now our
weather data object.
Actually it's not an object.
It's going to be an array.
That's populated with these objects.
That include the date and min and max temperature for each date.
All right.
So to wrap up.
We're going to take the weather data and the location name from the response here.
From the function that's working with the response.
And we're going to return that.
We're going to say return an object.
That contains the location name.
As well as weather data.
There we have it.
All the data that we need for our bot's forecast slash command.
Before we wrap up.
We're working with the internet.
We're working with HTTP requests.
So we should catch any errors that come
back from Axios.
Which we can do using the dot catch
function on this promise chain.
So below dot then.
We're going to add a dot catch.
And this is going to accept some error object.
Inside of an arrow function.
Which we're just going to console dot error.
That error.
Looking good.
Now the only thing missing is to export our function.
So module dot exports.
Equals.
Fetch forecast.
Right now.
Because we're working from the bottom up.
We don't have any way of testing this
fetch forecast function.
I'm sure I've made a mistake somewhere.
At least one typo somewhere.
So what we can do for now.
Just to give us a little bit of extra confidence in our code.
Is to run our fetch forecast function.
Say when our client is ready.
And we're logged in.
We're going to do this temporarily as
just a quick test.
So let's import our requests file.
We're going to say.
Const fetch forecast.
Equals require.
And in this case we need to go up out of
the events folder. And into requests.
Slash forecast.
And we're just going to try to quickly.
Console dot log.
The result of fetch forecast.
On some location.
Say Cairo in Egypt.
And because our fetch forecast function is.
Asynchronous.
We're going to need to await the result
of that function.
But first.
Right now we're calling this axios promise.
And we're awaiting the result.
But our fetch forecast function.
Isn't returning anything.
So we need to return.
Await axios.
And hopefully the data logged from this fetch forecast function.
Will include the location name and weather data.
For Cairo.
So again because our function is asynchronous.
We're going to need to await it.
When we're logging it here.
So in our client ready test.
We're going to say await.
Fetch forecast.
Let's see if our quick little test here works.
We're going to run npm run dev.
Our bot is logged in.
And we're getting some kind of result being logged.
Check this out.
Location name Cairo Egypt.
Weather data.
Is an array that includes dates.
And min and max temperatures.
In both Fahrenheit and Celsius.
Very very nice.
Before we go.
Let's make one quick little improvement.
In forecast .js.
Right now we're using the HTTP URL.
For our end point.
Let's make this a little bit more secure.
By using HTTPS.
Rather than plain old .
Insecure unencrypted HTTP.
And if we save that file.
Let's go back into the terminal.
And see if our result is still being logged.
I'm going to scroll down to the bottom.
And things are looking good.
This was a bit of a long video.
But we did a lot of heavy lifting.
In the next one.
Let's make use of our forecast data.
In an actual slash command.
We're getting close to the finish line.
So I'll see you there.