I want to escalate the conversation to the agent portal i.e. Dynamaics omnichannel customer service. But I didn't get the response from agent portal - dynamics-365

Actually, I have built a bot and registered it with the azure service and Dynamics 365 omnichannel customer service. I want to escalate the conversation to the human agent from dynamics omnichannel customer service. I have a code snippet from Microsoft but that is in C#. I have written the logic according to the reference code in JavaScript but I didn't get a response from the agent side. Below is the C# code snippet but I want it in JavaScript. can anyone help me to solve this issue?
if (turnContext.Activity.Text.Contains("agent") | conversation.EscalationDictionary.ContainsKey(turnContext.Activity.Text))
{
Dictionary<string, string> endConversationContext = new Dictionary<string, string>();
if (conversation.EscalationDictionary.ContainsKey(turnContext.Activity.Text)) { endConversationContext = conversation.EscalationDictionary[turnContext.Activity.Text]; }
await turnContext.SendActivityAsync("Transferring to an agent, who can help you with this. Please remain online…");
Dictionary<string, object> handOffContext = new Dictionary<string, object>()
{
{ "BotHandoffContext", "Specialist request" },
{ "skill", "service" }
};
var handoffevent = EventFactory.CreateHandoffInitiation(turnContext, new
{
MessageToAgent = "Issue Summary: billing question",
Context = handOffContext
}); // Transcript is persisted by Omnichannel
await turnContext.SendActivityAsync(handoffevent);
}
this is a JavaScript code that I have written. But I didn't get a response from agent portal end.
async function handoffMiddleware(context, next) {
if (context.activity.text == "agent") {
await context.sendActivity("Transferring conversation to the agent")
// let activities = GetRecentActivities()
let handoffContext = {
botHandoffContext: "specialist request",
}
console.log(handoffContext)
let handoffEvent = EventFactory.createHandoffInitiation(context, {
message: "summary:fine",
context: handoffContext,
})
handoffEvent.type = ActivityTypes.Message
handoffEvent.text = "agent can handle this issue"
console.log(handoffEvent)
await context.sendActivity(handoffEvent)
}
await next()
}

Related

How to use TeamsFx useGraph hook to get meeting infos

I would like to use TeamsFx React package to call MS Graph Api.
I tried to do separated component
import { useContext } from "react";
import { useGraph } from "#microsoft/teamsfx-react";
import { TeamsFxContext } from "../Context";
import { TeamsFxProvider } from "#microsoft/mgt-teamsfx-provider";
import { Providers, ProviderState } from "#microsoft/mgt-element";
import * as microsoftTeams from "#microsoft/teams-js";
export function MeetingContext(props: { showFunction?: boolean; environment?: string }) {
const { teamsfx } = useContext(TeamsFxContext);
const { loading, error, data, reload } = useGraph(
async (graph, teamsfx, scope) => {
// Call graph api directly to get user profile information
let profile;
try {
profile = await graph.api("/me").get();
} catch (error) {
console.log(error);
}
// Initialize Graph Toolkit TeamsFx provider
const provider = new TeamsFxProvider(teamsfx, scope);
Providers.globalProvider = provider;
Providers.globalProvider.setState(ProviderState.SignedIn);
let photoUrl = "";
let meeting =null;
try {
const photo = await graph.api("/me/photo/$value").get();
photoUrl = URL.createObjectURL(photo);
microsoftTeams.getContext(async (context)=>{
console.log(context);
try {
meeting = await graph.api(`/me/onlineMeetings/${context.meetingId}`).get();
} catch (error) {
console.error(error);
}
})
} catch {
// Could not fetch photo from user's profile, return empty string as placeholder.
}
console.log(meeting);
return { meeting };
},
{ scope: ["User.Read","User.Read","OnlineMeetingArtifact.Read.All"," OnlineMeetings.Read"], teamsfx: teamsfx }
);
return (
<>
</>
)
}
When I debug my interpreter stops on
profile = await graph.api("/me").get();
Then it does not pass after.
I would like also to know what should I put in scope field ?
Should I put the authorisations listed here ?
Should I also Add them in registered app in Azure Portal ?
Update:
I'm getting response from
Failed to get access token cache silently, please login first: you need login first before get access token.
I'm using the teams toolkit and I'm already logged in . I don't know what Should I do to be considered as logged in ?
Update :
I have updated my app api authorisations in azure portal now I'm not getting anymore this error.
But I'm getting a new error :
meeting = await graph.api(`/me/onlineMeetings/${context.chatId}`).get();
"Invalid meeting id
19:meeting_MzU0MzFhYTQtNjlmOS00NGI4LTg1MTYtMGI3ZTkwOWYwMzk4#thread.v2."
I'll post a new question about this as it not the original problem
You can get the details of an online meeting using videoTeleconferenceId, meeting ID, or joinWebURL.
Instead of ChatID you have to use meeting ID or you have to use filter with videoTeleconferenceId or joinWebURL.
The invalid meeting ID error get because
chatID is not the correct parameter for this graph API.
You can refer below API for getting meeting information.
To get an onlineMeeting using meeting ID with delegated (/me) and app (/users/{userId}) permission:
GET /me/onlineMeetings/{meetingId}
GET /users/{userId}/onlineMeetings/{meetingId}
To get an onlineMeeting using videoTeleconferenceId with app permission*:
GET /communications/onlineMeetings/?$filter=VideoTeleconferenceId%20eq%20'{videoTeleconferenceId}'
To get an onlineMeeting using joinWebUrl with delegated and app permission:
GET /me/onlineMeetings?$filter=JoinWebUrl%20eq%20'{joinWebUrl}'
GET /users/{userId}/onlineMeetings?$filter=JoinWebUrl%20eq%20'{joinWebUrl}'
Ref Doc: https://learn.microsoft.com/en-us/graph/api/onlinemeeting-get?view=graph-rest-1.0&tabs=http

