回覆關鍵詞的無限擴充套件機制

三人行工作室發表於2019-08-07

引言

在微信公眾號的開發中,自動回覆關鍵詞主要可回覆的內容為文字訊息、圖文訊息(目前僅支援一個連結)。為了讓關鍵詞支援“帶引數” 和 無限擴充套件,本文引入一個對接關鍵詞的介面規範,使得關鍵詞可以攜引數一起交由第三方處理,並返回使用者文字訊息或圖文訊息。

基本原理:為關鍵詞配置回撥地址,關鍵詞與引數使用空格分隔,第一個空格後邊的均為引數,公眾號在接收到使用者文字訊息後,解析關鍵詞與引數,並根據配置將其傳送請求給回撥地址,獲取返回的處理結果。

本文主要介紹介面的定義,並提供一個具體的介面實現。

1 介面約定

1.1 傳入引數

作為 Request.Body 請求體 POST 給回撥地址。

{
    "keyword" : "Keyword",
    "parameter" : "Parameters string",
    "user" : "useropenid"
}

1.2 返回格式

返回結果為 JSON 形式,要求必須有 err_code 與 err_msg 屬性,其中 err_code 為狀態碼,狀態碼為 200 時,表示成功,其它表示失敗。err_msg 表示訊息描述。如:

{
    "err_code" : 101,
    "err_msg" : "操作失敗!"
}

當成功時,支援返回“文字”與“連結”兩種型別的訊息。
使用 key_type 屬性表示,可取值“文字”或"連結"。
當 key_type 為“文字”的時候,data 為相應的文字內容。
當 key_type 為“連結”的時候,data 為連結資訊的陣列,只是目前只支援一個連結。
連結的屬性包括:
title : 標題
icon : 圖示
note_desc : 描述
url : 連結地址

1.3 文字型別示例

{
    "err_code" : 101,
    "err_msg" : "操作失敗!",
    "key_type" : "文字",
    "data" : "回覆的內容"
}

1.4 連結型別示例

{
    "err_code" : 101,
    "err_msg" : "操作失敗!",
    "key_type" : "連結",
    "data" : [
        {
            "title" : "一個數學公式",
            "icon" : "http://****/formula.png",
            "note_desc" : "一個神寄的數學公式",
            "url" : "http://****"
        }
    ]
}

2 關鍵詞介面示例

以下為一個完整的介面實現示例。

2.1 功能需求描述

關鍵詞:提取
引數:一段文字或僅是一個 url
功能描述:從文字中提取出郵箱、手機號、身份證號、IPv4 地址(可進一步補充與完善)。如果引數僅是一個 url,則進行提取的文字為請求該 url 所得的內容。

2.2 實現過程

流程:是否僅為url -> 是則請求url 得到內容 -> 根據正規表示式提取匹配資料 -> 根據長度返回文字訊息 或是 返回一個可操作介面的連結。
回覆關鍵詞的無限擴充套件機制

2.2.1 準備好匹配的正規表示式
private static Dictionary<string, string> _RegexDict;
public static Dictionary<string, string> RegexDict
{
    get
    {
        if (_RegexDict == null)
        {
            _RegexDict = new Dictionary<string, string>();
            // _RegexDict.Add("連結", @"((ht)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?"); 
            _RegexDict.Add("郵箱", @"[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+");
            _RegexDict.Add("手機號", @"(((13[0-9]{1})|(14[0-9]{1})|(15[0-9]{1})|(17[0-9]{1})|(18[0-9]{1})|(19[0-9]{1}))+\d{8})");
            _RegexDict.Add("身份證號", @"[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]");
            _RegexDict.Add("IPv4地址", @"(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])");
        }
        return _RegexDict;
    }
}
2.2.2 處理過程

一個工具方法,請求 url 獲取內容。

public static string GetUrlContent(string url)
{
    System.Net.WebClient webClientObj = new System.Net.WebClient();
    webClientObj.Encoding = Encoding.UTF8;
    string respInfo = webClientObj.DownloadString(url);
    return respInfo;
}

