Last active
August 3, 2017 07:30
-
-
Save yingclin/54762ca213cd8a9807555f0a08930543 to your computer and use it in GitHub Desktop.
以 ASP.NET Web API 實作 LINE Messaging API 範例
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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