in blog-samples/CSharp/BotStateExport/BotStateExport/BotStateExport/Program.cs [80:266]
public static async Task<bool> DoExport(Options opts)
{
IBotDataStore<BotData> targetStore = null;
StreamWriter outputFile = null;
switch (opts.Destination.ToLower())
{
case "cosmos":
if (string.IsNullOrEmpty(opts.CosmosDbKey) || string.IsNullOrEmpty(opts.CosmosDbUrl))
{
Console.WriteLine("Both CosmosDb Key and Url are required in order to copy to a new database");
return false;
}
try
{
targetStore = new Microsoft.Bot.Builder.Azure.DocumentDbBotDataStore(new Uri(opts.CosmosDbUrl), opts.CosmosDbKey);
}
catch (Exception e)
{
Console.WriteLine($"Problem initializing cosmos DB: {e}");
throw;
}
break;
case "file":
if (string.IsNullOrEmpty(opts.FileName))
{
Console.WriteLine("FileName must be specified.");
return false;
}
try
{
outputFile = new StreamWriter(opts.FileName);
}
catch
{
Console.WriteLine($"Error creating output file {opts.FileName}.");
}
outputFile.WriteLine("{\r\n");
break;
case "table":
if (string.IsNullOrEmpty(opts.ConnectionString))
{
Console.WriteLine("ConnectionString must be set for Azure Storage Table");
return false;
}
try
{
targetStore = new Microsoft.Bot.Builder.Azure.TableBotDataStore(opts.ConnectionString);
}
catch (Exception e)
{
Console.WriteLine($"Problem initializing Azure Storage Table: {e}");
throw;
}
break;
default:
Console.WriteLine($"undefined destination type: {opts.Destination}");
break;
}
if (opts.Destination.ToLower() == "cosmos")
{
if (string.IsNullOrEmpty(opts.CosmosDbKey) || string.IsNullOrEmpty(opts.CosmosDbUrl))
{
Console.WriteLine("Both CosmosDb Key and Url are required in order to copy to a new database");
return false;
}
try
{
targetStore = new Microsoft.Bot.Builder.Azure.DocumentDbBotDataStore(new Uri(opts.CosmosDbUrl), opts.CosmosDbKey);
}
catch (Exception e)
{
Console.WriteLine($"Problem initializing cosmos DB: {e}");
throw;
}
}
else if (opts.Destination.ToLower() == "table")
{
if (string.IsNullOrEmpty(opts.ConnectionString) )
{
Console.WriteLine("ConnectionString must be set for Azure Storage Table");
return false;
}
try
{
targetStore = new Microsoft.Bot.Builder.Azure.TableBotDataStore(opts.ConnectionString);
}
catch (Exception e)
{
Console.WriteLine($"Problem initializing Azure Storage Table: {e}");
throw;
}
}
var credentials = new MicrosoftAppCredentials(opts.AppId, opts.AppPassword);
var botId =opts.BotId;
var stateUrl = new Uri(opts.StateUrl);
var serviceUrl = "https://store.botframework.com";
MicrosoftAppCredentials.TrustServiceUrl(stateUrl.AbsoluteUri);
string continuationToken = "";
var client = new StateClient(stateUrl, credentials);
var state = client.BotState;
BotStateDataResult stateResult = null;
foreach (var channelId in KnownChannelsIds)
{
Console.WriteLine($"***{channelId}***");
continuationToken = "";
do
{
try
{
// should work with "directline", "facebook", or "kik"
stateResult = await BotStateExtensions.ExportBotStateDataAsync(state, channelId, continuationToken).ConfigureAwait(false);
foreach (var datum in stateResult.BotStateData)
{
if ((DateTime.UtcNow - datum.LastModified).HasValue && (DateTime.UtcNow - datum.LastModified).Value.Days < 1)
{
Console.WriteLine($"LastModified: {datum.LastModified}, UsserId: {datum.UserId}");
}
if (datum.Data != "{}")
{
Console.WriteLine($"conversationID: {datum.ConversationId}\tuserId: {datum.UserId}\tdata:{datum.Data}\n");
if (targetStore != null)
{
var cancellationToken = new CancellationToken();
var address = new Microsoft.Bot.Builder.Dialogs.Address(botId, channelId, datum.UserId, datum.ConversationId, serviceUrl);
var botStoreType = string.IsNullOrEmpty(datum.ConversationId) ? BotStoreType.BotUserData : BotStoreType.BotPrivateConversationData;
var botData = new BotData
{
Data = datum.Data
};
await targetStore.SaveAsync(address, botStoreType, botData, cancellationToken);
}
else if (outputFile != null)
{
var id = new StringBuilder();
id.Append($"{channelId}:");
if (!string.IsNullOrEmpty(datum.ConversationId))
{
id.Append($"private{datum.ConversationId}:");
}
id.Append(datum.UserId);
var serializedData = JsonConvert.SerializeObject(datum.Data);
var outputValue = $"\t{{\r\n\t\"id\": \"{id.ToString()}\",\r\n" +
$"\t\t\"botId\": \"{botId}\",\r\n" +
$"\t\t\"channelId\": \"{channelId}\",\r\n" +
$"\t\t\"conversationId\": \"{datum.ConversationId}\",\r\n" +
$"\t\t\"userId\": \"{datum.UserId}\",\r\n" +
$"\t\t\"data\": {serializedData}\r\n\t}},\r\n";
outputFile.Write(outputValue);
}
}
}
continuationToken = stateResult.ContinuationToken;
}
catch (Exception e)
{
var errorException = e as ErrorResponseException;
if (errorException?.Body?.Error?.Message?.ToLower() == "channel not configured for bot")
{
continue;
}
Console.WriteLine(e);
}
} while (!string.IsNullOrEmpty(continuationToken));
}
Console.Write("Press Enter key to continue:");
Console.Read();
if (outputFile != null)
{
outputFile.WriteLine("}\r\n");
outputFile.Flush();
outputFile.Close();
}
// TODO: Do I need to flush the targetStore? If so, what Address should I use?
return true;
}