Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
namespace EpiBot.Models
{
public class ApprovalDecision
{
public string Decision;
public int StepId;
public int ActiveStepIndex;
}
}
using System;
namespace EpiBot.Models
{
public class ApprovalDetail
{
public string ContentUrl;
public string ThumbUrl
{
get
{
if (ContentUrl.Contains("?"))
return ContentUrl + "&w=300";
return ContentUrl + "?w=300";
}
}
public DateTime Started;
public string StartedBy;
public int StepId;
public int ActiveStepIndex;
public int ContentId;
public int WorkId;
}
}
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Web.Compilation;
using EpiBot.Models;
namespace EpiBot.Impl
{
public class ApprovalsRepo
{
private readonly HttpClient _client;
public ApprovalsRepo()
{
_client = new HttpClient();
_client.BaseAddress = new Uri(AppSettingsExpressionBuilder.GetAppSetting("EpiRootUrl").ToString());
_client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
public async Task<IEnumerable<ApprovalDetail>> GetAllApprovals()
{
IEnumerable<ApprovalDetail> allApprovals = null;
HttpResponseMessage response = await _client.GetAsync("api/approvals");
if (response.IsSuccessStatusCode)
{
allApprovals = await response.Content.ReadAsAsync<IEnumerable<ApprovalDetail>>();
}
return allApprovals;
}
public async void SendApprovalDecisionAsync(ApprovalDecision approvalDecision)
{
HttpResponseMessage response = await _client.PostAsJsonAsync("api/approvals", approvalDecision);
response.EnsureSuccessStatusCode();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
using EpiBot.Impl;
using EpiBot.Models;
using Microsoft.Bot.Connector;
namespace EpiBot.Controllers
{
[BotAuthentication]
public class MessagesController : ApiController
{
/// <summary>
/// POST: api/Messages
/// Receive a message from a user and reply to it
/// </summary>
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
var handler = new MessageHandler(activity);
var repo = new ApprovalsRepo();
if (activity.Type == ActivityTypes.Message)
{
ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
if (activity.Text.Contains("Reject"))
{
await handler.HandleReject();
}
else if (activity.Text.Contains("Approve"))
{
await handler.HandleAccept();
}
else
{
// Check for approvals
var allApprovals = await repo.GetAllApprovals();
if (allApprovals == null || !allApprovals.Any())
{
await handler.HandleNothingToDo();
}
await handler.HandleNextApproval(allApprovals.First(), false);
}
}
else if (activity.Type == ActivityTypes.ConversationUpdate)
{
await handler.HandleNewConversation();
}
else
{
HandleSystemMessage(activity, handler);
}
var response = Request.CreateResponse(HttpStatusCode.OK);
return response;
}
private Activity HandleSystemMessage(Activity message, MessageHandler handler)
{
if (message.Type == ActivityTypes.DeleteUserData)
{
// Implement user deletion here
// If we handle user deletion, return a real message
}
else if (message.Type == ActivityTypes.ConversationUpdate)
{
// Handle conversation state changes, like members being added and removed
// Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
// Not available in all channels
}
else if (message.Type == ActivityTypes.ContactRelationUpdate)
{
// Handle add/remove from contact lists
// Activity.From + Activity.Action represent what happened
}
else if (message.Type == ActivityTypes.Typing)
{
// Handle knowing tha the user is typing
}
else if (message.Type == ActivityTypes.Ping)
{
}
return null;
}
}
class MessageHandler
{
private Activity activity;
ConnectorClient connector;
ApprovalsRepo repo;
public MessageHandler(Activity activity)
{
this.activity = activity;
connector = new ConnectorClient(new Uri(activity.ServiceUrl));
repo = new ApprovalsRepo();
}
public async Task HandleAccept()
{
repo.SendApprovalDecisionAsync(GetDecisionData(activity.Text));
Activity reply = activity.CreateReply($"Great news (happy)! It's been accepted.");
await connector.Conversations.ReplyToActivityAsync(reply);
await AnyMoreApprovals();
}
public async Task HandleReject()
{
repo.SendApprovalDecisionAsync(GetDecisionData(activity.Text));
Activity reply = activity.CreateReply($"Aww sorry to hear that (sad), it's been rejected.");
await connector.Conversations.ReplyToActivityAsync(reply);
await AnyMoreApprovals();
}
public async Task HandleNothingToDo()
{
Activity noDataReply = activity.CreateReply($"Great news, there's nothing to do here (happy)!");
await connector.Conversations.ReplyToActivityAsync(noDataReply);
}
public async Task HandleNewConversation()
{
Activity noDataReply = activity.CreateReply($"Hi I'm epibot. You can ask me what Episerver has for you and I can let you know if you have any outstanding content approval requests.");
await connector.Conversations.ReplyToActivityAsync(noDataReply);
}
public async Task HandleNextApproval(ApprovalDetail approval, bool isNext)
{
Activity reply;
if (isNext)
{
reply = activity.CreateReply($"The next item that needs your sign off is this:");
}
else
{
reply = activity.CreateReply($"The first item that needs your sign off is this:");
}
reply.Type = "message";
reply.Attachments = new List<Attachment>();
List<CardImage> cardImages = new List<CardImage>();
cardImages.Add(new CardImage(url: approval.ThumbUrl));
List<CardAction> cardButtons = new List<CardAction>();
// View button
cardButtons.Add(new CardAction()
{
Value = approval.ContentUrl,
Type = "openUrl",
Title = "View"
});
// Approve button
cardButtons.Add(new CardAction()
{
Value = GetDecisionPostBackData("Approve", approval),
Type = "postBack",
Title = "Approve"
});
// Decline button
cardButtons.Add(new CardAction
{
Value = GetDecisionPostBackData("Reject", approval),
Type = "postBack",
Title = "Reject"
});
HeroCard plCard = new HeroCard()
{
Title = "Requested by: " + approval.StartedBy,
Subtitle = "On " + approval.Started.ToString("dd/MM/yyyy HH:MM"),
Images = cardImages,
Buttons = cardButtons
};
Attachment plAttachment = plCard.ToAttachment();
reply.Attachments.Add(plAttachment);
await connector.Conversations.ReplyToActivityAsync(reply);
}
private async Task AnyMoreApprovals()
{
var allApprovals = await repo.GetAllApprovals();
if (allApprovals.Any())
{
Activity moreToDoReply = activity.CreateReply($"Seems it's busy here today, getting the next thing for your attention.");
await connector.Conversations.ReplyToActivityAsync(moreToDoReply);
await HandleNextApproval(allApprovals.First(), true);
}
}
private ApprovalDecision GetDecisionData(string postBackValue)
{
return new ApprovalDecision()
{
Decision = postBackValue.Split('_')[0],
StepId = int.Parse(postBackValue.Split('_')[1]),
ActiveStepIndex = int.Parse(postBackValue.Split('_')[2])
};
}
private string GetDecisionPostBackData(string decision, ApprovalDetail approval)
{
return decision + "_" + approval.StepId + "_" + approval.ActiveStepIndex;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.