第12 屆iT邦幫忙鐵人賽系列文章 (Day29)

在上一篇我們用 Console App 發送訊息到 Api 的 Server Hub,並呈現在HTML上,今天這篇我們要來結合 chatbot,其實就是在chatbot當成SignalR的client而已,實際效果如下(本篇不會介紹CSS部分):

新增一個 MessageBoard class 來處理留言板發送,這部分可以看這篇

而透過 Line 的 User Id ,我們能取得使用者的大頭照.姓名…等等資訊

    public async Task ReplyAsync(string replyToken)

    {

    var profile = await lineProfileUtility.GetUserProfile(userId);

    var hubClient = new ClientSignalR();

    await hubClient.Initialize("http://localhost:12733/message");

    await hubClient.SendHubMessage("SendMessage", profile.pictureUrl, profile.displayName, message);

    await lineMessageUtility.ReplyMessageAsync(replyToken, "謝謝您,我們已收到留言");

    }

GetUserProfile

    public async Task<UserProfile> GetUserProfile(string userId)

    {

    using (var httpClient = new HttpClient())

    {

    using (var request = new HttpRequestMessage(new HttpMethod("GET"), $"{lineMessageApiBaseUrl}/{userId}"))

    {

    request.Headers.TryAddWithoutValidation("Authorization", $"Bearer {accessToken}");

    var response = await httpClient.SendAsync(request);

    if(response.StatusCode != HttpStatusCode.OK)

    {

    // 這邊未來應該要 log 起來

    throw new Exception("get_profile_error");

    }

    var result = await response.Content.ReadAsStringAsync();

    return JsonConvert.DeserializeObject<UserProfile>(result);

    }

    }

    }

HTML 部分

這邊是用JavaScript去塞DOM,如果用主流框架Angular/Vue/React寫起來應該更簡潔~

    document.addEventListener('DOMContentLoaded', function () {

    // 建立連線

    var connection = new signalR.HubConnectionBuilder()

    .withUrl('/message') //因為是同個網域,要視情況換成完成Server Hub的URL

    .build();

    // 開始連線

    connection.start()

    .then(function () {

    console.log('連線成功...');

    })

    .catch(function (error) {

    console.error(error.message);

    });

    bindConnectionMessage(connection);

    // 呈現資料到Html

    function createMessageEntry(imgUrl, encodedName, encodedMsg) {

    var entry = document.createElement('li');

    var html = '<a href="#"><div><div id="divcss5"><img src="' + imgUrl +'" />';

    html += '<span class="displayName">' + encodedName+'</span>';

    html += '</div></div><p>' + encodedMsg+'</p></a>';

    entry.innerHTML = html;

    console.log(html);

    return entry;

    }

    // 監聽接收訊息事件

    function bindConnectionMessage(connection) {

    connection.on('CallBackMessage', function (imgUrl, displayName, message) {

    if (!message) return;

    var encodedName = displayName;

    var encodedMsg = message.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");

    var messageEntry = createMessageEntry(imgUrl, encodedName, encodedMsg);

    var messageBox = document.getElementById('messages');

    messageBox.appendChild(messageEntry);

    messageBox.scrollTop = messageBox.scrollHeight;

    });

    }

    });

這樣就能完成即時用Line傳送的留言板了,但這個只是Demo,真正的話還是要審核一下訊息,不然把怪怪的訊息發送到大螢幕就不好啦。Azure SignalR Service 已經大大降低做即時通訊的開發門檻,透過這種服務就能去發想更多的應用!

懶人包,本次學到了什麼?