diff --git a/README.md b/README.md index f88d3f820ebc7636ce57414f2e262da6b45deb11..2d2a998dfb16fc87555ed89e40d8cff33204850c 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ | ---------- | ------------------------------------------------------------ | | 中文名称 | 腾讯云文本内容安全(TMS)插件 | | 英文名称 | tencentcloud-tms | -| 最新版本 | v1.0.1 (2020.12.11) | +| 最新版本 | v1.0.2 (2021.4.28) | | 适用平台 | [WordPress](https://wordpress.org/) | | 适用产品 | [腾讯云文本内容安全(SMS)](https://cloud.tencent.com/product/tms) | | 文档中心 | [春雨文档中心](https://openapp.qq.com/docs/Wordpress/tms.html) | @@ -42,6 +42,10 @@  >对发文章/评论的场景中提交的文字内容进行检测,检测不通过将会提示如上信息 + +>配置敏感词白名单,发文章/评论时将绕过白名单中的关键词检测 + + ### 4.2. 名词解释 - **自定义密钥:** 插件提供统一密钥管理,既可在多个腾讯云插件之间共享SecretId和SecretKey,也可为插件配置单独定义的腾讯云密钥。 - **Secret ID:** 在[腾讯云API密钥管理](https://console.cloud.tencent.com/cam/capi)上申请的标识身份的 SecretId。 @@ -63,6 +67,9 @@ > 暂无 ## 7.GitHub版本迭代记录 +### 2021.04.28 tencentcloud-wordpress-plugin-tms v1.0.2 +- 新增敏感词白名单功能和敏感词命中记录功能 + ### 2020.12.11 tencentcloud-wordpress-plugin-tms v1.0.1 - 支持在windows环境下运行 diff --git a/images/tms3.png b/images/tms3.png new file mode 100644 index 0000000000000000000000000000000000000000..7e4123e5072bd406aa9aba9f123b708c46537528 Binary files /dev/null and b/images/tms3.png differ diff --git a/images/tms4.png b/images/tms4.png new file mode 100644 index 0000000000000000000000000000000000000000..51c257d7bdd02c41c15c81e9e6e187fd0d584228 Binary files /dev/null and b/images/tms4.png differ diff --git a/tencentcloud-tms/TencentWordpressTMSActions.php b/tencentcloud-tms/TencentWordpressTMSActions.php index 2b9c5ff566d741f9df9884b5cbbda80a4563d83c..03111a0bad2d588d566ddc794cb731cb9e8e30ea 100644 --- a/tencentcloud-tms/TencentWordpressTMSActions.php +++ b/tencentcloud-tms/TencentWordpressTMSActions.php @@ -30,13 +30,16 @@ use TencentWordpressPluginsSettingActions; class TencentWordpressTMSActions { - const PLUGIN_TYPE ='tms'; + const PLUGIN_TYPE = 'tms'; + const WHITELIST_TABLE_NAME = 'tencent_wordpress_tms_keyword_records'; + /** * 插件初始化 */ public static function initPlugin() { static::addToPluginCenter(); + static::createTMSWhitelistTable(); self::requirePluginCenterClass(); TencentWordpressPluginsSettingActions::setWordPressSiteID(); $staticData = self::getTencentCloudWordPressStaticData('activate'); @@ -60,7 +63,8 @@ class TencentWordpressTMSActions public static function uninstallPlugin() { self::requirePluginCenterClass(); - delete_option( TENCENT_WORDPRESS_TMS_OPTIONS); + delete_option(TENCENT_WORDPRESS_TMS_OPTIONS); + self::deleteTMSWhitelistTable(); TencentWordpressPluginsSettingActions::deleteTencentWordpressPlugin(TENCENT_WORDPRESS_TMS_SHOW_NAME); $staticData = self::getTencentCloudWordPressStaticData('uninstall'); TencentWordpressPluginsSettingActions::sendUserExperienceInfo($staticData); @@ -92,6 +96,43 @@ class TencentWordpressTMSActions TencentWordpressPluginsSettingActions::prepareTencentWordressPluginsDB($plugin); } + /** + * 创建敏感词命中记录表 + * @return bool + */ + public static function createTMSWhitelistTable() + { + $wpdb = $GLOBALS['wpdb']; + $tableName = $wpdb->prefix . self::WHITELIST_TABLE_NAME; + if ($wpdb->get_var("SHOW TABLES LIKE '{$tableName}'") !== $tableName) { + $sql = "CREATE TABLE IF NOT EXISTS `{$tableName}` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `user_login` varchar(100) NOT NULL DEFAULT '', + `user_nicename` varchar(100) NOT NULL DEFAULT '', + `user_email` varchar(32) NOT NULL DEFAULT '', + `user_role` varchar(32) NOT NULL DEFAULT '', + `type` varchar(10) NOT NULL DEFAULT '', + `content` text NOT NULL DEFAULT '', + `post_title` varchar(50) NOT NULL DEFAULT '', + `evil_label` varchar(20) NOT NULL DEFAULT '', + `create_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"; + require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); + dbDelta($sql); + } + return true; + } + + public static function deleteTMSWhitelistTable() + { + $wpdb = $GLOBALS['wpdb']; + $tableName = $wpdb->prefix . self::WHITELIST_TABLE_NAME; + if ($wpdb->get_var("SHOW TABLES LIKE '{$tableName}'") === $tableName) { + $sql = "DROP TABLE {$tableName};"; + $wpdb->query($sql); + } + } public static function getTencentCloudWordPressStaticData($action) { @@ -103,19 +144,18 @@ class TencentWordpressTMSActions $staticData['data']['site_app'] = TencentWordpressPluginsSettingActions::getWordPressSiteApp(); $TMSOptions = self::getTMSOptionsObject(); $staticData['data']['uin'] = TencentWordpressPluginsSettingActions::getUserUinBySecret($TMSOptions->getSecretID(), $TMSOptions->getSecretKey()); - $staticData['data']['cust_sec_on'] = $TMSOptions->getCustomKey() === $TMSOptions::CUSTOM_KEY ?1:2; + $staticData['data']['cust_sec_on'] = $TMSOptions->getCustomKey() === $TMSOptions::CUSTOM_KEY ? 1 : 2; return $staticData; } - /** * 初始化插件中心设置页面 */ public function initCommonSettingPage() { self::requirePluginCenterClass(); - if ( class_exists('TencentWordpressPluginsSettingActions') ) { + if (class_exists('TencentWordpressPluginsSettingActions')) { TencentWordpressPluginsSettingActions::init(); } } @@ -132,13 +172,27 @@ class TencentWordpressTMSActions $TMSOptions = self::getTMSOptionsObject(); $response = $this->textModeration($TMSOptions, $content); //检测接口异常不影响用户提交评论 - if ( !($response instanceof TextModerationResponse) ) { + if (!($response instanceof TextModerationResponse)) { return $content; } - if ( $response->getData()->EvilFlag === 0 || $response->getData()->EvilType === 100 ) { + if ($response->getData()->EvilFlag === 0 || $response->getData()->EvilType === 100) { return $content; } + // 命中记录入库 + $user = wp_get_current_user(); + $user_login = $user->data->user_login; + $user_nicename = $user->data->user_nicename; + $user_email = $user->data->user_email; + $user_role = $user->roles[0]; + $type = 'comment'; + $post_title = $content; + $content = $response->getData()->Keywords[0]; + $evil_label = $response->getData()->EvilLabel; + $create_time = date('Y-m-d H:i:s', time()); + $this->insertTMSKeywordRecord($user_login, $user_nicename, $user_email, + $user_role, $type, $content, $post_title, $evil_label, $create_time); + $error = new WP_Error( 'comment_examined_fail', __('评论检测不通过,包含关键字' . $response->getData()->Keywords[0] . '请修改后重新提交') @@ -156,24 +210,38 @@ class TencentWordpressTMSActions public function examineCommentAfterInsertDatabase($id, $comment) { $TMSOptions = self::getTMSOptionsObject(); - if ( !($comment instanceof WP_Comment) ) { + if (!($comment instanceof WP_Comment)) { return false; } $response = $this->textModeration($TMSOptions, $comment->comment_content); //检测接口异常不影响用户提交评论 - if ( !($response instanceof TextModerationResponse) ) { + if (!($response instanceof TextModerationResponse)) { return false; } - if ( $response->getData()->EvilFlag === 0 || $response->getData()->EvilType === 100 ) { + if ($response->getData()->EvilFlag === 0 || $response->getData()->EvilType === 100) { //是否需要人工审核 - if ( $TMSOptions->getAllowOption() === TencentWordpressTMSOptions::ALLOW_TO_PASS ) { + if ($TMSOptions->getAllowOption() === TencentWordpressTMSOptions::ALLOW_TO_PASS) { wp_set_comment_status($id, 'approve'); } return true; } - if ( $TMSOptions->getFailOption() === TencentWordpressTMSOptions::FAIL_TO_TRASH ) { + // 命中记录入库 + $user = wp_get_current_user(); + $user_login = $user->data->user_login; + $user_nicename = $user->data->user_nicename; + $user_email = $user->data->user_email; + $user_role = $user->roles[0]; + $type = 'comment'; + $post_title = $comment; + $content = $response->getData()->Keywords[0]; + $evil_label = $response->getData()->EvilLabel; + $create_time = date('Y-m-d H:i:s', time()); + $this->insertTMSKeywordRecord($user_login, $user_nicename, $user_email, + $user_role, $type, $content, $post_title, $evil_label, $create_time); + + if ($TMSOptions->getFailOption() === TencentWordpressTMSOptions::FAIL_TO_TRASH) { //标记为垃圾评论 wp_spam_comment($id); } else { @@ -191,11 +259,11 @@ class TencentWordpressTMSActions * * @param $post_id * @return string + * @throws Exception */ public function examineCommentWhenSaveArticle($post_id) { - if (!$post_id) - { + if (!$post_id) { $error = new WP_Error( 'comment_examined_fail', __('文章不存在') @@ -203,7 +271,7 @@ class TencentWordpressTMSActions wp_die($error, '文章不存在。', ['back_link' => true]); exit; } - $post = get_post( $post_id ); + $post = get_post($post_id); if (!is_object($post)) { return true; } @@ -218,12 +286,25 @@ class TencentWordpressTMSActions $TMSOptions = self::getTMSOptionsObject(); $response = $this->textModeration($TMSOptions, $content); //检测接口异常不影响用户提交评论 - if ( !($response instanceof TextModerationResponse) ) { + if (!($response instanceof TextModerationResponse)) { return true; } - if ( $response->getData()->EvilFlag === 0 || $response->getData()->EvilType === 100 ) { + if ($response->getData()->EvilFlag === 0 || $response->getData()->EvilType === 100) { return true; } + // 命中记录入库 + $user = wp_get_current_user(); + $user_login = $user->data->user_login; + $user_nicename = $user->data->user_nicename; + $user_email = $user->data->user_email; + $user_role = $user->roles[0]; + $type = 'article'; + $post_title = $post->post_title; + $content = $response->getData()->Keywords[0]; + $evil_label = $response->getData()->EvilLabel; + $create_time = date('Y-m-d H:i:s', time()); + $this->insertTMSKeywordRecord($user_login, $user_nicename, $user_email, + $user_role, $type, $content, $post_title, $evil_label, $create_time); $error = new WP_Error( 'comment_examined_fail', @@ -241,6 +322,11 @@ class TencentWordpressTMSActions */ private function textModeration($TMSOptions, $text) { + $whitelist = self::getTMSOptionsObject()->getWhitelist(); + if ($whitelist !== '') { + $whitelistArr = preg_split("/[;;]+/", $whitelist); + $text = str_replace($whitelistArr, '', $text); + } try { $cred = new Credential($TMSOptions->getSecretID(), $TMSOptions->getSecretKey()); $clientProfile = new ClientProfile(); @@ -254,12 +340,47 @@ class TencentWordpressTMSActions } } + /** + * @param $user_login + * @param $user_nicename + * @param $user_email + * @param $user_role + * @param $type + * @param $content + * @param $post_title + * @param $evil_label + * @param $create_time + * @return mixed + */ + private function insertTMSKeywordRecord($user_login, $user_nicename, $user_email, $user_role, $type, $content, + $post_title, $evil_label, $create_time) + { + $wpdb = $GLOBALS['wpdb']; + $tableName = $this->getWhiteListTableName(self::WHITELIST_TABLE_NAME); + $sql = "INSERT INTO `{$tableName}` (`user_login`, `user_nicename`, `user_email`, `user_role`, `type`, `content`, `post_title`, `evil_label`, `create_time`) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s);"; + return $wpdb->query($wpdb->prepare( + $sql, $user_login, $user_nicename, $user_email, $user_role, $type, $content, $post_title, $evil_label, $create_time + )); + } + + /** + * 获取表名称 + * @param $tableName + * @return string + */ + private function getWhiteListTableName($tableName) + { + $wpdb = $GLOBALS['wpdb']; + return $wpdb->prefix . $tableName; + } + /** * 评论表单 */ public function commentFormTips() { - if ( $GLOBALS['pagenow'] === 'edit-comments.php' ) { + if ($GLOBALS['pagenow'] === 'edit-comments.php') { echo '
get_results($wpdb->prepare($sql)); + //统计总条数 + $sql = "SELECT COUNT(`id`) as `count` FROM `{$tableName}`"; + $count = $wpdb->get_row($wpdb->prepare($sql)); + } else { + $sql = "SELECT * FROM `{$tableName}` WHERE `content` LIKE '%s' ORDER BY `id` DESC LIMIT {$skip},{$pageSize}"; + $result = $wpdb->get_results($wpdb->prepare($sql, '%' . $keyword . '%')); + $sql = "SELECT COUNT(`id`) as `count` FROM `{$tableName}` WHERE `content` LIKE '%s'"; + $count = $wpdb->get_row($wpdb->prepare($sql, '%' . $keyword . '%')); + } + $return = array('list' => $result, 'totalNum' => 0, 'totalPage' => 0, 'hasNext' => false); + if (!$result) { + wp_send_json_success($return); + } + $return['totalNum'] = (int)$count->count; + $return['hasNext'] = $count->count > $pageSize * $page; + $return['totalPage'] = intval(ceil($count->count / $pageSize)); + wp_send_json_success($return); + } + /** * 更新系统讨论设置 * @param TencentWordpressTMSOptions $TMSOptions @@ -366,7 +558,7 @@ class TencentWordpressTMSActions { $commentWhitelist = 0; $commentModeration = 0; - if ( $TMSOptions->getAllowOption() === $TMSOptions::ALLOW_TO_REVIEW ) { + if ($TMSOptions->getAllowOption() === $TMSOptions::ALLOW_TO_REVIEW) { $commentWhitelist = 1; $commentModeration = 1; } @@ -382,7 +574,7 @@ class TencentWordpressTMSActions */ public function pluginSettingPageLinkButton($links, $file) { - if ( $file === TENCENT_WORDPRESS_TMS_BASENAME ) { + if ($file === TENCENT_WORDPRESS_TMS_BASENAME) { $links[] = '设置'; } return $links; @@ -390,6 +582,3 @@ class TencentWordpressTMSActions } - - - diff --git a/tencentcloud-tms/TencentWordpressTMSOptions.php b/tencentcloud-tms/TencentWordpressTMSOptions.php index 62a41ce803064e725284b8e69287bd937569f553..187a13ad53d22b180f5a400e79745308cb0c1973 100644 --- a/tencentcloud-tms/TencentWordpressTMSOptions.php +++ b/tencentcloud-tms/TencentWordpressTMSOptions.php @@ -40,14 +40,17 @@ class TencentWordpressTMSOptions private $allowOption; private $failOption; private $customKey; + private $whitelist = []; - public function __construct($customKey = self::GLOBAL_KEY, $secretID = '', $secretKey = '', $allowOption = self::ALLOW_TO_PASS, $failOption = self::FAIL_TO_FORBID_SUBMISSION) + public function __construct($customKey = self::GLOBAL_KEY, $secretID = '', $secretKey = '', + $allowOption = self::ALLOW_TO_PASS, $failOption = self::FAIL_TO_FORBID_SUBMISSION, $whitelist = '') { $this->customKey = $customKey; $this->secretID = $secretID; $this->secretKey = $secretKey; $this->allowOption = $allowOption; $this->failOption = $failOption; + $this->whitelist = $whitelist; } /** @@ -60,7 +63,7 @@ class TencentWordpressTMSOptions public function setSecretID($secretID) { - if ( empty($secretID) ) { + if (empty($secretID)) { throw new \Exception('secretID不能为空'); } $this->secretID = $secretID; @@ -68,7 +71,7 @@ class TencentWordpressTMSOptions public function setSecretKey($secretKey) { - if ( empty($secretKey) ) { + if (empty($secretKey)) { throw new \Exception('secretKey不能为空'); } $this->secretKey = $secretKey; @@ -76,7 +79,7 @@ class TencentWordpressTMSOptions public function setCustomKey($customKey) { - if ( !in_array($customKey, array(self::GLOBAL_KEY, self::CUSTOM_KEY)) ) { + if (!in_array($customKey, array(self::GLOBAL_KEY, self::CUSTOM_KEY))) { throw new \Exception('自定义密钥传参错误'); } $this->customKey = intval($customKey); @@ -85,7 +88,7 @@ class TencentWordpressTMSOptions public function setAllowOption($allowOption) { - if ( !in_array($allowOption, [self::ALLOW_TO_PASS, self::ALLOW_TO_REVIEW]) ) { + if (!in_array($allowOption, [self::ALLOW_TO_PASS, self::ALLOW_TO_REVIEW])) { throw new \Exception('系统审核通过参数传值错误'); } $this->allowOption = intval($allowOption); @@ -93,17 +96,22 @@ class TencentWordpressTMSOptions public function setFailOption($failOption) { - if ( !in_array($failOption, [self::FAIL_TO_TRASH, self::FAIL_TO_RECYCLE_BIN, self::FAIL_TO_FORBID_SUBMISSION]) + if (!in_array($failOption, [self::FAIL_TO_TRASH, self::FAIL_TO_RECYCLE_BIN, self::FAIL_TO_FORBID_SUBMISSION]) ) { throw new \Exception('系统不审核通过参数传值错误'); } $this->failOption = $failOption; } + public function setWhitelist($whitelist) + { + $this->whitelist = $whitelist; + } + public function getSecretID() { $commonOptions = $this->getCommonOptions(); - if ( $this->customKey === self::GLOBAL_KEY && isset($commonOptions['secret_id']) ) { + if ($this->customKey === self::GLOBAL_KEY && isset($commonOptions['secret_id'])) { $this->secretID = $commonOptions['secret_id'] ?: ''; } return $this->secretID; @@ -112,7 +120,7 @@ class TencentWordpressTMSOptions public function getSecretKey() { $commonOptions = $this->getCommonOptions(); - if ( $this->customKey === self::GLOBAL_KEY && isset($commonOptions['secret_key']) ) { + if ($this->customKey === self::GLOBAL_KEY && isset($commonOptions['secret_key'])) { $this->secretKey = $commonOptions['secret_key'] ?: ''; } return $this->secretKey; @@ -133,4 +141,9 @@ class TencentWordpressTMSOptions return $this->customKey; } + public function getWhitelist() + { + return $this->whitelist; + } + } \ No newline at end of file diff --git a/tencentcloud-tms/TencentWordpressTMSSettingPage.php b/tencentcloud-tms/TencentWordpressTMSSettingPage.php index 9856d325e95bcbbe057b2bc2f4bfdf7c47b87906..c784dfaaac6ec376d64a4343f2b5ee9e7849dd5e 100644 --- a/tencentcloud-tms/TencentWordpressTMSSettingPage.php +++ b/tencentcloud-tms/TencentWordpressTMSSettingPage.php @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + use TencentWordpressTMS\TencentWordpressTMSActions; function TencentWordpressTMSSettingPage() @@ -25,8 +26,9 @@ function TencentWordpressTMSSettingPage() $allowOption = $TMSOptions->getAllowOption(); $failOption = $TMSOptions->getFailOption(); $customKey = $TMSOptions->getCustomKey(); + $whitelist = $TMSOptions->getWhitelist(); $optionsUrl = admin_url('options-discussion.php'); -?> + ?> - +