Add Dun Check
This commit is contained in:
parent
e611b519ab
commit
fc9588fb63
|
@ -0,0 +1,50 @@
|
|||
module DunCheckAble
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
validate :check_text_able
|
||||
end
|
||||
|
||||
def check_text_able
|
||||
dun_check_params = get_model
|
||||
if dun_check_params[:is_change]
|
||||
dun_check_params.delete(:is_change)
|
||||
check_result = DunCheck::TextCheck.new(dun_check_params).call
|
||||
if check_result[:status].to_i == -1
|
||||
errors.add(:base, "内容含有:#{check_result[:extra_params][:infos]},请修改")
|
||||
# raise ActiveRecord::RecordInvalid.new(self)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def get_model
|
||||
dun_model = self.class.name
|
||||
case dun_model
|
||||
when "Issue"
|
||||
check_params = {
|
||||
title: self.subject,
|
||||
content: self.description,
|
||||
is_change: (self.subject_changed? || self.description_changed?) && self.subject.present? && self.description.present?
|
||||
}
|
||||
when "PullRequest"
|
||||
check_params = {
|
||||
title: "",
|
||||
content: self.body,
|
||||
is_change: self.body_changed? && self.body.present?
|
||||
}
|
||||
when "Journal"
|
||||
check_params = {
|
||||
title: "",
|
||||
content: self.notes,
|
||||
is_change: self.notes_changed? && self.notes.present?
|
||||
}
|
||||
when "Version"
|
||||
check_params = {
|
||||
title: self.name,
|
||||
content: self.description,
|
||||
is_change: (self.name_changed? || self.description_changed?) && self.name.present? && self.description.present?
|
||||
}
|
||||
end
|
||||
return check_params
|
||||
end
|
||||
end
|
|
@ -0,0 +1,34 @@
|
|||
module DunCheckImageAble
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
def self.check_image_able(file)
|
||||
|
||||
original_filename = file.original_filename
|
||||
file_extention = original_filename.split(".").last
|
||||
check_include = %w(jpg png bmp gif webp tiff jpeg)
|
||||
|
||||
if file_extention && check_include.include?(file_extention)
|
||||
base64_file = Base64.encode64(file.open.read.force_encoding(Encoding::UTF_8))
|
||||
check_params = [
|
||||
{
|
||||
name: original_filename,
|
||||
type: 2,
|
||||
data: base64_file,
|
||||
}
|
||||
]
|
||||
check_result = DunCheck::ImageCheck.new(check_params).call
|
||||
if check_result[:status].to_i == -1
|
||||
return {status: -1, message: check_result[:message]}
|
||||
else
|
||||
return {status: 1}
|
||||
end
|
||||
else
|
||||
return {status: 1}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
|
@ -1,5 +1,6 @@
|
|||
class Issue < ApplicationRecord
|
||||
#issue_type 1为普通,2为悬赏
|
||||
include DunCheckAble
|
||||
belongs_to :project, :counter_cache => true
|
||||
belongs_to :tracker,optional: true
|
||||
has_many :project_trends, as: :trend, dependent: :destroy
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
class Journal < ApplicationRecord
|
||||
include DunCheckAble
|
||||
belongs_to :user
|
||||
belongs_to :issue, foreign_key: :journalized_id, :touch => true
|
||||
has_many :journal_details, :dependent => :delete_all
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
class PullRequest < ApplicationRecord
|
||||
#status 0 默认未合并, 1表示合并, 2表示请求拒绝
|
||||
include DunCheckAble
|
||||
belongs_to :issue
|
||||
belongs_to :user
|
||||
belongs_to :project, :counter_cache => true
|
||||
|
|
|
@ -0,0 +1,167 @@
|
|||
class DunCheck::ImageCheck
|
||||
|
||||
#检测结果,0:通过,1:嫌疑,2:不通过
|
||||
# include ActionView::Helpers::LoopTextsHelper
|
||||
|
||||
require 'uri'
|
||||
require 'net/http'
|
||||
|
||||
def initialize(image_params)
|
||||
@image_params = image_params
|
||||
end
|
||||
|
||||
def call
|
||||
begin
|
||||
Rails.logger.info("==========@image_params===========#{@image_params}")
|
||||
dun_params = check_dun_params(@image_params)
|
||||
|
||||
api_url = Redmine::Configuration['dun']['image_api']
|
||||
|
||||
uri = URI.parse(api_url)
|
||||
|
||||
http = Net::HTTP.new(uri.hostname, uri.port)
|
||||
if api_url.include?("https://")
|
||||
http.use_ssl = true
|
||||
end
|
||||
dun_params_str = URI.encode_www_form(dun_params)
|
||||
|
||||
header = {'content-type':'application/x-www-form-urlencoded'}
|
||||
response = http.post(uri.path, dun_params_str, header)
|
||||
|
||||
response_body = JSON.parse(response.body)
|
||||
if response_body["code"].to_i == 200
|
||||
response_body_result = response_body["antispam"]
|
||||
response_lables = response_body_result[0]["labels"]
|
||||
return_sub_lable = ""
|
||||
if response_lables.present?
|
||||
return_sub_lable = get_sub_labels(response_lables)
|
||||
end
|
||||
render_status = response_body_result[0]["action"].to_i == 0 ? 1 : -1
|
||||
tip_status(render_status, return_sub_lable.present? ? "图片含有: #{return_sub_lable}" : response_body["msg"] )
|
||||
else
|
||||
tip_status(-1, response_body["msg"])
|
||||
end
|
||||
rescue Exception => ex
|
||||
Rails.logger.info "*** transaction abored!"
|
||||
Rails.logger.info "*** errors: #{ex.message}"
|
||||
tip_status(-1, "检测失败")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_dun_params(image_params)
|
||||
|
||||
dun_public_params = DunCheck::PublicParams.new("image")
|
||||
check_params = {
|
||||
version: "v4",
|
||||
images: image_params.to_json
|
||||
}
|
||||
check_params.merge!(dun_public_params.call)
|
||||
dun_params = dun_public_params.generate_sign(check_params)
|
||||
|
||||
return dun_params
|
||||
end
|
||||
|
||||
def tip_status(status, message, msg_params={})
|
||||
return {status: status, message: message, extra_params: msg_params}
|
||||
end
|
||||
|
||||
def get_sub_labels(labels)
|
||||
_sub_labels = []
|
||||
labels.each do |label|
|
||||
error_label = label["subLabels"].present? ? label["subLabels"][0]["subLabel"] : ""
|
||||
if error_label.present?
|
||||
_sub_labels.push(sub_lables[:"#{error_label.to_s}"])
|
||||
end
|
||||
end
|
||||
return _sub_labels.present? ? _sub_labels.join(",") : ""
|
||||
end
|
||||
|
||||
def sub_lables
|
||||
{
|
||||
"10000": "色情",
|
||||
"10001": "女下体",
|
||||
"10002": "女胸",
|
||||
"10003": "男下体",
|
||||
"10004": "性行为",
|
||||
"10005": "臀部",
|
||||
"10006": "口交",
|
||||
"10007": "卡通色情",
|
||||
"10008": "色情人物",
|
||||
"10009": "儿童色情",
|
||||
"11000": "性感低俗",
|
||||
"11001": "亲吻",
|
||||
"11002": "腿部特写",
|
||||
"11003": "非漏点赤膊",
|
||||
"11004": "胸部",
|
||||
"100001": "色情文字-色情其他",
|
||||
"100002": "色情文字-色情传播",
|
||||
"100003": "色情文字-色情性器官",
|
||||
"100004": "色情文字-色情挑逗",
|
||||
"100005": "色情文字-色情低俗段子",
|
||||
"100006": "色情文字-色情性行为",
|
||||
"100007": "色情文字-色情舆情事件",
|
||||
"100008": "色情文字-色情交友类",
|
||||
"20000": "广告",
|
||||
"20001": "广告带文字",
|
||||
"200009": "广告文字-商业推广",
|
||||
"200010": "广告文字-广告法",
|
||||
"200011": "刷量行为",
|
||||
"200012": "广告其他",
|
||||
"260052": "广告文字-广告法-涉医疗用语",
|
||||
"260053": "广告文字-广告法-迷信用语",
|
||||
"260054": "广告文字-广告法-需要凭证",
|
||||
"260055": "广告文字-广告法-限时性用语",
|
||||
"260056": "广告文字-广告法-涉嫌诱导消费者",
|
||||
"260057": "广告文字-广告法-涉嫌欺诈消费者",
|
||||
"260058": "广告文字-广告法-法律风险较高",
|
||||
"260059": "广告文字-广告法-极限词",
|
||||
"21000": "二维码",
|
||||
"30000": "暴恐",
|
||||
"30001": "暴恐图集",
|
||||
"30002": "暴恐旗帜",
|
||||
"30003": "暴恐人物",
|
||||
"30004": "暴恐标识",
|
||||
"30005": "暴恐场景",
|
||||
"300016": "暴恐文字-暴恐其他",
|
||||
"40000": "违禁",
|
||||
"40001": "违禁图集",
|
||||
"40002": "违禁品",
|
||||
"40003": "特殊标识",
|
||||
"40004": "血腥模型",
|
||||
"40005": "公职服饰",
|
||||
"40006": "不文明",
|
||||
"40007": "违禁人物",
|
||||
"40008": "违禁场景",
|
||||
"40009": "火焰",
|
||||
"40010": "骷髅",
|
||||
"40011": "货币",
|
||||
"40012": "毒品",
|
||||
"400017": "违禁文字-违禁其他",
|
||||
"600018": "违禁文字-谩骂其他",
|
||||
"50000": "涉政",
|
||||
"50001": "涉政图集",
|
||||
"50002": "中国地图",
|
||||
"50003": "涉政人物",
|
||||
"50004": "涉政旗帜",
|
||||
"50005": "涉政标识",
|
||||
"50006": "涉政场景",
|
||||
"500013": "涉政文字-涉政其他",
|
||||
"500014": "涉政文字-敏感专项",
|
||||
"500015": "涉政文字-严格涉政",
|
||||
"500039": "涉政文字-时事报道",
|
||||
"500040": "涉政文字-领导人相关",
|
||||
"500041": "涉政文字-英雄烈士相关",
|
||||
"500042": "涉政文字-邪教迷信",
|
||||
"500043": "涉政文字-落马官员相关",
|
||||
"500044": "涉政文字-热点舆情",
|
||||
"500045": "涉政文字-涉政综合",
|
||||
"90000": "其他",
|
||||
"90002": "自定义用户名单",
|
||||
"90003": "自定义IP名单",
|
||||
"900020": "文字违规-其他"
|
||||
}
|
||||
end
|
||||
end
|
|
@ -0,0 +1,31 @@
|
|||
class DunCheck::PublicParams
|
||||
def initialize(type)
|
||||
@type = type
|
||||
end
|
||||
|
||||
def call
|
||||
|
||||
public_params = {
|
||||
secretId: Redmine::Configuration['dun']['secretId'],
|
||||
businessId: Redmine::Configuration['dun']["#{@type}_businessId"],
|
||||
timestamp: DateTime.current.strftime('%Q').to_i,
|
||||
nonce: rand(10 ** 11).to_i
|
||||
}
|
||||
return public_params
|
||||
end
|
||||
|
||||
def generate_sign(params)
|
||||
secretkey = Redmine::Configuration['dun']['secretKey']
|
||||
sort_params = params.sort.to_h
|
||||
sign_str = ""
|
||||
sort_params.each do |k,v|
|
||||
sign_str += "#{k.to_s}#{v.to_s}"
|
||||
end
|
||||
sign_str += secretkey
|
||||
md5_sign = Digest::MD5.hexdigest(sign_str.to_s.force_encoding("UTF-8"))
|
||||
return sort_params.merge!(signature: md5_sign)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
class DunCheck::TextCheck
|
||||
|
||||
# include DunCheck::PublicParams
|
||||
#text_params = {
|
||||
# content: "ccc", #内容
|
||||
# ip: "xxx", #用户ip
|
||||
# account: "xxx", #登录login
|
||||
# nickname: "xxx", #用户姓名
|
||||
# title: "xxx", #帖子的标题
|
||||
# }
|
||||
|
||||
#检测结果,0:通过,1:嫌疑,2:不通过
|
||||
# include ActionView::Helpers::LoopTextsHelper
|
||||
|
||||
require 'uri'
|
||||
require 'net/http'
|
||||
|
||||
def initialize(text_params)
|
||||
@text_params = text_params
|
||||
end
|
||||
|
||||
def call
|
||||
new_text_params = @text_params
|
||||
text_long_array = []
|
||||
check_content = new_text_params[:content]
|
||||
format_text(check_content,text_long_array)
|
||||
(1..text_long_array.size).each do |i|
|
||||
new_text_params.merge!(content: text_long_array[i-1])
|
||||
check_result = check_text(new_text_params)
|
||||
if check_result[:status].to_i == -1
|
||||
return check_result
|
||||
break
|
||||
else
|
||||
if i == text_long_array.size
|
||||
return check_result
|
||||
else
|
||||
next
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def check_text(text_params)
|
||||
begin
|
||||
dun_params = check_dun_params(text_params)
|
||||
|
||||
api_url = Redmine::Configuration['dun']['text_api']
|
||||
|
||||
uri = URI.parse(api_url)
|
||||
|
||||
http = Net::HTTP.new(uri.hostname, uri.port)
|
||||
if api_url.include?("https://")
|
||||
http.use_ssl = true
|
||||
end
|
||||
dun_params_str = URI.encode_www_form(dun_params)
|
||||
header = {'content-type':'application/x-www-form-urlencoded'}
|
||||
response = http.post(uri.path, dun_params_str, header)
|
||||
response_body = eval(response.body)
|
||||
Rails.logger.info("======response========#{response_body}")
|
||||
|
||||
if response_body[:code].to_i == 200
|
||||
response_body_result = response_body[:result]
|
||||
response_body_labels = response_body_result[:labels].present? ? response_body_result[:labels][0] : []
|
||||
extra_params = {
|
||||
action: response_body_result[:action],
|
||||
taskId: response_body_result[:taskId],
|
||||
infos: response_body_labels.present? ? sub_lables[:"#{response_body_labels[:subLabels][0][:subLabel]}"] : ""
|
||||
}
|
||||
render_status = response_body_result[:action].to_i == 0 ? 1 : -1
|
||||
tip_status(render_status, response_body[:msg], extra_params)
|
||||
else
|
||||
tip_status(-1, response_body[:msg])
|
||||
end
|
||||
rescue Exception => ex
|
||||
Rails.logger.info "*** transaction abored!"
|
||||
Rails.logger.info "*** errors: #{ex.message}"
|
||||
tip_status(-1, "检测失败")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_dun_params(text_params)
|
||||
dun_public_params = DunCheck::PublicParams.new("text")
|
||||
rand_data_id = random_dataId
|
||||
check_params = {
|
||||
dataId: rand_data_id,
|
||||
version: "v3.1",
|
||||
callback: rand_data_id
|
||||
}.merge(text_params)
|
||||
|
||||
check_params.merge!(dun_public_params.call)
|
||||
dun_params = dun_public_params.generate_sign(check_params)
|
||||
return dun_params
|
||||
end
|
||||
|
||||
def format_text(text_long, text_long_array)
|
||||
slice_content = text_long.slice(0..4998)
|
||||
last_slice_content = text_long.slice(4999..-1)
|
||||
text_long_array.push(slice_content)
|
||||
if last_slice_content.present?
|
||||
if last_slice_content.length > 4999
|
||||
format_text(last_slice_content, text_long_array)
|
||||
else
|
||||
text_long_array.push(last_slice_content)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def random_dataId
|
||||
Digest::MD5.hexdigest(rand(100000000).to_s)
|
||||
end
|
||||
|
||||
def check_labels
|
||||
# 100:色情,200:广告,260:广告法,300:暴恐,400:违禁,500:涉政,600:谩骂,700:灌水
|
||||
%w(100 200 260 300 400 500 600 700).join(",")
|
||||
end
|
||||
|
||||
def tip_status(status, message, msg_params={})
|
||||
return {status: status, message: message, extra_params: msg_params}
|
||||
end
|
||||
|
||||
def sub_lables
|
||||
{
|
||||
"100001": "色情其他",
|
||||
"100002": "色情传播",
|
||||
"100003": "色情性器官",
|
||||
"100004": "色情挑逗",
|
||||
"100005": "色情低俗段子",
|
||||
"100006": "色情性行为",
|
||||
"100007": "色情舆情事件",
|
||||
"100008": "色情交友类",
|
||||
"200009": "商业推广",
|
||||
"200010": "广告法",
|
||||
"200011": "刷量行为",
|
||||
"200012": "广告其他",
|
||||
"260052": "广告法-涉医疗用语(非药品禁止宣传药效)",
|
||||
"260053": "广告法-迷信用语",
|
||||
"260054": "广告法-需要凭证(可以写但需要凭证证明)",
|
||||
"260055": "广告法-限时性用语(可以写但必须有具体时间)",
|
||||
"260056": "广告法-涉嫌诱导消费者",
|
||||
"260057": "广告法-涉嫌欺诈消费者",
|
||||
"260058": "广告法-法律风险较高",
|
||||
"260059": "广告法-极限词(用语绝对化)",
|
||||
"300016": "暴恐其他",
|
||||
"400017": "违禁其他",
|
||||
"400021": "违禁网监要求",
|
||||
"500013": "涉政其他",
|
||||
"500014": "敏感专项",
|
||||
"500015": "严格涉政",
|
||||
"500039": "时事报道",
|
||||
"500040": "领导人相关",
|
||||
"500041": "英雄烈士相关",
|
||||
"500042": "邪教迷信",
|
||||
"500043": "落马官员相关",
|
||||
"500044": "热点舆情",
|
||||
"500045": "涉政综合",
|
||||
"600018": "谩骂其他",
|
||||
"700019": "灌水其他",
|
||||
"900020": "其他",
|
||||
}
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue