[打怪升級]小程式評論回覆和發帖功能實戰(二)

前端智酷方程發表於2019-08-02

封面

這次分享下“發帖功能”,這個功能其實風險蠻大的,特別是對一些敏感言論的控制,如果沒有做好可能導致小程式被封,所以除了必要的人工稽核和巡查以外,我們需要一些微信安全監測API的幫忙,在AI加持下,現在很多大公司對內容和圖片的效率大大提高了。

示例圖

這個DEMO僅是一個流程示例,由於涉及到雲函式和“真”敏感圖,這裡就有文字圖代替。

開發思路圖

發帖的功能只要理清思路,其實並不複雜,利用機器AI做內容審查是關鍵,直接關係到小程式的整體安全。

使用者選擇手機相簿或拍照

let tempImg = 0; //代表已選擇的圖片
wx.chooseImage({
    count: 3 - tempImg.length, //選擇不超過3張照片,去掉當前已經選擇的照片
    sizeType: ['original', 'compressed'],  //獲取原圖或者壓縮圖
    sourceType: ['album', 'camera'],  //獲取圖片來源 相簿、拍照
    success(res) {
        // tempFilePath可以作為img標籤的src屬性顯示圖片
        let tempFilePaths = res.tempFilePaths;
        console.log(tempFilePaths);
        
        //舉例:這裡可以size 來判斷圖片是否大於 1MB,方便後面內容檢查
        if (res.tempFiles[0] && res.tempFiles[0].size > 1024 * 1024) {
            console.log("圖片大於1MB啦")
        }
    }
})
複製程式碼

這裡用到的方法是chooseImage,它可以設定讓使用者選擇手機圖片庫和拍照獲得,需要注意的是考慮到後面要用微信自帶API做圖片安全檢查,圖片大小不能超過1MB,所以需要設定sizeTypecompressed

內容檢查(重點)

由於內容安全對於小程式運營至關重要,稍有不慎就容易導致小程式被封,所以在這塊的校驗除了常規人工檢查外,我們還可以用到微信的內容安全API。

為什麼用微信官方提供的API? 主要有二點:有一定的免費額度,基於企鵝大廠的專業AI檢查。

1、雲函式+雲呼叫

圖示

目錄結構

├─checkContent
│      config.json   //雲呼叫的許可權配置
│      index.js   //雲伺服器node 入口檔案
│      package-lock.json 
│      package.json   // NPM包依賴
│ ...
複製程式碼

為什麼要強調這個? 因為本人一開始在用雲函式+雲呼叫的時候,經常會出現各種不明BUG,很多都是因為目錄裡面少傳檔案,或者少配置。

雲函式內容:

const cloud = require('wx-server-sdk');
cloud.init();
exports.main = async (event, context) => {
    console.log(event.txt);
    const { value, txt } = event;
    try {
        let msgR = false;
        let imageR = false;
        //檢查 文字內容是否違規
        if (txt) {
            msgR = await cloud.openapi.security.msgSecCheck({
                content: txt
            })
        }
        //檢查 圖片內容是否違規
        if (value) {
            imageR = await cloud.openapi.security.imgSecCheck({
                media: {
                    header: { 'Content-Type': 'application/octet-stream' },
                    contentType: 'image/png',
                    value: Buffer.from(value)
                }
            })
        }
        return {
            msgR,   //內容檢查返回值
            imageR   //圖片檢查返回值
        };
    } catch (err) {
        // 錯誤處理
        // err.errCode !== 0
        return err
    }
}
複製程式碼

這裡主要用到security.msgSecChecksecurity.imgSecCheck這2個微信開放雲呼叫方法(需開發者工具版本 >= 1.02.1904090),以往我們還要在伺服器上單獨寫個方法,現在變得十分的方便,直接在雲函式中呼叫即可。

這裡需要重點說2個點

  • 圖片security.imgSecCheck 方法只能接收buffer,所以需要把temp的臨時圖片轉化為buffer的形式傳過去,我們這裡用到 getFileSystemManager 的方法。
  • 如果目錄檔案中沒有config.json,需要自己建一個,並且做一個授權的配置。
{
    "permissions": {
        "openapi": [
            "security.msgSecCheck",
            "security.imgSecCheck"
        ]
    }
}
複製程式碼

