Skip to content
This repository was archived by the owner on Jun 30, 2022. It is now read-only.

Commit cdd7f65

Browse files
authored
News skill: adding trending articles, favorite topics, searching by market, searching by website (#1660)
* Added trending articles, changing search market, search specific sites, choosing favorite topics * Changes from comments * fis newsLuis
1 parent 69efd7b commit cdd7f65

File tree

22 files changed

+660
-54
lines changed

22 files changed

+660
-54
lines changed

skills/src/csharp/experimental/newsskill/Deployment/Resources/LU/en/news.lu

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,84 @@
1919
- find me news on {topic}
2020
- find news on {topic}
2121
- news about {topic}
22+
- news about {topic=microsoft} on {site=wsj.com}
23+
- whats the latest news on {site=nytimes.com}
24+
- news on {site=cnn.com}
25+
- latest news on {site}
26+
- find me news about {topic} on {site}
27+
- find me news on {topic} on {site}
28+
- whats the news on {site=cnn.com}
29+
- find news on {topic=technology} on {site=wsj.com}
30+
- whats the latest on {topic} on {site}
31+
- find me news from {site}
32+
- find me news about {topic} from {site}
33+
- {topic} news from {site}
34+
- {topic} news on {site}
35+
36+
## TrendingArticles
37+
- what's trending now
38+
- what's the latest trending news
39+
- find trending news
40+
- what's the top news on social media
41+
- trending news
42+
- top news on social media
43+
- what news is popular right now
44+
- popular news
45+
- find trending articles
46+
- trending articles
47+
- news trending on social media
48+
- articles popular on social media
49+
- news trending now
50+
- find news trending on social networks
51+
- news popular on social networks
52+
- articles trending now
53+
54+
## SetFavoriteTopics
55+
- set favorite news topics
56+
- set favorite news categories
57+
- choose favorite news topics
58+
- choose favorite news categories
59+
- set news topics
60+
- set news categories
61+
- set favorites
62+
- choose favorites
63+
- choose my topics
64+
- set my topics
65+
- set news I'm interested in
66+
- choose topics I'm interested in
67+
68+
## ShowFavoriteTopics
69+
- favorite news
70+
- favorite news topics
71+
- my news categories
72+
- my news topics
73+
- my news interests
74+
- news I'm interested in
75+
- what's my favorite news
76+
- topics I'm interested in
77+
- my news
78+
- my favorite news
79+
- news for me
80+
- my news suggestions
81+
- news topics for me
82+
- what are my favorites
83+
- what are my favorite topics
84+
- find favorites
85+
- find favorite news
86+
- find favorite topics
2287

2388
## None
89+
- 1
90+
- 2
91+
- forward email
92+
- find point of interest
93+
- get directions
94+
- add to my to do list
95+
- how long do I have until my next calendar appointment
96+
- hello world
97+
- what's the weather today
2498

2599
> # Entity definitions
26100

27-
$topic:simple
101+
$topic:simple
102+
$site:simple

skills/src/csharp/experimental/newsskill/Deployment/Resources/template.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@
7070
"bingServiceName": {
7171
"type": "string",
7272
"defaultValue": "[concat(parameters('name'), '-bing')]"
73+
},
74+
"azureMapsServiceName": {
75+
"type": "string",
76+
"defaultValue": "[concat(parameters('name'), '-maps')]"
7377
}
7478
},
7579
"variables": {
@@ -202,6 +206,16 @@
202206
"sku": {
203207
"name": "S1"
204208
}
209+
},
210+
{
211+
"type": "Microsoft.Maps/accounts",
212+
"apiVersion": "2018-05-01",
213+
"name": "[parameters('azureMapsServiceName')]",
214+
"location": "global",
215+
"sku": {
216+
"name": "s1",
217+
"tier": "Standard"
218+
}
205219
}
206220
],
207221
"outputs": {
@@ -236,6 +250,10 @@
236250
"bingSearch": {
237251
"type": "string",
238252
"value": "[listKeys(resourceId('Microsoft.CognitiveServices/accounts', parameters('bingServiceName')),'2017-04-18').key1]"
253+
},
254+
"azureMaps": {
255+
"type": "string",
256+
"value": "[listKeys(resourceId('Microsoft.Maps/accounts', parameters('azureMapsServiceName')),'2018-05-01').primaryKey]"
239257
}
240258
}
241259
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Globalization;
4+
using System.Linq;
5+
using System.Threading;
6+
using System.Threading.Tasks;
7+
using Microsoft.Bot.Builder;
8+
using Microsoft.Bot.Builder.Dialogs;
9+
using Microsoft.Bot.Builder.Dialogs.Choices;
10+
using NewsSkill.Models;
11+
using NewsSkill.Responses.FavoriteTopics;
12+
using NewsSkill.Services;
13+
14+
namespace NewsSkill.Dialogs
15+
{
16+
public class FavoriteTopicsDialog : NewsDialogBase
17+
{
18+
private NewsClient _client;
19+
private FavoriteTopicsResponses _responder = new FavoriteTopicsResponses();
20+
21+
public FavoriteTopicsDialog(
22+
BotSettings settings,
23+
BotServices services,
24+
ConversationState conversationState,
25+
UserState userState,
26+
AzureMapsService mapsService,
27+
IBotTelemetryClient telemetryClient)
28+
: base(nameof(FavoriteTopicsDialog), settings, services, conversationState, userState, mapsService, telemetryClient)
29+
{
30+
TelemetryClient = telemetryClient;
31+
32+
var newsKey = settings.Properties["BingNewsKey"] ?? throw new Exception("The BingNewsKey must be provided to use this dialog. Please provide this key in your Skill Configuration.");
33+
34+
_client = new NewsClient(newsKey);
35+
36+
var favoriteTopics = new WaterfallStep[]
37+
{
38+
GetMarket,
39+
SetMarket,
40+
SetFavorites,
41+
ShowArticles,
42+
};
43+
44+
AddDialog(new WaterfallDialog(nameof(FavoriteTopicsDialog), favoriteTopics));
45+
AddDialog(new ChoicePrompt(nameof(ChoicePrompt)));
46+
AddDialog(new TextPrompt(nameof(TextPrompt), MarketPromptValidatorAsync));
47+
}
48+
49+
private async Task<DialogTurnResult> SetFavorites(WaterfallStepContext sc, CancellationToken cancellationToken)
50+
{
51+
var convState = await ConvAccessor.GetAsync(sc.Context, () => new NewsSkillState());
52+
var userState = await UserAccessor.GetAsync(sc.Context, () => new NewsSkillUserState());
53+
54+
// if intent is SetFavorites or not set in state yet
55+
if (convState.LuisResult.TopIntent().intent == Luis.newsLuis.Intent.SetFavoriteTopics || userState.Category == null)
56+
{
57+
// show card with categories the user can choose
58+
var categories = new PromptOptions()
59+
{
60+
Choices = new List<Choice>(),
61+
};
62+
63+
categories.Choices.Add(new Choice("Business"));
64+
categories.Choices.Add(new Choice("Entertainment"));
65+
categories.Choices.Add(new Choice("Health"));
66+
categories.Choices.Add(new Choice("Politics"));
67+
categories.Choices.Add(new Choice("World"));
68+
categories.Choices.Add(new Choice("Sports"));
69+
70+
return await sc.PromptAsync(nameof(ChoicePrompt), new PromptOptions()
71+
{
72+
Prompt = await _responder.RenderTemplate(sc.Context, sc.Context.Activity.Locale, FavoriteTopicsResponses.FavoriteTopicPrompt),
73+
Choices = categories.Choices
74+
});
75+
}
76+
77+
return await sc.NextAsync(userState.Category);
78+
}
79+
80+
private async Task<DialogTurnResult> ShowArticles(WaterfallStepContext sc, CancellationToken cancellationToken)
81+
{
82+
var userState = await UserAccessor.GetAsync(sc.Context, () => new NewsSkillUserState());
83+
84+
userState.Category = (FoundChoice)sc.Result;
85+
86+
// show favorite articles
87+
var articles = await _client.GetNewsByCategory(userState.Category.Value, userState.Market);
88+
await _responder.ReplyWith(sc.Context, FavoriteTopicsResponses.ShowArticles, articles);
89+
90+
return await sc.EndDialogAsync();
91+
}
92+
}
93+
}

