第12 屆iT邦幫忙鐵人賽系列文章 (Day10)
在上一篇我們用 Template Message 中的 ImageCarousel 實作輪播後,我們再來練習一篇 Template Message,實作到達婚禮現場的各種交通方式資訊,也是先來看看今天的成果
上一篇有介紹 Action 的 7 種類型,前面幾個操作都是用 MessageAction 來引島使用者,而當點選如何前往時,會直接跳出之前實作的"地址導覽" 的 intent,這就是我們今天會帶到的 postback event
上一篇輪播圖片,這一篇我們來輪播自訂的樣板,CarouselTemplate,一樣繼承 ITemplate 實作
public class CarouselTemplate : ITemplate
{
public CarouselTemplate()
{
}
public CarouselTemplate(List<ColumnMultipleAction> columns)
{
Columns = columns;
}
public string Type => "carousel";
public List<ColumnMultipleAction> Columns { get; set; }
}
可以設定圖片/標題/副標題…等資訊,
ThumbnailImageUrl: 縮圖URL
ImageAspectRatio: 圖片的比例 rectangle(1.51:1) square(1:1)
ImageSize: cover(不適應地方會裁切掉) contain(包含全部圖片)
ImageBackgroundColor: 圖片區塊的背景色 (loading時候會看到)
Title: 標題
Text: 副標題
ImageUrl: 圖片網址
DefaultAction: 預設的Action (這樣就不用一個一個塞進 Actions 裡面)
Actions: 如我們前一篇文章所說的,7種Action
public class ColumnMultipleAction
{
/// <summary>
/// Max width: 1024px
/// Max file size: 1 MB
/// JPEG or PNG
/// </summary>
public string ThumbnailImageUrl { get; set; }
public ImageAspectRatioType ImageAspectRatio { get; set; } = ImageAspectRatioType.rectangle;
public ImageSizeType ImageSize { get; set; } = ImageSizeType.cover;
public string ImageBackgroundColor { get; set; } = "#FFFFFF";
public string Title { get; set; }
public string Text { get; set; }
public string ImageUrl { get; set; }
public Defaultaction DefaultAction { get; set; }
public List<IAction> Actions { get; set; }
}
為了開發方便,陸續可以定義一些 Type
StringEnumConverter 主要是 JSON.NET 的功能,可以在我們從 Enum 轉JSON的時候,轉成字串,而不是該 Enum 的 Index Value
[JsonConverter(typeof(StringEnumConverter))]
public enum ImageAspectRatioType
{
/// <summary>
/// 1.51:1
/// </summary>
rectangle,
/// <summary>
/// 1:1
/// </summary>
square
}
[JsonConverter(typeof(StringEnumConverter))]
public enum ImageSizeType
{
cover,
contain
}
public class Directions : IReplyIntent
{
private readonly LineReplyMessageUtility lineMessageUtility;
private readonly LineProfileUtility lineProfileUtility;
public Directions(LineReplyMessageUtility _lineMessageUtility, LineProfileUtility _lineProfileUtility)
{
lineMessageUtility = _lineMessageUtility;
lineProfileUtility = _lineProfileUtility;
}
public async Task ReplyAsync(string replyToken)
{
var carouselTemplate = new CarouselTemplate();
var columns = new List<ColumnMultipleAction>();
// 輪播兩種 Template, 三種 Action
columns.Add(new ColumnMultipleAction()
{
ThumbnailImageUrl = "https://imgur.com/2u6F3dV.jpg",
Title = "搭乘大眾運輸",
Text = "交通便利好方便~",
Actions = new List<IAction>()
{
new MessageAction("從高鐵"),
new MessageAction("從捷運"),
new MessageAction("從機場")
}
});
columns.Add(new ColumnMultipleAction()
{
ThumbnailImageUrl = "https://imgur.com/FGitN5M.jpg",
Title = "自行開車前往",
Text = "切記酒後不開車~",
Actions = new List<IAction>()
{
new PostbackAction("如何前往", "婚宴地點"),
new MessageAction("停車資訊"),
new MessageAction("開車提醒")
}
});
carouselTemplate.Columns = columns;
await lineMessageUtility.ReplyTemplateMessageAsync(replyToken, carouselTemplate);
}
}
OnMessageAsync
DefaultIntent 增加一個選擇性參數,當有要傳訊息的時候回傳,這樣我們就不用定義到那麼多的 Intent
public class DefaultIntent : IReplyIntent
{
private readonly LineReplyMessageUtility lineMessageUtility;
private readonly LineProfileUtility lineProfileUtility;
private readonly string replyText;
public DefaultIntent(
LineReplyMessageUtility _lineMessageUtility,
LineProfileUtility _lineProfileUtility,
string _replyText = "")
{
lineMessageUtility = _lineMessageUtility;
lineProfileUtility = _lineProfileUtility;
replyText = _replyText;
}
public async Task ReplyAsync(string replyToken)
{
if(!string.IsNullOrEmpty(replyText))
{
await lineMessageUtility.ReplyMessageAsync(replyToken, replyText);
}
else
{
await Task.CompletedTask;
}
}
}
要來擴充 Event 了,OnMessage Event已經不夠我們使用,在如何前往那邊我們有塞一個 Action 叫做 PostbackAction,data 可以帶一些程式要溝通的資料,如果想傳的資料太多甚至你可以傳個JSON字串,在反序列化回來成物件,我這邊帶的是 “婚宴地點” 這個字串,用來判斷我要執行這個 Intent
public class PostbackAction : IAction
{
public PostbackAction(string text, string data, string label = "")
{
Text = text;
Data = data;
Label = string.IsNullOrEmpty(label) ? text : label;
}
public string Data { get; set; }
public string Text { get; set; }
public ActionType Type => ActionType.postback;
public string Label { get; set; }
}
回到 LineBotApp.cs 的 RunAsync
Webhook 所接收的 Event 要多 postback 這個 class
實作 OnUnPostbackAsync
ev.postback.data 即可取得上面給的 data ,本範例是 "婚宴地點"
NOTE:看到這邊,我們開始嗅到第一個壞味道了,Intent開始定義兩邊,且開始多和複雜,沒關係,我們找篇文章來做重構的動作
JOKE:然後也會發現,透過引導的方式,感覺不用 AI 的技術,也能讓 chatbot 有流程對話,我懂你的感覺 (可以開始包裝我大AI時代了)
CarouselTemplate 在傳送的時候最多只能設定10個輪播 (其實太多也不好,很亂)
URL 最大 1000 字元
一定要是 HTTPS 且加密規範 TLS 1.2 以上
檔案大小上限 200 MB
圖片需為 JPEG or PNG
如何用 CarouselTemplate 來發送多張樣本圖片
https://developers.line.biz/en/reference/messaging-api/#carousel
如何用 Postback Event 來帶一些參數
https://developers.line.biz/en/reference/messaging-api/#postback-event
透過 StringEnumConverter 來讓JSON轉換時,將Enum轉成字串,而不是index value
https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Converters_StringEnumConverter.htm
本篇文章同步發佈於我的 Medium 如果這篇文章對你有幫助,就大力追蹤和拍手鼓掌下去吧 !!