2、檢查文字內容安全

wx.cloud.callFunction({
    name: 'checkContent',
    data: {
        txt: "樂於分享,一起進步"
    },
    success(_res) {
        console.log(_res)
    },
    fail(_res) {
        console.log(_res)
    }
})

//返回值參考
{
    "errMsg": "cloud.callFunction:ok",
    "result": {
        "msgR": {
            "errMsg": "openapi.security.msgSecCheck:ok",
            "errCode": 0
        },
        "imageR": false
    },
    "requestID": "77952319-b2b4-11e9-bdc8-525400192d0e"
}
複製程式碼

應用場景舉例:

  • 使用者個人資料違規文字檢測;
  • 媒體新聞類使用者發表文章,評論內容檢測;
  • 遊戲類使用者編輯上傳的素材(如答題類小遊戲使用者上傳的問題及答案)檢測等。 頻率限制:單個 appId 呼叫上限為 4000 次/分鐘,2,000,000 次/天*

通過wx.cloud.callFunction的方法呼叫checkContent的雲函式,檢查一段文字是否含有違法違規內容。

3、檢查圖片內容安全

//獲取 temp臨時圖片檔案的 buffer
wx.getFileSystemManager().readFile({
    filePath: tempImg[0],  //這裡做示例,所以就選取第一張圖片
    success: buffer => {
        console.log(buffer.data)
        //這裡是 雲函式呼叫方法
        wx.cloud.callFunction({
            name: 'checkContent',
            data: {
                value: buffer.data
            },
            success(json) {
                console.log(json.result.imageR)
                if (json.result.imageR.errCode == 87014) {
                    wx.showToast({
                        title: '圖片含有違法違規內容',
                        icon: 'none'
                    });
                    console.log("bad")
                } else {
                    //圖片正常
                }
            }
        })
    }
})

//返回值參考
{
    "errMsg": "cloud.callFunction:ok",
    "result": {
        "msgR": false,
        "imageR": {
            "errMsg": "openapi.security.imgSecCheck:ok",
            "errCode": 0
        }
    },
    "requestID": "c126353c2d-b40b-11e9-81c4d-525400235f2a"
}
複製程式碼

應用場景舉例:

圖片智慧鑑黃:涉及拍照的工具類應用(如美拍,識圖類應用)使用者拍照上傳檢測;電商類商品上架圖片檢測;媒體類使用者文章裡的圖片檢測等; 敏感人臉識別:使用者頭像;媒體類使用者文章裡的圖片檢測;社交類使用者上傳的圖片檢測等。 頻率限制:單個 appId 呼叫上限為 2000 次/分鐘,200,000 次/天*(圖片大小限制:1M)

這裡先要用 getFileSystemManager() 獲取臨時圖片的buffer(這個是重點),然後再通過wx.cloud.callFunction的方法呼叫 checkContent的雲函式中security.imgSecCheck的方法,校驗一張圖片是否含有違法違規內容。

一開始本人除錯的時候,也遇到無法上傳的問題,必須通過檔案管理(getFileSystemManager)獲取buffer後才能上傳檢查圖片,耗費了本人不少debugger時間。

完整程式碼

原本想做個實際的demo(程式碼片段)分享給大家開啟參考的,但是雲函式必須是一個已註冊的APPID,無奈只能貼程式碼。

這裡主要還是提供一個整體思路,希望能幫助大家減少開發成本,更好的解決問題和完成任務 ^_^

html部分:

