This is a whistle stop tour for adding a method to allow the user to download their transcript.
Automatically record the transcript
You need to add the built-in transcript services. In this example I’ll use the In-Memory store, you’ll want to evaluate the others for production code. Add this to the startup.cs
var memoryTranscriptStore = new MemoryTranscriptStore(); … options.Middleware.Add(new TranscriptLoggerMiddleware(memoryTranscriptStore));
Next we’ll create a component to expose the ITranscriptStore (memoryTranscriptStore) to the dialog context. We’ll do that via our own middleware;
public class TranscriptProvider : IMiddleware { private readonly ITranscriptStore transcriptStore; public TranscriptProvider(ITranscriptStore transcriptStore) { this.transcriptStore = transcriptStore; } public async Task OnTurn(ITurnContext context, MiddlewareSet.NextDelegate next) { context.Services.Add(transcriptStore); await next(); } }
Now add this to the startup middleware;
options.Middleware.Add(new TranscriptProvider(memoryTranscriptStore));
Download the transcript
The middleware will now capture all the activity traffic to and from the bot and user. We can add a simple mechanism to request the transcript file. In your bot’s OnTurn method we can hardcode a ‘Transcript’ message/command;
if (context.Activity.Text.Equals("Transcript", StringComparison.InvariantCultureIgnoreCase)) { var transcriptStore = context.Services.Get(); var transcripts = await transcriptStore.GetTranscriptActivities(context.Activity.ChannelId, context.Activity.Conversation.Id); var transcriptContents = new StringBuilder(); foreach (var transcript in transcripts.Items.Where(i => i.Type == ActivityTypes.Message)) { transcriptContents.AppendLine((transcript.From.Name == "Bot" ? "\t\t" : "") + transcript.AsMessageActivity().Text); } byte[] bytes = StringToBytes(transcriptContents.ToString()); var contentType = "text/plain"; var attachment = new Attachment { Name = "Transcript.txt", ContentUrl = $"data:{contentType};base64,{Convert.ToBase64String(bytes)}", ContentType = contentType }; var activity = MessageFactory.Attachment(attachment); await context.SendActivity(activity); return; } ... private byte[] StringToBytes(string transcriptToSend) { byte[] bytes = new byte[transcriptToSend.Length * sizeof(char)]; System.Buffer.BlockCopy(transcriptToSend.ToCharArray(), 0, bytes, 0, bytes.Length); return bytes; }
When your user types in ‘Transcript’ they’ll be provided with a download attachment called ‘Transcript.txt’.
Production Ready
The above code is great for early testing but you should probably consider using the Download Activity Type and providing a URL to the full transcript. The above code has a nasty weakness in that it must fit inside the maximum reply payload for the bot, ~94K. You could just truncate the body but I’ll leave that up to you. Note, as of writing the emulator has an issue where it will allow you to click on the download but then it gets into a pickle and launches Windows Store. If you try this on a webchat it works fine.