azure linebot ocr c# .net core

Azure Function 結合 Line Bot 玩出新花樣

Matt 2019/06/12 17:26:56
220

準備工作:

 

Azure Services

  • Azure Function
  • Blob Storage(或是直接使用 Azure Function 的 Blob 儲存體也可以) blob conn string
  • Cognitive Service: Computer Vision(服務申請/建立有雷,要注意) computer vision data center computer vision keys

 

Line develop backend

  • 請使用 Line 帳號登入 develop 後台管理界面,用來取得幾個重要的參數 channel secret
    access token, hook api
  • 下圖,是本次 demo 的 Linebot QRCode
  • 或是搜尋 @752kqktr

@752kqktr

 

Azure Function 簡介

  • Serverless 雲服務
    • 我們不需要擔心伺服器設定或虛擬機的修補與擴充
  • 使用 Serverless,Azure 可以預先準備資源。它透過事件觸發,Azure 會提供必要運算資源。服務執行時才產生費用,所以我們只需要付出執行期間的費用。
    • 每百萬次執行 NT$6.011,收費相當便宜/公道。當然也可以選擇 Consumption Plan 免費模式(幾乎所有功能都有開放,但使用上會有些限制。且一旦選定付費模式就無法調整)
    • Azure Function Pricing

 

Azure Function 的應用

  • Azure Function 是處理資料、整合系統、使用物聯網 (IoT),以及建置簡單 API 和微服務的絕佳解決方案。
  • 需要排程執行,或大量計算的任何工作
  • Overview
  • 請注意:預設 5 分鐘後沒有任何驅動動靜時,Azure Function 會進入休眠
    • 若選用付費的價格方案,則可以啟用 Always On,延長或阻止 Azure Function 進入休眠
      always on

Azure Function Triggers

azf_triggers

Line Bot 是什麼?

  • 什麼是 Web Hook?
    • 以今天的例子,它是建置在 Azure Function 的 API(此即 Web Hook),負責接受 Line Server POST 進來的訊息(訊息範例如下)。執行 Line 訊息的任何一個動作,都會觸發一個事件送給 Web Hook
    • {"events":[{"type":"message","replyToken":"9b3b1ebbae04424795449febea80ebb1","source":{"userId":"U9b91b518d6888d33993f22……….","type":"user"},"timestamp":1555777816998,"message":{"type":"text","id":"9727800348111","text":"line://app/1566998925-rZDo1ZXB "}}],"destination":"U06d5e57efb11eea8973b89………."}
    • 白話文:當 Line App 發出一則訊息給 Linebot 好友/群組/聊天室時,Line Server 會以 HTTP POST 發出一段如上的 Json 內容給 Web Hook API,之後進入處理流程。分析該 Json 內容,並依據內容的關鍵點進行處置,這個流程就是 Linebot 的行為。
  • Web App Service、Mobile App Service 等服務,也都可以成為 Linebot Web Hook 的載體

Azure Function - Linebot 溝通流程

Azure Function - Linebot 溝通流程

來吧。看程式範例。

---code 1---

    public static class Hook
    {
        ///TODO: using HttpClient like a singleton instance
        private static HttpClient _client = HttpClientFactory.Create();

        [FunctionName("Hook")]
        public static async Task<IActionResult> Run (
#if DEBUG
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
#else
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
#endif
            ExecutionContext context,
            ILogger log)
        {
            var body = await new StreamReader(req.Body).ReadToEndAsync();
            log.LogInformation($"{body}");

            var xline = GetSignature(req, log);
            var signatureVerify = new Signature().Verify(body, xline, out string bodySignature);
            if (!signatureVerify)
            {
                log.LogError($"Body Signature: {bodySignature}\nX-Line-Signature: {xline}\n簽章驗證無效!");
                return new OkObjectResult(new { });
            }

第 4. 行。.Net core 2.0 後開始支援 HttpClientFactory。關於 HttpClient 的作法,文末有一系列參考文章。

第 8~12 行,以 #if 切換組態,方便測試環境測試,及正式環境部署

第 20~25 行,linebot 實作中很重要的簽章檢查。以避免遭人冒用 Web Hook。需 Linebot Secret Key。

 

---code 2---

            var config = new ConfigurationBuilder()
                .SetBasePath(context.FunctionAppDirectory)
                .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
                .AddJsonFile("options.settings.json", optional: true, reloadOnChange: true)
                .AddEnvironmentVariables()
                .Build();

            var settings = config.GetSection("Settings").Get<Settings>();

第 1~8 行,設置設定檔。local.setting.json 是 AZF 預設使用的設定檔,因安全性政策,不允許任何修改(即使本地端修改後測試通過,上傳 Azure 之後會被還原)。但是我們可以利用 .Net core 的特性安插新的自訂設定。

 

---code 3---

            var par = new Parser(body);
            par.Determine();

            var type = par.SourceMsgType.HasValue
                    ? par.SourceMsgType.Value.ToString()
                    : string.Empty;
            switch (type)
            {
                case "text": //MessageTypeEnum.text.ToString():
                    await GoByTextMessage(par);
                    break;

                case "image":
                    await GoByImageMessage(par, settings);
                    break;

                default:
                    break;
            }
            return new OkObjectResult(new { });
        }

說明,Linebot 的主程式片段(因 line 官方並未提供 c# 版 SDK,本範例會使用到我自已實作的 linebot SDK,未完整版,大約有 8、9 成的功能可運作。或者可以考慮使用董大偉老師的 SDK)。範例程式針對「文字」「圖片」訊息反應,其餘忽略。

第 9、10 行,收到文字訊息時,linebot 的回應

第 13、14 行,收到圖片訊息時,會將圖片上傳到 Azure Blob Storage 儲存,再呼叫 Computer Vision: OCR API 識別圖片中的文字,並回傳。

詳細的程式碼請參考這裡

執行範例

demo result

 

 

參考資源

 

 

 

Matt