處理流程實現,建立一個 WebApi,程式碼如是說。

public JObject Index([FromBody] JObject body)
{
    string keyword = body.Value<string>("keyword");
    string parameter = body.Value<string>("parameter");
    string user = body.Value<string>("user");
    JObject result = new JObject();
    if (!"提取".Equals(keyword))
    {
        result["err_code"] = 101;
        result["err_msg"] = "關鍵詞未找到";
        return result;
    }

    //// 處理過程 
    var content = parameter;
    var regUrl = @"^((ht)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$";
  
    // (1) 為網址嗎
    if (Regex.IsMatch(content, regUrl))
    {
        try
        {
            content = GetUrlContent(content);
        }
        catch (Exception ue)
        {
            result["err_code"] = 101;
            result["err_msg"] = "站點無法連線!";
            return result;
        }
    }
             
    //(2)根據正規表示式提取
    Dictionary<string, List<string>> typeMatches = new Dictionary<string, List<string>>();
    foreach (var kv in RegexDict)
    {
        List<string> list = new List<string>();
        var mc = Regex.Matches(content, kv.Value, RegexOptions.IgnoreCase);
        foreach (Match c in mc)
        {
            list.Add(c.Value);
        }

        if (list.Count > 0)
        {
            typeMatches.Add(kv.Key, list);
        }
    }


    //(3)拼成字串
    StringBuilder sb = new StringBuilder(1024);
    foreach (var kv in typeMatches)
    {
        sb.Append(kv.Key + "\n" + String.Join("\n", kv.Value) + "\n"); 
    }

    //(4)長度<1020 文字訊息
    if (sb.Length < 1020)
    {
        result["err_code"] = 200;
        result["err_msg"] = "success";
        result["key_type"] = "文字";
        result["data"] = sb.Length == 0 ? "無匹配內容!" : sb.ToString();
        return result;
    }

    //(5)長度較大,返回工具連結
    JObject link = new JObject();
    link["title"] = "提取內容中的格式化資料資訊";
    link["icon"] = "http://www.timeddd.com/Content/images/logo_bar.png";
    link["note_desc"] = "指定連結地址或文字內容,從中提取一些常格式資料,如郵箱、手機號、連結、身份證號等資訊!";
    link["url"] = "http://www.timeddd.com/Tool/Fetch";

    JArray links = new JArray();
    links.Add(link);

    result["err_code"] = 200;
    result["err_msg"] = "success";
    result["key_type"] = "連結";
    result["data"] = links;
    return result;              
}

3 效果

在公眾號“時間維度”中,回覆關鍵詞提取,空格帶上內容,如下:

提取 各種格式的郵箱入下所示:kevintian126@126.com ,1136667341@qq.com 3. meiya@cn-meiya.com 4. wq901200@hotmail.com 5. meiyahr@163.com 6. meiyuan@0757info.com 7. chingpeplo@sina.com 8. tony@erene.com.com 9. melodylu@buynow.com

會得到以下結果:

郵箱
kevintian126@126.com
1136667341@qq.com
meiya@cn-meiya.com
wq901200@hotmail.com
meiyahr@163.com
meiyuan@0757info.com
chingpeplo@sina.com
tony@erene.com.com
melodylu@buynow.com

回覆:

提取 https://www.nhxz.com/doc/181017fc325d4b598aaede18.html

會得到:

郵箱
kevintian126@126.com
1136667341@qq.com
meiya@cn-meiya.com
wq901200@hotmail.com
meiyahr@163.com
meiyuan@0757info.com
chingpeplo@sina.com
tony@erene.com.com
melodylu@buynow.com
xxxxxx@163.com
123321@126.com
手機號
15758523729
18101710555
18300405945
身份證號
560087183004059455

3 招募關鍵詞

給定一個關鍵詞,一個接收關鍵詞及引數的 URL 地址,按約定的格式返回 JSON,就有可能成為“時間維度”公眾號裡的實用工具供大家使用。如有興趣歡迎在“時間維度”留言。

相關文章