<!-- pages/post /index.wxml -->
<view class="wrap">
        <view class="title">
                <input placeholder="智酷方程式,樂於分享" maxlength="30"  bindinput="getTitle"/>
        </view>
        <view class="content">
                <textarea auto-focus="true" maxlength="200" bindinput="textareaCtrl" placeholder-style="color:#999;" placeholder="關注公眾號,一起學習,一起進步" />
                <view class='fontNum'>{{content.length}}/200</view>
        </view>
        <view class="chooseImg">
                <block wx:for="{{tempImg}}" wx:for-item="item" wx:key="ids" wx:for-index="index">
                        <view class="chooseImgBox">
                                <image src="{{item}}" />
                                <view data-index="{{index}}" catch:tap="removeImg" class="removeImg"></view>
                        </view>
                </block>
                <!-- 判斷圖片 大於等於3張的時候 取消 更多 -->
                <block wx:if="{{tempImg.length < 3}}">
                        <view class="chooseImgBoxMore" catch:tap="choosePhoto">
                                <view class="arrow"></view>
                        </view>
                </block>
        </view>
        <view class='submit' catch:tap="submitPost">
                <view class='blue'>提交</view>
                <view>取消</view>
        </view>
</view>
複製程式碼

JS部分:

Page({
    /**
     * 頁面的初始資料
     */
    data: {
        titleDetail: "", //帖子title內容
        content: "", //發帖內容
        tempImg: [], //選擇圖片的縮圖,臨時地址
    },

    /**
     * 生命週期函式--監聽頁面載入
     */
    onLoad: function (options) {
        wx.cloud.init();
    },

    /**
     * 生命週期函式--監聽頁面顯示
     */
    onShow: function () {

    },
    /**
     * 檢測輸入字數
     * @param {object} e 
     */
    textareaCtrl: function (e) {
        if (e.detail.value) {
            this.setData({
                content: e.detail.value
            })
        } else {
            this.setData({
                content: ""
            })
        }
    },
    /**
     * 選擇圖片
     */
    choosePhoto() {
        let self = this;
        let tempImg = self.data.tempImg;
        if (tempImg.length > 2) {
            return;
        }
        wx.chooseImage({
            count: 3 - tempImg.length, //選擇不超過3張照片,去掉當前已經選擇的照片
            sizeType: ['original', 'compressed'],
            sourceType: ['album', 'camera'],
            success(res) {
                console.log(res);
                // tempFilePath可以作為img標籤的src屬性顯示圖片
                let tempFilePaths = res.tempFilePaths;
                tempImg = tempImg.concat(tempFilePaths);
                console.log(tempImg);
                self.setData({
                    tempImg
                })

                wx.getFileSystemManager().readFile({
                    filePath: tempImg[0],
                    success: buffer => {
                        console.log(buffer.data)
                        wx.cloud.callFunction({
                            name: 'checkContent',
                            data: {
                                value: buffer.data
                            },
                            success(json) {
                                console.log(JSON.stringify(json))
                                console.log(json.result.imageR)
                                if (json.result.imageR.errCode == 87014) {
                                    wx.showToast({
                                        title: '圖片含有違法違規內容',
                                        icon: 'none'
                                    });
                                    console.log("bad")
                                } else {
                                    //圖片正常
                                }
                            }
                        })
                    }
                })
            },
            fail: err => {
                console.log(err)
            }
        })
    },
    /**
     * 刪除照片
     */
    removeImg(e) {
        let self = this;
        let index = e.currentTarget.dataset.index;
        console.log(e);
        let tempImg = self.data.tempImg;
        tempImg.splice(index, 1);
        self.setData({
            tempImg
        })
    },
    /**
     * 發貼
     */
    submitPost(e) {
        let { titleDetail, content } = this.data;
        wx.cloud.callFunction({
            name: 'checkContent',
            data: {
                txt: content
            },
            success(_res) {
                console.log(JSON.stringify(_res))

                wx.navigateTo({
                    url: "/pages/postimg/result"
                })
            },
            fail(_res) {
                console.log(_res)
            }
        })
    }
})
複製程式碼

往期回顧:
[打怪升級]小程式評論回覆和發貼功能實戰(一)
[填坑手冊]小程式Canvas生成海報(一)
[拆彈時刻]小程式Canvas生成海報(二)
[填坑手冊]小程式目錄結構和component元件使用心得

[打怪升級]小程式評論回覆和發帖功能實戰(二)

[打怪升級]小程式評論回覆和發帖功能實戰(二)

相關文章