Skip to content

Instantly share code, notes, and snippets.

@yingclin
Last active August 3, 2017 07:30
Show Gist options
  • Select an option

  • Save yingclin/54762ca213cd8a9807555f0a08930543 to your computer and use it in GitHub Desktop.

Select an option

Save yingclin/54762ca213cd8a9807555f0a08930543 to your computer and use it in GitHub Desktop.
以 ASP.NET Web API 實作 LINE Messaging API 範例
namespace LineBotDemo.Controllers
{
[RoutePrefix("echo")]
public class LineMessagesSampleController : ApiController
{
private static readonly ILog Log4netLogger = LogManager.GetLogger(typeof(LineMessagesSampleController));
private LineClient lineClient = new LineClient(ConfigurationManager.AppSettings["ChannelToken"].ToString());
private Logger Logger = new Logger(Log4netLogger);
[Route]
public async Task<HttpResponseMessage> Post(HttpRequestMessage request)
{
if (!await VaridateSignature(request))
return Request.CreateResponse(HttpStatusCode.BadRequest);
var content = await request.Content.ReadAsStringAsync();
Activity activity = JsonConvert.DeserializeObject<Activity>(content);
Logger.Info("request=" + content);
// Line may send multiple events in one message, so need to handle them all.
foreach (Event lineEvent in activity.Events)
{
Profile profile = await lineClient.GetProfile(lineEvent.Source.UserId);
switch (lineEvent.Type)
{
case EventType.Beacon:
Logger.Info("Beacon event");
break;
case EventType.Follow:
Logger.Info("Follow event");
break;
case EventType.Join:
Logger.Info("Join event");
break;
case EventType.Leave:
Logger.Info("Leave event");
break;
case EventType.Message:
Logger.Info("Message event");
Message message = JsonConvert.DeserializeObject<Message>(lineEvent.Message.ToString());
switch (message.Type)
{
case MessageType.Text:
var textMessageReply = await HandleTextMessage(lineEvent);
await Reply(lineEvent, textMessageReply);
break;
case MessageType.Audio:
case MessageType.Image:
case MessageType.Video:
var mediaReplyMessage = await HandleMediaMessage(lineEvent);
await Reply(lineEvent, mediaReplyMessage);
break;
case MessageType.Sticker:
var stickerReplyMessage = await HandleStickerMessage(lineEvent);
await Reply(lineEvent, stickerReplyMessage);
break;
case MessageType.Location:
var locationReplyMessage = await HandleLocationMessage(lineEvent);
await Reply(lineEvent, locationReplyMessage);
break;
}
break;
case EventType.Postback:
Logger.Info("Postback event");
//
var postbackReplyMessage = new TextMessage(lineEvent.Postback.Data);
await Reply(lineEvent, postbackReplyMessage);
break;
case EventType.Unfollow:
Logger.Info("Unfollow event");
break;
}
}
return Request.CreateResponse(HttpStatusCode.OK);
}
private async Task<bool> VaridateSignature(HttpRequestMessage request)
{
var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(ConfigurationManager.AppSettings["ChannelSecret"].ToString()));
var computeHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(await request.Content.ReadAsStringAsync()));
var contentHash = Convert.ToBase64String(computeHash);
var headerHash = Request.Headers.GetValues("X-Line-Signature").First();
return contentHash == headerHash;
}
private async Task<Message> HandleTextMessage(Event lineEvent)
{
var textMessage = JsonConvert.DeserializeObject<TextMessage>(lineEvent.Message.ToString());
Message replyMessage = null;
if (textMessage.Text.ToLower() == "demo")
{
List<TemplateAction> actions = new List<TemplateAction>();
actions.Add(new MessageTemplateAction("Buttons", "buttons"));
actions.Add(new MessageTemplateAction("Confirm", "confirm"));
actions.Add(new MessageTemplateAction("Carousel", "carousel"));
actions.Add(new MessageTemplateAction("Imagemap", "imagemap"));
ButtonsTemplate buttonsTemplate = new ButtonsTemplate(null, "可用功能", "直接選比較快", actions);
replyMessage = new TemplateMessage("Buttons", buttonsTemplate);
}
else if (textMessage.Text.ToLower() == "buttons")
{
List<TemplateAction> actions = new List<TemplateAction>();
actions.Add(new MessageTemplateAction("Message Label", "sample data"));
// text 參數為 null 就不會有 message 在畫面上
actions.Add(new PostbackTemplateAction("Postback Label", "postback data", null));
actions.Add(new UriTemplateAction("Uri Label", "https://github.com/kenakamu"));
ButtonsTemplate buttonsTemplate = new ButtonsTemplate("https://github.com/apple-touch-icon.png", "Sample Title", "Sample Text", actions);
replyMessage = new TemplateMessage("Buttons", buttonsTemplate);
}
else if (textMessage.Text.ToLower() == "confirm")
{
// Actions
List<TemplateAction> actions = new List<TemplateAction>();
actions.Add(new MessageTemplateAction("OK", "ok"));
actions.Add(new MessageTemplateAction("Cancel", "cancel"));
// Template
ConfirmTemplate confirmTemplate = new ConfirmTemplate("Are you sure?", actions);
// Message
replyMessage = new TemplateMessage("Confirm", confirmTemplate);
}
else if (textMessage.Text.ToLower() == "carousel")
{
List<TemplateColumn> columns = new List<TemplateColumn>();
List<TemplateAction> actions = new List<TemplateAction>();
actions.Add(new MessageTemplateAction("Message Label", "sample data"));
// text 內容為 "postback text", 可以和 buttons 的 Postback action 做比較
actions.Add(new PostbackTemplateAction("Postback Label", "postback data", "postback text"));
actions.Add(new UriTemplateAction("Uri Label", "https://github.com/kenakamu"));
columns.Add(new TemplateColumn() { Title = "Casousel 1 Title", Text = "Casousel 1 Text", ThumbnailImageUrl = "https://github.com/apple-touch-icon.png", Actions = actions });
columns.Add(new TemplateColumn() { Title = "Casousel 2 Title", Text = "Casousel 2 Text", ThumbnailImageUrl = "https://github.com/apple-touch-icon.png", Actions = actions });
CarouselTemplate carouselTemplate = new CarouselTemplate(columns);
replyMessage = new TemplateMessage("Carousel", carouselTemplate);
}
else if (textMessage.Text.ToLower() == "imagemap")
{
// Base URL 圖片路徑請自行定義
var url = HttpContext.Current.Request.Url;
var imageUrl = $"{url.Scheme}://{url.Host}:{url.Port}/images/githubicon";
List<ImageMapAction> actions = new List<ImageMapAction>();
actions.Add(new UriImageMapAction("http://github.com", new ImageMapArea(0, 0, 520, 1040)));
actions.Add(new MessageImageMapAction("I love LINE!", new ImageMapArea(520, 0, 520, 1040)));
replyMessage = new ImageMapMessage(imageUrl, "GitHub", new BaseSize(1040, 1040), actions);
}
else
{
replyMessage = new TextMessage(textMessage.Text);
}
return await Task.FromResult(replyMessage);
}
private async Task<Message> HandleMediaMessage(Event lineEvent)
{
Message message = JsonConvert.DeserializeObject<Message>(lineEvent.Message.ToString());
// Get media from Line server.
Media media = await lineClient.GetContent(message.Id);
// 統一回圖片
Message replyMessage = new ImageMessage("https://github.com/apple-touch-icon.png", "https://github.com/apple-touch-icon.png");
return await Task.FromResult(replyMessage);
}
private async Task<Message> HandleStickerMessage(Event lineEvent)
{
var stickerMessage = JsonConvert.DeserializeObject<StickerMessage>(lineEvent.Message.ToString());
// https://devdocs.line.me/files/sticker_list.pdf
return await Task.FromResult<Message>(new StickerMessage("1", "1"));
}
private async Task<Message> HandleLocationMessage(Event lineEvent)
{
var locationMessage = JsonConvert.DeserializeObject<LocationMessage>(lineEvent.Message.ToString());
var replyMessage = new LocationMessage(
locationMessage.Title,
locationMessage.Address,
locationMessage.Latitude,
locationMessage.Longitude);
return await Task.FromResult(replyMessage);
}
private async Task Reply(Event lineEvent, Message replyMessage)
{
try
{
await lineClient.ReplyToActivityAsync(lineEvent.CreateReply(message: replyMessage));
}
catch
{
await lineClient.PushAsync(lineEvent.CreatePush(message: replyMessage));
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment