I'm trying to send proactive 1:1 message from bot to teams using Teams SDK with the code below
MicrosoftAppCredentials.TrustServiceUrl(turnContext.Activity.ServiceUrl);
var connectorClient = new ConnectorClient(new Uri(turnContext.Activity.ServiceUrl), Configuration["MicrosoftAppId"], Configuration["MicrosoftAppPassword"]);
var userId = _operation.MemberTeamsId;
var tenantId = Configuration["TenantId"];
var parameters = new ConversationParameters
{
Members = new[] { new ChannelAccount(userId) },
ChannelData = new TeamsChannelData
{
Tenant = new TenantInfo(tenantId),
},
};
var conversationResource = await connectorClient.Conversations.CreateConversationAsync(parameters);
var message = Microsoft.Bot.Schema.Activity.CreateMessageActivity();
message.Text = _operation.Message;
await connectorClient.Conversations.SendToConversationAsync(conversationResource.Id, (Microsoft.Bot.Schema.Activity)message);
I have the following issues with this,
The bot cannot send a proactive message unless the user has a prior conversation after deployment
Bot deployed
Bill to Bot - Works
Bot to Bill - Works
Bot redeployed
Bot to Bill - Not works because there are no members in the conversation now after redeploying
Bill to Bot - Works
Bot to Bill - Works now as Bill had a conversation after redeploying
Bot sends the same message multiple times to users
Bill to Bot - Works
Bot to Bill - Works Proactively - Sends 1 defined message as it should
Sim to Bot - Works
Bot to Sim - Sends 2 same messages as there are two members in the conversation now
Will to Bot - works
Bot to Will - Sends 3 same messages as there are three members in the conversation now
Note: I am storing the Teams userid in DB and use them to send direct messages to users
Any help on how to correct this would be appreciated. Thanks.
Based on the answers in the comments, I think I understand the scenario better, and it looks to me like the problem is that you're not setting a Conversation Id anyway - although you tell the Bot which user you want to interact with, it needs to know if you want to interact with them directly (i.e. 1-1), or as part of a group chat somewhere, or a Teams channel.
You need to set this by configuring the Conversation property on the Activity instance (in your case the "message" variable). See my post here for more detailed information: Programmatically sending a message to a bot in Microsoft Teams
Hope that helps - if not, let me know
Related
I have an existing user in my Xamarin Forms app whose Details are as follows:
First Name: Jim
Last Name: Smith
ProviderLoginId = jsmith#google.com
OAuth Provider: Google
When I first create this user, I use the following method to authenticate against google as follows:
result = await AuthenticationClient.AcquireTokenInteractive("https://***.onmicrosoft.com/profile.read/profile.read")
.ExecuteAsync();
JObject objToken = new JObject();
objToken.Add("access_token", result.IdToken);
MobileServiceUser user = await App.syncMgr.CurrentClient.LoginAsync(MobileServiceAuthenticationProvider.WindowsAzureActiveDirectory, objToken);
Now, I take the UserId property from the MobileServiceUser user variable and store it into my User Table as primary key.
Subsequently, I create another new user with the following details:
First Name: Jim
Last Name: Smith
ProviderLoginId = jsmith#hotmail.com
OAuthProvider: Microsoft
When I create the user using the same steps as above, I get the same UserId back from Azure. Obviously, I am not able to store it in my User table for the second user. This only happens when the first name and the last name are the same regardless of which ProviderLoginId was used (whether it was Google OAuth or Microsoft OAuth).
Should I not be getting a unique UserId in each case? Since the bug surfaces only when the first and last names are same, I am assuming it is some sort of a bug.
Any and all help is appreciated.
You are using the older client, which is no longer supported.
You should be submitting the access token to the service, not the IdToken. You haven't stated what the AuthenticationClient is, but hopefully it is ADAL (since the older service doesn't work with MSAL).
The newer client and service completely abstracts the authentication code, allowing you to use whatever authentication mechanism you like and just dealing with standard OAuth2/OIDC and bearer tokens (Authorization header) instead of the non-standard X-ZUMO-AUTH header that was used in the past. My recommendation is to upgrade the client and server.
How to read particular user latest messages i have userId but i want to read all messages send by that user.
I want if there is any bot functions which can be used for this.
I also want to know can i read reactions on a particular message of that user
It's pretty easy to filter the messages by sender id. You should:
Disable the privacy mode.
A bot running in privacy mode will not receive all messages that
people send to the group.
When you have an incoming update, check for the update.message.from.id to know if he's the target user.
use copyMessage or forwardMessage to send his message to yourself.
Here's a simple example using PHP/TeleBot:
$tg = new TeleBot('your-token');
if ($tg->user->id == 'target-user-id') {
$tg->forwardMessage([
'chat_id' => 'your-user-id',
'from_chat_id' => $tg->chat->id,
'message_id' => $tg->message->message_id,
]);
}
You can also check out this repository to more know and get inspired:
https://github.com/mkleymenov/telespy-bot
I'm trying to implement the "on behalf of" flow in an application using ADFS 2016 as STS. As a reference, I look at this Microsoft tutorial (https://learn.microsoft.com/en-ca/windows-server/identity/ad-fs/development/ad-fs-on-behalf-of-authentication-in-windows-server). It's working as it should, I can login into my web application and then use my original access token in UserAssertion to generate a new access token with the proper audience to call my API BUT I found absolutely no way to include any user informations (sub, name, email, upn etc.) into the access token for my API, even if I set claim rules into my ADFS configurations for the API.
I checked the communication between my app and adfs using Fiddler and everything looks like the informations in the tutorial. See the screen shot of the "on behalf of" request below :
Here's the resulting access token :
Finally, here's the code I use to generate my new access token :
private async Task<string> GetAccessToken(ClaimsPrincipal user, string originalAccessToken)
{
var authority = "[authority]";
var context = new AuthenticationContext(authority, false);
string userName = user.FindFirstValue("upn");
var userAssertion = new UserAssertion(originalAccessToken, "urn:ietf:params:oauth:grant-type:jwt-bearer",userName);
var cc = new ClientCredential("https://localhost:44387/", "[client_secret]");
var result = await context.AcquireTokenAsync("https://localhost:44339/", cc, userAssertion);
return result.AccessToken;
}
Have you struggle with that scenario and if yes, did you find a way to fix this ?
Thanks
I've only used the Microsoft On Behalf Of flow with Azure AD and not ADFS, but it looks like you need to send a more detailed scope in your User Info request.
Maybe try sending 'openid profile email', to indicate that you want that type of detail, as in Section 17 of my blog post. Of course this assumes that this type of data has been registered for all users.
TROUBLESHOOTING
Looks like one of these will be the cause:
A suboptimal Microsoft library that does not allow you to send the required scope
Or ADFS 2016 perhaps lacks the scope features that work correctly in Azure AD
I would concentrate on making extra sure you are sending the correct form URL encoded request message, using a tool such as curl, Postman or a plain C# HttpClient. Here is the code I used to send the correct scope - using an open source library rather than a Microsoft one:
Sample NodeJS Code
If you can get the scope sent correctly then you should have a resolution either way:
Either you get the correct data and can update your code
Or the behaviour you want is not supported by ADFS
Good luck ...
In the signalr, for each tag that opens, the ConnectionId registers for the user.
I use the following code to send messages to users.
1
2
hubContext.Clients.Clients (user.ConnectionIds.ToLi st ()); receiveNotification (message, userID, link);
The problem I have is that I want to send a message to the user once, not to the number of ConnectionId.
How can I find one of its active ConnectionIds and just send that message?
Is there a better way?
I also worked on this link
https://stackoverflow.com/questions/...ovider-new-2-0
But because of
I do not use request.User.Identity.Name, this method does not work. I'm using my user id. I'm reading the table.
value of request.User.Identity.Name in my app is empty because i'm reading user information from table in database
Thanks for your advice
You can retain connection and user information in a Map that is stored in memory.
private readonly Dictionary<T, HashSet<string>> _connections =
new Dictionary<T, HashSet<string>>();
You can find the fulle example here :
https://learn.microsoft.com/en-us/aspnet/signalr/overview/guide-to-the-api/mapping-users-to-connections
I know I create new bot, give it name, description from BotFather inside telegram
But this only adds the bot, when I modify my bot, code some functionality in python\lua\php etc - where should the code go and how telegram will know the behavior of my bot?
Who runs the new code, where should I upload my new additional code for my bot?
Does it go to telegram server and runs there on the cloud?
If so, how to upload it?
After you have setup your Bot's identity (#bot_name) with BotFather, the next step is to design the interaction/functions your Bot will perform.
Your bot code lives on YOUR server.
Requests from users interacting with your #bot_name will be routed from Telegram to your servers which ...
1) you have setup with a webHook (using the setWebhook method) so Telegram knows where to send your bot's requests
or
2) your bot polls Telegram's Bot-API repeatedly asking if there are any new updates (i.e. messages users sent to your bot) using the getUpdates method
Your bot receives these messages, and replies as directed by your bots "code or logic"
hope this helps.
You can run the code quite easily from your machine.
For example how I did it using NodeJS:
1)Install NodeJS on your machine (details - https://nodejs.org/en/download/package-manager/)
2)Install Node Telegram Bot API (https://github.com/yagop/node-telegram-bot-api)
3) create a file like this, filling in with necessary changes:
const TelegramBot = require('node-telegram-bot-api');
// replace the value below with the Telegram token you receive from #BotFather
const token = 'YOUR_TELEGRAM_BOT_TOKEN';
// Create a bot that uses 'polling' to fetch new updates
const bot = new TelegramBot(token, {polling: true});
// Matches "/echo [whatever]"
bot.onText(/\/echo (.+)/, (msg, match) => {
// 'msg' is the received Message from Telegram
// 'match' is the result of executing the regexp above on the text content
// of the message
const chatId = msg.chat.id;
const resp = match[1]; // the captured "whatever"
// send back the matched "whatever" to the chat
bot.sendMessage(chatId, resp);
});
// Listen for any kind of message. There are different kinds of
// messages.
bot.on('message', (msg) => {
const chatId = msg.chat.id;
// send a message to the chat acknowledging receipt of their message
bot.sendMessage(chatId, 'Received your message');
});
4) Finally launch your command console (like cmd on Windows) navigate to telegram bot directory where the script is located and type node index.js (assuming your file with the bot script like above is named index.js)
Following these steps you will have a fully functioning bot. As you make changes to index.js you can simply rerun the command "node index.js" in console.
The procedure is similar if you need to set up a bot on a server.
Hope this helps.