From f3245ed217bb82e29f46a558f765b8366142360d Mon Sep 17 00:00:00 2001 From: Tien Suwandy Date: Fri, 15 Dec 2017 01:08:24 -0800 Subject: [PATCH] updated card --- WeatherBot/Controllers/MessagesController.cs | 9 ++- WeatherBot/Weather.cs | 26 +++---- WeatherBot/WeatherView.cs | 71 +++++++++++++++++--- 3 files changed, 83 insertions(+), 23 deletions(-) diff --git a/WeatherBot/Controllers/MessagesController.cs b/WeatherBot/Controllers/MessagesController.cs index e1899e1..5a90382 100644 --- a/WeatherBot/Controllers/MessagesController.cs +++ b/WeatherBot/Controllers/MessagesController.cs @@ -6,6 +6,7 @@ using Microsoft.Bot.Builder.Storage; using Microsoft.Bot.Connector; using Microsoft.Extensions.Configuration; +using System.Linq; namespace WeatherBot.Controllers { @@ -39,12 +40,10 @@ public MessagesController(IConfiguration configuration) { if (text.Contains("current")) { - context.Reply(await Weather.GetCurrentWeatherByCityName(city)); context.ReplyWith(WeatherView.CURRENT, city); } else { - context.Reply(await Weather.GetWeatherForecastByCityName(city)); context.ReplyWith(WeatherView.FORECAST, city); } } @@ -55,7 +54,11 @@ public MessagesController(IConfiguration configuration) } else { - context.Reply("Type city name to get weather"); + var activity = context.Request.AsConversationUpdateActivity(); + if (activity.MembersAdded.Where(m => m.Id == activity.Recipient.Id).Any()) + { + context.Reply("Hello, type something like 'forecast for seattle'"); + } } }); } diff --git a/WeatherBot/Weather.cs b/WeatherBot/Weather.cs index 535b87d..0cba785 100644 --- a/WeatherBot/Weather.cs +++ b/WeatherBot/Weather.cs @@ -6,18 +6,20 @@ namespace WeatherBot { public static class Weather { - const string WeatherApiBaseUrl = "http://api.openweathermap.org/data/2.5/{0}?q={1}&units=imperial&APPID=a0f75f6b2f7ce29295822d2862df66a6{2}"; - const string CurrentWeather = "weather"; - const string Forecast = "forecast/daily"; - const string CityNameParam = "q"; - const string NumForecastDaysParam = "&cnt=3"; + const string CurrentConditionApiUrl = "https://query.yahooapis.com/v1/public/yql?q=select%20item.condition%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22{0}%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys"; + const string ForecastApiUrl = "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22{0}%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys"; - static HttpClient client = new HttpClient(); + static string[] Cardinals = { "N", "NE", "E", "SE", "S", "SW", "W", "NW", "N" }; - public static async Task GetCurrentWeatherByCityName(string cityName) + public static string DegreesToCardinal(double degrees) { - HttpResponseMessage response = await client.GetAsync( - String.Format(WeatherApiBaseUrl, CurrentWeather, cityName, String.Empty)); + return Cardinals[(int)Math.Round(((double)degrees % 360) / 45)]; + } + + public static async Task GetCurrentWeatherByCityNameAsync(string cityName) + { + HttpClient httpClient = new HttpClient(); + HttpResponseMessage response = await httpClient.GetAsync(String.Format(ForecastApiUrl, cityName)); if (response.IsSuccessStatusCode) { string jsonResponse = await response.Content.ReadAsStringAsync(); @@ -29,10 +31,10 @@ public static async Task GetCurrentWeatherByCityName(string cityName) } } - public static async Task GetWeatherForecastByCityName(string cityName) + public static async Task GetWeatherForecastByCityNameAsync(string cityName) { - HttpResponseMessage response = await client.GetAsync( - String.Format(WeatherApiBaseUrl, Forecast, cityName, NumForecastDaysParam)); + HttpClient httpClient = new HttpClient(); + HttpResponseMessage response = await httpClient.GetAsync(String.Format(ForecastApiUrl, cityName)); if (response.IsSuccessStatusCode) { string jsonResponse = await response.Content.ReadAsStringAsync(); diff --git a/WeatherBot/WeatherView.cs b/WeatherBot/WeatherView.cs index e7510a5..5308763 100644 --- a/WeatherBot/WeatherView.cs +++ b/WeatherBot/WeatherView.cs @@ -5,6 +5,7 @@ using Newtonsoft.Json; using System; using System.Collections.Generic; +using System.Threading.Tasks; namespace WeatherBot { @@ -19,7 +20,7 @@ public class WeatherView : TemplateRendererMiddleware // Default templates ["default"] = new TemplateIdMap { - { CURRENT, (context, city) => GetWeatherCard(context, city, false) }, + { CURRENT, (context, city) => GetWeatherCard(context, city, false) }, { FORECAST, (context, city) => GetWeatherCard(context, city, true) }, } }; @@ -102,12 +103,6 @@ public class WeatherView : TemplateRendererMiddleware ""type"": ""TextBlock"", ""weight"": ""bolder"" }, - { - ""isSubtle"": true, - ""width"": ""small"", - ""text"": ""60% chance of rain"", - ""type"": ""TextBlock"" - }, { ""isSubtle"": true, ""width"": ""small"", @@ -336,11 +331,48 @@ public WeatherView() : base(new DictionaryRenderer(Templates)) { } + public static string GetWeatherImage(bool useSmallImage, string weatherText) + { + Dictionary lookup = useSmallImage ? SmallWeatherImages : LargeWeatherImages; + weatherText = weatherText.ToLowerInvariant(); + if (weatherText.Contains("cloudy")) + { + return lookup["Cloudy"]; + } + else if (weatherText.Contains("rain") || + weatherText.Contains("showers") || + weatherText.Contains("thunderstorms")) + { + return lookup["Rain"]; + } + else if (weatherText.Contains("snow")) + { + return lookup["Snow"]; + } + else + { + return lookup["Sunny"]; + } + } + public static IMessageActivity GetWeatherCard(BotContext context, string city, bool isForecast) + { + return Task.Run(() => GetWeatherCardAsync(context, city, isForecast)).Result; + } + + public static async Task GetWeatherCardAsync(BotContext context, string city, bool isForecast) { IMessageActivity activity = context.Request.CreateReply(); AdaptiveCard card = JsonConvert.DeserializeObject(isForecast ? TemplateForecast : TemplateCurrent); DateTime now = DateTime.Now; + string weatherJson = await Weather.GetWeatherForecastByCityNameAsync(city); + dynamic weatherInfo = !String.IsNullOrWhiteSpace(weatherJson) ? JsonConvert.DeserializeObject(weatherJson) : null; + + if (weatherInfo == null) + { + activity.Text = $"Could not get weather information for {city}"; + return activity; + } // update header TextBlock dateHeader = (TextBlock)(((ColumnSet)card.Body[0]).Columns[0].Items[0]); @@ -351,7 +383,30 @@ public static IMessageActivity GetWeatherCard(BotContext context, string city, b // update updated time TextBlock updated = (TextBlock)card.Body[card.Body.Count - 1]; - updated.Text = now.ToShortTimeString(); + updated.Text = $"Updated {now.ToShortTimeString()}"; + + weatherInfo = weatherInfo.query.results.channel; + dynamic wind = weatherInfo.wind; + string cardinalDirection = Weather.DegreesToCardinal(double.Parse(wind.direction.ToString())); + + // update wind + TextBlock windInfo = (TextBlock)card.Body[3]; + windInfo.Text = $"Winds {wind.speed} mph {cardinalDirection}"; + + dynamic currentCondition = weatherInfo.item.condition; + + // update weather condition text and image + TextBlock conditionSummary = (TextBlock)card.Body[2]; + conditionSummary.Text = currentCondition.text; + + Image currentWeatherImage = (Image)(((ColumnSet)card.Body[1]).Columns[0].Items[0]); + currentWeatherImage.Url = GetWeatherImage(false, currentCondition.text); + + if (isForecast) + { + dynamic forecast = weatherInfo.item.forecast; + } + activity.Attachments.Add(new Attachment(AdaptiveCard.ContentType, content: card)); return activity; }