Getting graph-compatible Team and conversation IDs in a Teams bot - botframework

I'm trying to use the new message action feature in Teams in my bot application. I can get the task module to invoke, but I want to have the bot read the contents of the full message thread (not just the first message as passed into the context). When I examine the ChannelData though, I get this:
ChannelData {{
"channel": {
"id": "19:5e4ce488280b467198400257473cfd4e#thread.skype"
},
"team": {
"id": "19:7a81d1b1c0b24ac192de1c3d5cfd5618#thread.skype"
},
"tenant": {
"id": "8c6ae172-a3ea-4f50-994d-a0256822697f"
},
"source": {
"name": "compose"
}
}}
It looks like you should be able to get the messages in a channel using the beta API like this:
GraphServiceClient graphClient = new GraphServiceClient( authProvider );
var replies = await graphClient.Teams["303d2c1c-f1c5-40ce-b68e-544343d7f42b"].Channels["19:fec4b0f2825d4c8c82abc09027a64184#thread.skype"].Messages["1555375673184"].Replies
.Request()
.GetAsync();
The challenge is, calling this using a TeamID, formatted as "19:7a81d1b1c0b24ac192de1c3d5cfd5618#thread.skype" doesn't work, and instead it needs the TeamID specified as a standard GUID (in this case, d12f244e-fd24-4430-a58a-1b2650ba8997). Is there a way to convert between these two ID formats? Is there something that details why they're different?

You can!
You have to use the Microsoft.Bot.Builder.Teams Package / GitHub.
From the README, you can get the Team ID:
var teamInfo = await teamsContext.Operations.FetchTeamDetailsAsync(incomingTeamId);
That will be in teamInfo.AadGroupId and is formatted as the GUID.

Related