I want to implement auto complete search for bot from Mongo Database

I want to implement auto complete search for bot..for example bot should get responses as auto complete options from Mongo Database. Can any one suggest how to do this without Azure Search?
I have tried implementing like this but in my case i want to get the tags from Database.
May i know what are the available options to do this?
When you send a message from the bot, you can add the autocomplete options to the activity's channel data. Then in Web Chat, you can use a custom store middleware to retrieve the options and update the JQuery Auto complete widget.
Bot Framework SDK v4 (C#)
var reply = turnContext.Activity.CreateReply();
reply.Text = "Hello, World!";
reply.ChannelData = JObject.FromObject( new {
autocompleteOptions = new List<string>() { "Option 1", "Option 2", "Option 3" }
});
await turnContext.SendActivityAsync(reply);
Web Chat v4
const store = createStore(
{},
({ dispatch }) => next => action => {
if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY') {
const { payload: { activity: { channelData: { autcompleteOptions } = {}}}} = action;
if (autcompleteOptions) {
// Update JQuery Autcomplete Widget with `autocompleteOptions`
}
}
return next(action);
}
);
For more details take a look at the Incoming Event Web Chat Sample and this Stack Overflow answer.
Hope this helps!

Secure Web API Post Method with Username and Password

I have a Web API service hosted in Microsoft Azure. I need a certain POST method to be only accessible with one unique username and password.
I understand the [Authorize] method does a token based authentication but its not tied to a single username and password. In my app, the web api also does the login authentication, so anyone who registers can access this post method if im not mistaken. (Please correct me if im wrong)
I am new to this could you guide me the right way please.
This is my WebAPI Post method i want to secure access to with specific unique username&pass:
[AllowAnonymous]
[HttpPost, Route("send")]
public async Task<NotificationOutcome> Post([FromBody]string message)
{
string hubName = "myHub";
string hubNameDefaultShared = "myHubNameDefaultShared";
NotificationHubClient hub = NotificationHubClient
.CreateClientFromConnectionString(hubNameDefaultShared, hubName, enableTestSend: true);
string installationId = string.Empty;
var templateParams = new Dictionary<string, string>
{
["messageParam"] = message
};
NotificationOutcome result = null;
if (string.IsNullOrWhiteSpace(installationId))
{
result = await hub.SendTemplateNotificationAsync(templateParams).ConfigureAwait(false);
}
else
{
result = await hub.SendTemplateNotificationAsync(templateParams, "$InstallationId:{" + installationId + "}").ConfigureAwait(false);
}
return result;
}
And this is how I currently access the POST Method:
var client = new RestClient("myWebApiRouteName");
var request = new RestRequest(Method.POST);
request.AddHeader("Postman-Token", "46c23eba-8ca6-4ede-b4fe-161473dc063a");
request.AddHeader("cache-control", "no-cache");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("undefined", messageBody, ParameterType.RequestBody);
try
{
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}

c# - Cannot generate file with YouTube authentication tokens