skills/src/csharp/experimental/newsskill/Dialogs/FindArticlesDialog.cs

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using System;
2+
using System.Globalization;
3+
using System.Linq;
24
using System.Threading;
35
using System.Threading.Tasks;
46
using Microsoft.Bot.Builder;
@@ -18,37 +20,38 @@ public FindArticlesDialog(
1820
BotSettings settings,
1921
BotServices services,
2022
ConversationState conversationState,
23+
UserState userState,
24+
AzureMapsService mapsService,
2125
IBotTelemetryClient telemetryClient)
22-
: base(nameof(FindArticlesDialog), services, conversationState, telemetryClient)
26+
: base(nameof(FindArticlesDialog), settings, services, conversationState, userState, mapsService, telemetryClient)
2327
{
2428
TelemetryClient = telemetryClient;
2529

26-
var key = settings.Properties["BingNewsKey"] ?? throw new Exception("The BingNewsKey must be provided to use this dialog. Please provide this key in your Skill Configuration.");
30+
var newsKey = settings.Properties["BingNewsKey"] ?? throw new Exception("The BingNewsKey must be provided to use this dialog. Please provide this key in your Skill Configuration.");
2731

28-
_client = new NewsClient(key);
32+
_client = new NewsClient(newsKey);
2933

3034
var findArticles = new WaterfallStep[]
3135
{
36+
GetMarket,
37+
SetMarket,
3238
GetQuery,
39+
GetSite,
3340
ShowArticles,
3441
};
3542

3643
AddDialog(new WaterfallDialog(nameof(FindArticlesDialog), findArticles));
37-
AddDialog(new TextPrompt(nameof(TextPrompt)));
44+
AddDialog(new TextPrompt(nameof(TextPrompt), MarketPromptValidatorAsync));
3845
}
3946