/* in transcoding from HTTP to gRPC

rpc CreateBook(CreateBookRequest) returns (Book) {
option (google.api.http) = {
post: "/v1/{parent=publishers/*}/books"
body: "book"
};
}
message CreateBookRequest {
// The publisher who will publish this book.
// When using HTTP/JSON, this field is automatically populated based
// on the URI, because of the `{parent=publishers/*}` syntax.
string parent = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {
child_type: "library.googleapis.com/Book"
}];
Book book = 2 [(google.api.field_behavior) = REQUIRED];
string book_id = 3;
}
I don't understand post: "/v1/{parent=publishers/*}/books"
I thought publishers was a field in CreateBookRequest, then it populates to http, so it is something like this
post: "/v1/parent=publishers_field_value/books"
But publishers is not a field in CreateBookRequest
No, publishers is part of the expected value of the parent field. So suppose you have a protobuf request like this:
{
"parent": "publishers/pub1",
"book_id": "xyz"
"book": {
"author": "Stacy"
}
}
That can be transcoded by a client into an HTTP request with:
Method: POST
URI: /v1/publishers/pub1/books?bookId=xyz (with the appropriate host name)
Body:
{
"author": "Stacy"
}
If you try to specify a request with a parent that doesn't match publishers/*, I'd expect transcoding to fail.
That's in terms of transcoding from protobuf to HTTP, in the request. (That's the direction I'm most familiar with, having been coding it in C# just this week...)
In the server, it should just be the opposite - so given the HTTP request above, the server should come up with the original protobuf request including parent="publishers/pub1".
For a lot more information on all of this, see the proto defining HttpRule.

How do I mention a Bot (not a user) using CardFactory.adaptiveCard (NodeJS) in a post to a channel

I've scoured all four corners of interweb trying to find documentation on how to do this. But my journey has been unsuccessful so far. Part way through the search, I was able to find out how to mention a User (not a bot), and that was even a pain to find. I found that you have to post a field named msteams at the top level of the "any" object parameter which is an object consisting of an entities array. That array is an array of objects. The following use of adaptiveCard works when mentioning a user with the proper values replacing username and userID:
CardFactory.adaptiveCard({
$schema: 'http://adaptivecards.io/schemas/adaptive-card.json',
type: 'AdaptiveCard',
msteams: {
entites: [
{
type: 'mention',
text: '<at>(username)</at>',
mentioned: {
id: <userID>,
name: <username>,
role: 'user'
}
}
]
}
body: [
{
type: 'TextBlock',
text: '<at>(userName)</at>',
}
]
});
The documentation of CardFactory.adaptiveCard just lists the parameter as an any Object and gives a small example not displaying an exhaustive list of fields of this parameter. It also posts a link to the Adaptive Card documentation, but that's what it's abstracting and the fields are not 1:1 (point and case this msteams object that is never referenced in the Adaptive Card documentation from what I can tell). I want to mention the bot itself that is posting this Adaptive Card. I've attempted to replace the mentioned object with the following
{
"id": "a3216960-131c-11eb-xxxx-xxxxxxxxx",
"name": "Bot",
"role": "bot"
}
This is equivalent to the object that I'm using to mention the "from" user in the adaptive card. But this is the recipient. The from user which is successfully mentioned is formatted like the following:
{
"id": "c3370a7c-95f2-4a60-xxxx-xxxxxxxxx",
"name": "User",
"role": "user"
}
Any help/guidance, tips, references would be greatly appreciated!
Currently #mention a bot in Adaptive card is not supported. You can #mention user in Adaptive card.

Web Api Query for Actions msdyn_BookingResource and msdyn_BookingResourceRequirement

From the web api reference here
I tried querying the api with no luck of success specially with the parameter Schedules being stated as type string.
1.) For msdyn_BookingResource
POST: https://bhaud365dev.crm6.dynamics.com/api/data/v9.0/msdyn_BookingResource
BODY:
{"ResourceId":[GUID],"BookingStatusId":[GUID],"BookingMethod":690970003,"BookingType":1,"Schedules":"[{\"StartDateTime\":\"2019-07-15T00:00:00Z\",\"EndDateTime\":\"2019-07-19T00:00:00Z\"}]","Timeframe":5}
RESPONSE: {
"error": {
"code": "0x80040224",
"message": "The added or subtracted value results in an un-representable DateTime.\r\nParameter name: value",
2.) For msdyn_BookingResourceRequirement
POST: https://bhaud365dev.crm6.dynamics.com/api/data/v9.1/msdyn_resourcerequirements([GUID])/Microsoft.Dynamics.CRM.msdyn_BookingResourceRequirement
BODY: {
"BookingMethod": 690970003,
"BookingStatusId": [GUID],
"BookingType": 1,
"EndDateTime": "2019-07-19T07:29:00Z",
"ResourceId": [GUID],
"StartDateTime": "2019-07-15T22:00:00Z"
}
RESPONSE: {
"error": {
"code": "0x80040224",
"message": "Object reference not set to an instance of an object.",
I was able to api query for functions but for the actions I am stuck and I am not sure on what am I doing wrong. Any tips or example is greatly appreciated.
BTW. tried the above queries also in CRM REST BUILDER v2.6.0.0 Same error responses.
I spent some time, getting same weird error and then I realized they are Internal Use only Actions. It's not intended for our usage & it's highly unsupported as they tend to break in future versions when Microsoft planned to change.
I was able to successfully create the Bookable Resource Bookings with the help of below web api request.
var entity = {};
entity["Resource#odata.bind"] = "/bookableresources(7B203E2F-F2FB-E911-A813-000D3A5A1BF8)";
entity["BookingStatus#odata.bind"] = "/bookingstatuses(026BDCEF-9257-4C10-9E49-C92539B883D6)";
entity["endtime"] = "2019-11-07T21:00:00Z";
entity["starttime"] = "2019-11-07T20:00:00Z"
entity.bookingtype = 1;
entity.msdyn_bookingmethod = 690970003;
Xrm.WebApi.online.createRecord("bookableresourcebooking", entity).then(
function success(result) {
var newEntityId = result.id;
},
function(error) {
Xrm.Utility.alertDialog(error.message);
}
);

How to pass the validation code to the Lambda function

I'm trying to customize the email that AWS Cognito sends if a user has forgotten their password.
It requires {####} placeholder for the verification code in the email message. For example, if you do
event['response']['emailMessage'] = "Your code is {####}", you'll receive a message Your code is 123456.
Here's an example of my AWS Lambda function:
def custom_message_handler(event, context):
event['response']['emailSubject'] = 'Custom subject'
event['response']['emailMessage'] = 'Custom email'
# verification_code = event[...] ???
return event
It seems like Cognito generates the verification code after your lambda returned the message with the placeholder. Is it possible to get the verification code inside your lambda to use it?
Amazon Cognito's Custom Message Lambda Trigger's Event JSON does not get the numerical verification code. The data of the Event available to the trigger, as stated in the official documentation is stated as follows:
{
"version": 1,
"triggerSource": "CustomMessage_AdminCreateUser",
"region": "<region>",
"userPoolId": "<userPoolId>",
"userName": "<userName>",
"callerContext": {
"awsSdk": "<calling aws sdk with version>",
"clientId": "<apps client id>",
...
},
"request": {
"userAttributes": {
"phone_number_verified": false,
"email_verified": true,
...
},
"codeParameter": "####",
"usernameParameter": "username"
},
"response": {
"smsMessage": "<custom message to be sent in the message with code parameter and username parameter>"
"emailMessage": "<custom message to be sent in the message with code parameter and username parameter>"
"emailSubject": "<custom email subject>"
}
}
You would be able to use Cognito data in a Lambda trigger only if it is available in an Event, or if there is a separate API call for the same. But given Amazon Cognito's design, this does not seem to be possible.

Getting image from Sharepoint post with Microsoft Graph

My company has made a custom photo-field in Sharepoint for it's news. I'm trying to use Microsoft Graph to fetch the images, but with no success.
This is the columns description:
{
"columnGroup": "Page Layout Columns",
"description": "",
"displayName": "Thumbnail image",
"enforceUniqueValues": false,
"hidden": false,
"id": "XXXXXXX-XXXX-XXXX-XXX-XXXXXXXXXXXX",
"indexed": false,
"name": "PublishingPageImage",
"readOnly": false,
"required": false
},
In the documentation for Microsoft Graph it is written that you can make a request like this
GET https://graph.microsoft.com/beta/sites/{site-id}/lists/{list-id}/items?expand=fields(select=Column1,Column2)
Although - no matter how I seem to write the request, i can't get the image field.
My most recent try has been this request:
https://graph.microsoft.com/beta/sites/knowit.sharepoint.com/lists/posts/items?expand=fields(select=PublishingPageImage)
The respons I got from Microsoft was this:
{
"error": {
"code": "-1, Microsoft.SharePoint.Client.ClientServiceException",
"message": "Cannot serialize data for type Microsoft.SharePoint.Publishing.Fields.ImageFieldValue.",
"innerError": {
"request-id": "f25e4851-0c1b-4061-ad6a-948d38004046",
"date": "2018-09-17T14:03:01"
}
}
}
Should I use something like .value or .data or .ImageUrl after the request? If i get a link or a data-value doesn't really matter. In the call for /me/ for Microsoft users there is a $value property for getting the user profile photo. Is it something like this?
It depends how image is stored.
If it is attachment you can do following:
string baseURL = $"https://{spTenant}/_api/web/lists('{ AA.config.listID}')/items({ siteData.Id})/AttachmentFiles";
string fileName = await GetFileNameAsync(baseURL);
string getPictureReqUrl = $"{baseURL}('{fileName}')/$value";
Stream responseStream = await GetPictureAsync(getPictureReqUrl);
private static async Task<Stream> GetPictureAsync(string reqUrl)
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", SPOToken);
HttpResponseMessage response = await client.GetAsync(reqUrl);
return await response.Content.ReadAsStreamAsync();
}
Important! This is not supported by graph yet, but you can use SharePoint Rest API
If picture is stored in document library you need to use Drive object instead
https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/resources/drive

Resources