I'm trying to implement pretty simple teams bot but constantly facing an issues with unpredictable behavior. E.g. documentation clearly says that Teams applies Adaptive card as link unfurling response but when I'm sending pretty simple response like:
var card = new AdaptiveCard(new AdaptiveSchemaVersion(1, 0));
card.Body.Add(new AdaptiveTextBlock { Text = "Title", Size = AdaptiveTextSize.ExtraLarge });
var attachment = new MessagingExtensionAttachment { ContentType = AdaptiveCard.ContentType, Content = card };
var result = new MessagingExtensionResult(AttachmentLayoutTypes.List, "result", new[] { attachment });
return new MessagingExtensionResponse(result);
Teams doesn't render anything or follback to the default behavior.
So the question is - are there any way to debug why it doesn't work?
Had the same issue, the problem is this is not documented at all. You'll need to send a hero card (maybe something else works as well?) as preview and the adaptive card as full card:
return {
composeExtension: {
type: 'result',
attachmentLayout: 'list',
attachments: [{
preview: CardFactory.heroCard("title", "description")
...CardFactory.adaptiveCard(card)
}]
}
};
This will display an "expandable" hero card which resolves to the adaptive card.
one easy way to find out what's going on and if your part is generally ok is by sending a full "static" card as a test. Just create the JSON layout somewhere, load it and sent it unchanged to MS Teams.
Also creating AdaptiveCard's like that is not the best way to do it, have a look at https://learn.microsoft.com/en-us/adaptive-cards/templating/ its a lot easier to handle cards like that.
Specific to your question there's no real way to debug anything inside ms teams. You can get a few errors in the analytics part of the bot framework and some times console output of your browser gives a few hints.
I wrote a similar thing some time ago which inserts a card on specific links similar to what you're trying to do and generally, that was (and still is) working fine.
Related
I developed a messaging extension for Teams. I want it to only be available for the teams i specifically install the app to. Is that possible and how? I can't find any info on this, but my use-case does not seem to be far-fetched, so i would expect it to be possible.
use-case: Members of a team use an external system to register cases. I want them to be able to search and reference cases within the teams corresponding project site in the external system. I add a tab to the general channel that refers to the project site, and the messaging extension uses the contentUrl of that tab to query the right case list. I don't want the extension to be available outside the teams channels. By default it seems that the extension is available in every chat input option.
Message extensions do no have a scope defined and they are available once you install it in teams. Currently, it is no possible to restrict to show the message extension in one team
I ended up responding with a card that handles the error:
private MessagingExtensionResponse errorResponse(string title, string errorText)
{
MessagingExtensionResult composeExtensionResult = new MessagingExtensionResult
{
Type = "result",
AttachmentLayout = "list",
Attachments = new List<MessagingExtensionAttachment>(),
};
ThumbnailCard h = new ThumbnailCard()
{
Title = title,
Text = errorText,
};
composeExtensionResult.Attachments.Add(h.ToAttachment().ToMessagingExtensionAttachment());
var messagingExtensionResponse = new MessagingExtensionResponse();
messagingExtensionResponse.ComposeExtension = composeExtensionResult;
return messagingExtensionResponse;
}
Although it would be nice to be able to scope the extension, this way i can catch some more invalid usage. For example:
var currentTeam = new TeamDetails();
IList<ChannelInfo> currentTeamChannels = new List<ChannelInfo>();
try
{
currentTeam = await TeamsInfo.GetTeamDetailsAsync(turnContext, turnContext.Activity.TeamsGetTeamInfo().Id, cancellationToken);
currentTeamChannels = await TeamsInfo.GetTeamChannelsAsync(turnContext, turnContext.Activity.TeamsGetTeamInfo().Id, cancellationToken);
}
catch
{
return errorResponse("Permission error", "This app has no permissions to this team / channel. Please add the app to this team / channel.");
}
Got the suggestion from this question: Is it possible for a teams messaging extension to return a plaintext response instead of a card?
I am new to bot framework and c# - we implemented a bot using a QnA maker knowledge base. I am trying to use adaptive cards with Adaptive Submit Actions.
Everything works perfectly in the WebChat, however in Teams I cannot display more than 6 submit actions at the same time...
Please find a test code below:
var demoActionList = new List<AdaptiveAction>();
for (int i=0; i<20; i++)
{
demoActionList.Add(
new AdaptiveSubmitAction()
{
Type = "Action.Submit",
Title = "title + "+i,
Data = new QnABot.Dialog.MsTeamsDataResponseWrapper() { MsTeamsResponse = new QnABot.Dialog.MsTeamsResponse() { Value = "title + " + i } }
});
}
var plCard = new AdaptiveCard(new AdaptiveSchemaVersion(1, 0));
plCard.Actions = demoActionList;
var attachment = new Attachment()
{
ContentType = AdaptiveCard.ContentType,
Content = plCard
};
chatActivity.Attachments.Add(attachment);
If I run this code in the webchat I will see all the 20 submit actions in the adaptive cards, however in ms teams I see only 6
Please see the example with teams, and the example with the webchat
Any idea how to display all the submit actions in the card with ms teams?
Teams does support carousels, so you could have multiple card attachments in a single activity like this.
This is a known hard limit in Teams right now - see this answer from someone at Microsoft not long ago: Can I show more than one button/option in teams using cards? which includes some suggested workarounds.
update: I'm also wondering if list cards might be of interest - it would look a bit similar to the web chat example you showed above - basically a long list of options.
const TeleBot = require('telebot');
const bot = new TeleBot({
token: 'i9NhrhCQGq7rxaA' // Telegram Bot API token.
});
bot.on(/^([Hh]ey|[Hh]oi|[Hh]a*i)$/, function (msg) {
return bot.sendMessage(msg.from.id, "Hello Commander");
});
var Historiepics = ['Schoolfotos/grr.jpg', 'Schoolfotos/boe.jpg',
'Schoolfotos/tobinsexy.jpg'];
console.log('Historiepics')
console.log(Math.floor(Math.random() * Historiepics.length));
var foto = Historiepics[(Math.floor(Math.random() * Historiepics.length))];
bot.on(/aap/, (msg) => {
return bot.sendPhoto(msg.from.id, foto);
});
bot.start();
The result I'm getting from this is just one picture everytime, but if I ask for another random picture it keeps showing me the same one without change.
I recently figured this out, so I'll drop an answer for anyone that runs into this issue.
The problem is with Telegram's cache. They cache images server side so that they don't have to do multiple requests to the same url. This protects them from potentially getting blacklisted for too many requests, and makes things snappier.
Unfortunately if you're using an API like The Cat API this means you will be sending the same image over and over again. The simplest solution is just to somehow make the link a little different every time. This is most easily accomplished by including the current epoch time as a part of the url.
For your example with javascript this can be accomplished with the following modifications
bot.on(/aap/, (msg) => {
let epoch = (new Date).getTime();
return bot.sendPhoto(msg.from.id, foto + "?time=" + epoch);
});
Or something similar. The main point is, as long as the URL is different you won't receive a cached result. The other option is to download the file and then send it locally. This is what Telebot does if you pass the serverDownload option into sendPhoto.
I am having a problem similar to Botframework findEntity() issue.
I have created a node.js botframework app using the azure interface. I am using the azure ide for development (to keep things simple).
The relevant code is:
// Main dialog with LUIS
var recognizer = new builder.LuisRecognizer(LuisModelUrl);
var intents = new builder.IntentDialog({ recognizers: [recognizer] })
/*
.matches('<yourIntent>')... See details at http://docs.botframework.com/builder/node/guides/understanding-natural-language/
*/
.matches('Help',(session, args) => {
var entities = args.entities;
var itype = builder.EntityRecognizer.findEntity(args.entities, 'ItemTypes');
session.send(args.entities[0]["entity"]);
session.send(args.entities[0]["type"]);
session.send('How may I assist you? ' + JSON.stringify(args));
session.send('Value of entity (didnt match) you said: \'%s\'.', itype);
})
the findEntity function returns null in itype (at least that is what I see in the session.send results.
I tried using both args.entities and args.intents.entities, no change.
When I look at the results of the args.entities[0]["entity"] and [type] I do get values. The results of the JSON.stringify are below (also showing it is finding the entity).
How may I assist you?
{"score":0.970185757,"intent":"Help","intents":[{"intent":"Help","score":0.970185757},{"intent":"Joke","score":0.0711096451},{"intent":"Greeting","score":0.0438234434},{"intent":"None","score":0.0408537947},{"intent":"Goodbye","score":0.04074517}],"entities":[{"entity":"stapler","type":"ItemTypes","
I'm assuming there is more but that it was cut off by the chat window.
I'm new to every technology involved and will take any help I can get.
I've been reading so much a bout node js lately, and the chat capabilities seem very nice. However, the only chat examples I've seen basically broadcast a chat server to a fixed URL (like a meeting room). Is it possible to use node js in part to create a chat client more like gchat? - where a chat window is popped up on the current page and then persists through multiple pages. Has anyone seen an example of this yet?
If not, suggestions for other technologies to use for this purpose (I know that's been answered in other questions)?
Thanks.
I'll give you a pseudo implementation relying on jquery and now to abstract away tedious IO and tedious DOM manipulation from the solution.
// Server
var nowjs = require('now');
var everyone = nowjs.initialize(httpServer);
everyone.now.joinRoom = function(room) {
nowjs.getGroup(room).addUser(this.user.clientId);
}
everyone.now.leaveRoom = function(room) {
nowjs.getGroup(room).removeUser(this.user.clientId);
}
everyone.now.messageRoom = function(room, message) {
nowjs.getGroup(room).now.message(message);
}
// Client
var currRoom = "";
$(".join").click(function() {
currRoom = ...
now.joinRoom(currRoom);
});
$(".send").click(function() {
var input = ...
now.messageRoom(currRoom, input.text());
});
now.messageRoom = function(message) {
$("messages").append($("<div></div>").text(message));
};
I only just noticed myself that the new version of nowjs (0.5) has the group system in build. This basically does what you want for you. No hassle.
If you want you can remove the nowjs dependency and replace it with 100/200 lines of code. I'll leave that as an exercise for the user.
Take a look at AjaxIM: https://github.com/freq32/AjaxIM
This is a facebook-style chat application (think friends list, small persistent chat bar at the bottom of the screen, popup chats) based on nodejs.