4047
private async Task<DialogTurnResult> GetQuery(WaterfallStepContext sc, CancellationToken cancellationToken)
4148
{
42-
var state = await Accessor.GetAsync(sc.Context, () => new NewsSkillState());
49+
var convState = await ConvAccessor.GetAsync(sc.Context, () => new NewsSkillState());
4350

4451
// Let's see if we have a topic
45-
if (state.LuisResult.Entities.topic != null)
52+
if (convState.LuisResult.Entities.topic != null && convState.LuisResult.Entities.topic.Length > 0)
4653
{
47-
// If we have a topic let's skip the topic prompt
48-
if (state.LuisResult.Entities.topic.Length > 0)
49-
{
50-
return await sc.NextAsync(state.LuisResult.Entities.topic[0]);
51-
}
54+
return await sc.NextAsync(convState.LuisResult.Entities.topic[0]);
5255
}
5356

5457
return await sc.PromptAsync(nameof(TextPrompt), new PromptOptions()
@@ -57,10 +60,29 @@ private async Task<DialogTurnResult> GetQuery(WaterfallStepContext sc, Cancellat
5760
});
5861
}
5962

63+
private async Task<DialogTurnResult> GetSite(WaterfallStepContext sc, CancellationToken cancellationToken)
64+
{
65+
var convState = await ConvAccessor.GetAsync(sc.Context, () => new NewsSkillState());
66+
67+
string query = (string)sc.Result;
68+
69+
// if site specified in luis, add to query
70+
if (convState.LuisResult.Entities.site != null && convState.LuisResult.Entities.site.Length > 0)
71+
{
72+
string site = convState.LuisResult.Entities.site[0].Replace(" ", string.Empty);
73+
query = string.Concat(query, $" site:{site}");
74+
}
75+
76+
return await sc.NextAsync(query);
77+
}
78+
6079
private async Task<DialogTurnResult> ShowArticles(WaterfallStepContext sc, CancellationToken cancellationToken)
6180
{
81+
var userState = await UserAccessor.GetAsync(sc.Context, () => new NewsSkillUserState());
82+
6283
var query = (string)sc.Result;
63-
var articles = await _client.GetNewsForTopic(query);
84+
85+
var articles = await _client.GetNewsForTopic(query, userState.Market);
6486
await _responder.ReplyWith(sc.Context, FindArticlesResponses.ShowArticles, articles);
6587

6688
return await sc.EndDialogAsync();

skills/src/csharp/experimental/newsskill/Dialogs/MainDialog.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public MainDialog(
3030
BotServices services,
3131
ConversationState conversationState,
3232
FindArticlesDialog findArticlesDialog,
33+
TrendingArticlesDialog trendingArticlesDialog,
34+
FavoriteTopicsDialog favoriteTopicsDialog,
3335
IBotTelemetryClient telemetryClient)
3436
: base(nameof(MainDialog), telemetryClient)
3537
{
@@ -42,6 +44,8 @@ public MainDialog(
4244
_stateAccessor = _conversationState.CreateProperty<NewsSkillState>(nameof(NewsSkillState));
4345

4446
AddDialog(findArticlesDialog ?? throw new ArgumentNullException(nameof(findArticlesDialog)));
47+
AddDialog(trendingArticlesDialog ?? throw new ArgumentNullException(nameof(trendingArticlesDialog)));
48+
AddDialog(favoriteTopicsDialog ?? throw new ArgumentNullException(nameof(favoriteTopicsDialog)));
4549
}
4650

4751
protected override async Task OnStartAsync(DialogContext dc, CancellationToken cancellationToken = default(CancellationToken))
@@ -72,6 +76,21 @@ public MainDialog(
7276
// switch on general intents
7377
switch (intent)
7478
{
79+
case newsLuis.Intent.TrendingArticles:
80+
{
81+
// send articles in response
82+
turnResult = await dc.BeginDialogAsync(nameof(TrendingArticlesDialog));
83+
break;
84+
}
85+
86+
case newsLuis.Intent.SetFavoriteTopics:
87+
case newsLuis.Intent.ShowFavoriteTopics:
88+
{
89+
// send favorite news categories
90+
turnResult = await dc.BeginDialogAsync(nameof(FavoriteTopicsDialog));
91+
break;
92+
}
93+
7594
case newsLuis.Intent.FindArticles:
7695
{
7796
// send greeting response

0 commit comments

Comments
 (0)