From 2851ebce3ce578b79daae1f23ce95bf7553cd96c Mon Sep 17 00:00:00 2001 From: DaviDev <97841570+DaviisDev@users.noreply.github.com> Date: Sun, 8 Sep 2024 18:30:56 -0300 Subject: [PATCH] feat: Add weather command using weather.com API (#10) * Update gsmarena.js * feat: Add weather command using weather.com API This commit introduces a new command that allows users to check the weather forecast. The command retrieves weather data from the weather.com API and provides relevant information to users. # Command: /weather Example usage: /weather New York Technical details: Implementation of the weather command using the weather.com API in English. --- commands/gsmarena.js | 1 - commands/weather.js | 107 ++++++++++++++++++++++++++++++++++++++++ locales/english.json | 6 ++- locales/portuguese.json | 7 ++- 4 files changed, 118 insertions(+), 3 deletions(-) create mode 100644 commands/weather.js diff --git a/commands/gsmarena.js b/commands/gsmarena.js index 28aa475..e3ff415 100644 --- a/commands/gsmarena.js +++ b/commands/gsmarena.js @@ -109,7 +109,6 @@ function formatPhone(phone) { .filter(([_, key]) => formattedPhone[key]) .map(([label, key]) => `${label}: ${formattedPhone[key]}`) .join("\n\n"); - const deviceUrl = `GSMArena page: ${formattedPhone.url}`; const deviceImage = phone.picture ? `Device Image: ${phone.picture}` : ''; diff --git a/commands/weather.js b/commands/weather.js new file mode 100644 index 0000000..c68b44e --- /dev/null +++ b/commands/weather.js @@ -0,0 +1,107 @@ +// Ported and improved from BubbalooTeam's PyCoala bot +// Copyright (c) 2024 BubbalooTeam. (https://github.com/BubbalooTeam) + +const axios = require('axios'); +const Config = require('../props/config.json'); +const { getStrings } = require('../plugins/checklang.js'); +const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js'); +const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch); + +const statusEmojis = { + 0: '⛈', 1: '⛈', 2: '⛈', 3: '⛈', 4: '⛈', 5: '🌨', 6: '🌨', 7: '🌨', + 8: '🌨', 9: '🌨', 10: '🌨', 11: '🌧', 12: '🌧', 13: '🌨', 14: '🌨', + 15: '🌨', 16: '🌨', 17: '⛈', 18: '🌧', 19: '🌫', 20: '🌫', 21: '🌫', + 22: '🌫', 23: '🌬', 24: '🌬', 25: '🌨', 26: '☁️', 27: '🌥', 28: '🌥', + 29: '⛅️', 30: '⛅️', 31: '🌙', 32: '☀️', 33: '🌤', 34: '🌤', 35: '⛈', + 36: '🔥', 37: '🌩', 38: '🌩', 39: '🌧', 40: '🌧', 41: '❄️', 42: '❄️', + 43: '❄️', 44: 'n/a', 45: '🌧', 46: '🌨', 47: '🌩', +}; + +const getStatusEmoji = (statusCode) => statusEmojis[statusCode] || 'n/a'; + +function getLocaleUnit(userLang) { + const fahrenheitCountries = ['US', 'BS', 'BZ', 'KY', 'LR']; + const languagePrefix = userLang.split('-')[0]; + const countryCode = userLang.split('-')[1]; + + if (languagePrefix === 'en' || (countryCode && fahrenheitCountries.includes(countryCode))) { + return { temperatureUnit: 'F', speedUnit: 'mph', apiUnit: 'e' }; + } else { + return { temperatureUnit: 'C', speedUnit: 'km/h', apiUnit: 'm' }; + } +} + +module.exports = (bot) => { + bot.command(['clima', 'weather'], spamwatchMiddleware, async (ctx) => { + const userLang = ctx.from.language_code || "en-US"; + const Strings = getStrings(userLang); + const args = ctx.message.text; + + if (args.length < 9) { + return ctx.reply(Strings.provideLocation, { + parse_mode: "Markdown", + reply_to_message_id: ctx.message.message_id + }); + } + + const location = args.slice(9).trim(); + const apiKey = Config.weatherKey; + + try { + const locationResponse = await axios.get('https://api.weather.com/v3/location/search', { + params: { + apiKey: apiKey, + format: 'json', + language: userLang, + query: location, + }, + }); + + const locationData = locationResponse.data.location; + if (!locationData || !locationData.address) { + return ctx.reply(Strings.invalidLocation, { + parse_mode: "Markdown", + reply_to_message_id: ctx.message.message_id + }); + } + + const addressFirst = locationData.address[0]; + const latFirst = locationData.latitude[0]; + const lonFirst = locationData.longitude[0]; + const { temperatureUnit, speedUnit, apiUnit } = getLocaleUnit(userLang); + + const weatherResponse = await axios.get('https://api.weather.com/v3/aggcommon/v3-wx-observations-current', { + params: { + apiKey: apiKey, + format: 'json', + language: userLang, + geocode: `${latFirst},${lonFirst}`, + units: apiUnit, + }, + }); + + const weatherData = weatherResponse.data['v3-wx-observations-current']; + const { temperature, temperatureFeelsLike, relativeHumidity, windSpeed, iconCode, wxPhraseLong } = weatherData; + + const weatherMessage = Strings.weatherStatus + .replace('{addressFirst}', addressFirst) + .replace('{getStatusEmoji(iconCode)}', getStatusEmoji(iconCode)) + .replace('{wxPhraseLong}', wxPhraseLong) + .replace('{temperature}', temperature) + .replace('{temperatureFeelsLike}', temperatureFeelsLike) + .replace('{temperatureUnit}', temperatureUnit) + .replace('{temperatureUnit2}', temperatureUnit) + .replace('{relativeHumidity}', relativeHumidity) + .replace('{windSpeed}', windSpeed) + .replace('{speedUnit}', speedUnit); + + ctx.reply(weatherMessage, { parse_mode: 'Markdown' }); + } catch (error) { + const message = Strings.weatherErr.replace('{error}', error.message); + ctx.reply(message, { + parse_mode: "Markdown", + reply_to_message_id: ctx.message.message_id + }); + } + }); +}; \ No newline at end of file diff --git a/locales/english.json b/locales/english.json index b17998d..eeb41ff 100644 --- a/locales/english.json +++ b/locales/english.json @@ -37,5 +37,9 @@ "lastFmStatusFor": "*Last.fm status for user* {lastfmUser}*:*\n\n*{nowPlaying}*: {trackName} by {artistName} \n\n*Number of plays*: {plays}", "lastFmErr": "*Error retrieving data for Last.fm user* {lastfmUser}.", "currentCommit": "*Current commit:* `{commitHash}`", - "errorRetrievingCommit": "*Error retrieving commit:* {error}" + "errorRetrievingCommit": "*Error retrieving commit:* {error}", + "provideLocation": "*Please provide a valid location.*", + "invalidLocation": "*Invalid location. Try again.*", + "weatherStatus": "*Weather in {addressFirst}:*\n\n*Status:* `{getStatusEmoji(iconCode)} {wxPhraseLong}`\n*Temperature:* `{temperature} °{temperatureUnit}`\n*Feels like:* `{temperatureFeelsLike} °{temperatureUnit2}`\n*Humidity:* `{relativeHumidity}%`\n*Wind speed:* `{windSpeed} {speedUnit}`", + "weatherErr": "*An error occurred while retrieving the weather. Please try again later.*\n\n`{error}`" } diff --git a/locales/portuguese.json b/locales/portuguese.json index ee5d4b6..2b3a737 100644 --- a/locales/portuguese.json +++ b/locales/portuguese.json @@ -37,5 +37,10 @@ "lastFmStatusFor": "*Status do Last.fm para o usuário* {lastfmUser}*:*\n\n*{nowPlaying}*: {trackName} por {artistName}\n\n*Numero de plays*: {plays}", "lastFmErr": "*Erro ao recuperar dados para o usuário do Last.fm* {lastfmUser}.", "currentCommit": "*Commit atual:* `{commitHash}`", - "errorRetrievingCommit": "*Erro ao obter o commit:* {error}" + "errorRetrievingCommit": "*Erro ao obter o commit:* {error}", + "provideLocation": "*Por favor, forneça uma localização válida.*", + "invalidLocation": "*Localização inválida. Tente novamente.*", + "weatherStatus": "*Clima em {addressFirst}:*\n\n*Estado:* `{getStatusEmoji(iconCode)} {wxPhraseLong}`\n*Temperatura:* `{temperature} °{temperatureUnit}`\n*Sensação térmica:* `{temperatureFeelsLike} °{temperatureUnit2}`\n*Umidade:* `{relativeHumidity}%`\n*Velocidade do vento:* `{windSpeed} {speedUnit}`", + "weatherErr": "*Ocorreu um erro ao obter o clima. Tente novamente mais tarde.*\n\n`{error}`" + }