I’m developing an asp.net application for video uploading in YouTube which uses IIS server. A refresh token is needed for successfully uploading. The following code shows the method which should generate new file with authentication access and refresh tokens in a file path passed as argument:
private void SetRefreshToken(string refresh_token_path)
{
ClientSecrets secrets = new ClientSecrets()
{
ClientId = this.clientId,
ClientSecret = this.clientSecret
};
UserCredential credentials;
try
{
// Approach 1
credentials = GoogleWebAuthorizationBroker.AuthorizeAsync(
secrets,
new[]
{
YouTubeService.Scope.YoutubeReadonly,
YouTubeService.Scope.YoutubeUpload,
YouTubeService.Scope.Youtube,
YouTubeService.Scope.YoutubeForceSsl,
YouTubeService.Scope.Youtubepartner,
YouTubeService.Scope.YoutubepartnerChannelAudit
},
"user",
CancellationToken.None,
new FileDataStore(refresh_token_path)
).Result;
// Approach 2
//IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(
// new GoogleAuthorizationCodeFlow.Initializer
// {
// ClientSecrets = secrets,
// Scopes = new[] {
// YouTubeService.Scope.YoutubeReadonly,
// YouTubeService.Scope.YoutubeUpload,
// YouTubeService.Scope.Youtube,
// YouTubeService.Scope.YoutubeForceSsl,
// YouTubeService.Scope.Youtubepartner,
// YouTubeService.Scope.YoutubepartnerChannelAudit
// },
// DataStore = new FileDataStore(refresh_token_path, true)
// });
}
catch (Exception ex)
{
System.IO.File.WriteAllText(#"D:\error.txt", string.Format("{0}{1}{2}", ex.Message, Environment.NewLine, ex.StackTrace));
}
}
When I start it, if I use Approach 1 - through "GoogleWebAuthorizationBroker.AuthorizeAsync" method, the execution flow freezes in the method. If I use Approach 2 - through "GoogleAuthorizationCodeFlow.Initializer" the code flow continues without throwing any exceptions but in fact there is no created file in the specified file path "refresh_token_path".
When I start this code in a test console application it works fine in both cases.
Could you, please, give me an appointment what is the reason for this and how could I fix it?
Thanks in advance!

asp.net web form client with identity server 4

I have a asp.net solution which consists of
1). asp.net identity server rc 3
2). asp.net Core web api
3). asp.net webform ( not in asp.net core, client)
I don't see any sample with identity server 4 and web form client. Can you please suggest how to authenticate web form user using identity server with asp.net identity and then call api with the access token ?
I don't see identity server 4 sample with web form client or sample
identity server 3 has a sample but it is doing everything in startup
When i see mvc client for identity server 4, it has all settings in configure method and then calls it like this
How will i apply Authorize attribute in webform so that i am redirected to identity server 4 for login and then after login when i call api like this:
how to change client for webform ?
new Client()
{
ClientId = "mvcClient",
ClientName = "MVC Client",
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
ClientSecrets = new List<Secret>()
{
new Secret("secret".Sha256())
},
RequireConsent = false;
// where to redirect to after login
RedirectUris = { "http://localhost:5002/signin-oidc" },
// where to redirect to after logout
PostLogoutRedirectUris = { "http://localhost:5002" },
AllowedScopes =
{
StandardScopes.OpenId.Name,
StandardScopes.Profile.Name,
StandardScopes.OfflineAccess.Name,
StandardScopes.Roles.Name,
"API"
}
}
new InMemoryUser()
{
Subject = "1",
Username = "testuser",
Password = "password",
Claims = new List<Claim>()
{
new Claim("name", "Alice"),
new Claim("Website", "http://alice.com"),
new Claim(JwtClaimTypes.Role, "admin")
}
}
return new List<Scope>()
{
StandardScopes.OpenId, // subject id
StandardScopes.Profile, // first name, last name
StandardScopes.OfflineAccess,
StandardScopes.Roles,
new Scope()
{
Name = "API",
Description = "API desc",
Type = ScopeType.Resource,
Emphasize = true,
IncludeAllClaimsForUser = true,
Claims = new List<ScopeClaim>
{
new ScopeClaim(ClaimTypes.Name),
new ScopeClaim(ClaimTypes.Role)
}
}
};
public void CallApiUsingClientCredentials()
{
var tokenClient = new TokenClient("http://localhost:5000/connect/token", "mvc", "secret");
var tokenResponse = await tokenClient.RequestClientCredentialsAsync("api1");
var client = new HttpClient();
client.SetBearerToken(tokenResponse.AccessToken);
var content = await client.GetStringAsync("http://localhost:5001/identity");
var result = JArray.Parse(content).ToString();
}
[Authorize(Roles="admin)]
[HttpGet]
public IActionResult Get()
{
return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
}
Late answer, but hopefully it helps someone, still supporting web forms.
There is no problem to use startup together with web forms. The only limitation is no place for AuthorizeAttribute there, but it's still not a problem, just put:
app.UseStageMarker(PipelineStage.Authenticate);
at the bottom of your
public void Configuration(IAppBuilder app)
method within OWIN Startup.An example Startup implementation could be fetched from my github. It works with MVC, Web Forms and additionally brings JWT validation from IdentityServer v.3' codebase, upgraded to compile with the latest OWIN libraries.
If I still left anything unclear, don't hesitate to ask in the comments.

Resources