censor_bear 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +80 -0
  4. data/Rakefile +18 -0
  5. data/app/assets/config/censor_bear_manifest.js +1 -0
  6. data/app/assets/stylesheets/censor_bear/application.css +15 -0
  7. data/app/assets/stylesheets/censor_bear/logs.css +4 -0
  8. data/app/assets/stylesheets/censor_bear/mod_logs.css +4 -0
  9. data/app/assets/stylesheets/censor_bear/stop_words.css +4 -0
  10. data/app/assets/stylesheets/censor_bear/tailwind.min.css +1 -0
  11. data/app/assets/stylesheets/scaffold.css +80 -0
  12. data/app/controllers/censor_bear/application_controller.rb +9 -0
  13. data/app/controllers/censor_bear/logs_controller.rb +62 -0
  14. data/app/controllers/censor_bear/mod_logs_controller.rb +87 -0
  15. data/app/controllers/censor_bear/stop_words_controller.rb +69 -0
  16. data/app/helpers/censor_bear/application_helper.rb +5 -0
  17. data/app/helpers/censor_bear/logs_helper.rb +4 -0
  18. data/app/helpers/censor_bear/mod_logs_helper.rb +4 -0
  19. data/app/helpers/censor_bear/stop_words_helper.rb +4 -0
  20. data/app/jobs/censor_bear/application_job.rb +4 -0
  21. data/app/mailers/censor_bear/application_mailer.rb +6 -0
  22. data/app/models/censor_bear/application_record.rb +5 -0
  23. data/app/models/censor_bear/log.rb +4 -0
  24. data/app/models/censor_bear/mod_log.rb +50 -0
  25. data/app/models/censor_bear/stop_word.rb +7 -0
  26. data/app/views/censor_bear/logs/_form.html.erb +37 -0
  27. data/app/views/censor_bear/logs/edit.html.erb +6 -0
  28. data/app/views/censor_bear/logs/index.html.erb +35 -0
  29. data/app/views/censor_bear/logs/new.html.erb +5 -0
  30. data/app/views/censor_bear/logs/show.html.erb +24 -0
  31. data/app/views/censor_bear/mod_logs/_form.html.erb +37 -0
  32. data/app/views/censor_bear/mod_logs/edit.html.erb +6 -0
  33. data/app/views/censor_bear/mod_logs/index.html.erb +44 -0
  34. data/app/views/censor_bear/mod_logs/new.html.erb +5 -0
  35. data/app/views/censor_bear/mod_logs/show.html.erb +24 -0
  36. data/app/views/censor_bear/stop_words/_form.html.haml +30 -0
  37. data/app/views/censor_bear/stop_words/_stop_word.html.haml +33 -0
  38. data/app/views/censor_bear/stop_words/destroy.turbo_stream.haml +1 -0
  39. data/app/views/censor_bear/stop_words/edit.html.haml +6 -0
  40. data/app/views/censor_bear/stop_words/index.html.haml +20 -0
  41. data/app/views/censor_bear/stop_words/new.html.haml +5 -0
  42. data/app/views/censor_bear/stop_words/show.html.haml +1 -0
  43. data/app/views/layouts/censor_bear/application.html.haml +18 -0
  44. data/config/cable.yml +9 -0
  45. data/config/initializers/censor_bear.rb +6 -0
  46. data/config/locales/censor_bear.yml +7 -0
  47. data/config/routes.rb +12 -0
  48. data/db/migrate/20211126133758_create_censor_bear_stop_words.rb +16 -0
  49. data/db/migrate/20211129093508_create_censor_bear_logs.rb +12 -0
  50. data/db/migrate/20211129110218_create_censor_bear_mod_logs.rb +18 -0
  51. data/lib/censor_bear/censor.rb +64 -0
  52. data/lib/censor_bear/configuration.rb +12 -0
  53. data/lib/censor_bear/engine.rb +11 -0
  54. data/lib/censor_bear/version.rb +3 -0
  55. data/lib/censor_bear.rb +36 -0
  56. data/lib/tasks/censor_bear_tasks.rake +4 -0
  57. metadata +177 -0
@@ -0,0 +1,33 @@
1
+ = turbo_frame_tag dom_id(stop_word) do
2
+ %div{class: "flex flex-col space-y-2 border rounded-md p-2 mt-2"}
3
+ %div{class: "flex justify-between text-xs"}
4
+ %span{class: "font-bold"}
5
+ = "##{stop_word.id}"
6
+ %span{class: "text-gray-500"}
7
+ = link_to stop_word.created_at, stop_word, data: {turbo: false}
8
+ %div{class: "space-y-0.5"}
9
+ %div{class: "text-xl font-meidum"}= stop_word.key
10
+ %div{class: "flex space-x-2"}
11
+ %div{class: "flex flex-col justify-center border rounded-md p-1"}
12
+ %div{class: "text-center"}=I18n.t("censor_log.action.#{stop_word.ugc}")
13
+ %div{class: "text-gray-500 text-xs text-center"} UGC内容处理
14
+ %div{class: "flex flex-col justify-center border rounded-md p-1"}
15
+ %div{class: "text-center"}=I18n.t("censor_log.action.#{stop_word.username}")
16
+ %div{class: "text-gray-500 text-xs text-center"} 用户名处理
17
+ %div{class: "flex flex-col justify-center border rounded-md p-1"}
18
+ %div{class: "text-center"}=I18n.t("censor_log.action.#{stop_word.nickname}")
19
+ %div{class: "text-gray-500 text-xs text-center"} 用户昵称处理
20
+ %div{class: "flex flex-col justify-center border rounded-md p-1"}
21
+ %div{class: "text-center"}=I18n.t("censor_log.action.#{stop_word.signature}")
22
+ %div{class: "text-gray-500 text-xs text-center"} 签名处理
23
+ %div{class: "flex flex-col justify-center border rounded-md p-1"}
24
+ %div{class: "text-center"}=I18n.t("censor_log.action.#{stop_word.dialog}")
25
+ %div{class: "text-gray-500 text-xs text-center"} 私信处理
26
+ %div{class: "flex flex-col justify-center border rounded-md p-1"}
27
+ %div{class: "text-center"}=stop_word.replacement
28
+ %div{class: "text-gray-500 text-xs text-center"} 过滤词替换
29
+ %div{class: "flex justify-end space-x-2 text-sm text-blue-600"}
30
+ %span
31
+ = link_to '编辑', edit_stop_word_path(stop_word)
32
+ %span
33
+ = button_to '删除', stop_word, method: :delete, data: { confirm: 'Are you sure?' }, class: "cursor-pointer bg-white text-red-600"
@@ -0,0 +1 @@
1
+ = turbo_stream.remove(@stop_word)
@@ -0,0 +1,6 @@
1
+ = turbo_frame_tag dom_id(@stop_word) do
2
+ %div{class: "bg-gray-100 p-2 rounded-lg"}
3
+ %div{class: "flex justify-between"}
4
+ %div{class: "text-lg font-bold"} 编辑
5
+ %div= link_to '返回', stop_words_path, class: "text-gray-500"
6
+ = render 'form', stop_word: @stop_word
@@ -0,0 +1,20 @@
1
+ %div{class: "flex flex-col space-y-2 justify-center"}
2
+ %div{class: "flex justify-between"}
3
+ %div
4
+ = form_with(url: stop_words_path, method: :get, class: "flex items-center") do |f|
5
+ %div{class: "space-x-0.5"}
6
+ = f.text_field :q, value: params[:q], placeholder: "关键词", class: "border rounded-md m py-0.5 px-1"
7
+ = f.submit "检索", class: "rounded-md px-2 py-1 text-sm bg-black text-white cursor-pointer"
8
+ = link_to "重置", stop_words_path, class: "text-sm"
9
+
10
+ %div
11
+ = link_to '批量导入', "#", class: "text-sm"
12
+ = link_to '新增', new_stop_word_path, class: "rounded-md px-2 py-1 text-sm bg-black text-white cursor-pointer"
13
+ %div
14
+ - if @stop_words.blank?
15
+ %div{class: "flex justify-center text-gray-500 p-8 border rounded-md"} 空空如也
16
+ - else
17
+ - @stop_words.each do |stop_word|
18
+ = render stop_word
19
+ %div{class: "flex justify-center"}
20
+ = raw pagy_nav(@pagy)
@@ -0,0 +1,5 @@
1
+ %div{class: "bg-gray-100 p-2 rounded-lg"}
2
+ %div{class: "flex justify-between"}
3
+ %div{class: "text-lg font-bold"} 添加
4
+ %div= link_to '返回', stop_words_path, class: "text-gray-500"
5
+ = render 'form', stop_word: @stop_word
@@ -0,0 +1 @@
1
+ = render @stop_word
@@ -0,0 +1,18 @@
1
+ !!! 5
2
+ %html
3
+ %head
4
+ %title 🐻 内容审核
5
+ = csrf_meta_tags
6
+ = csp_meta_tag
7
+ = stylesheet_link_tag "censor_bear/application", media: "all"
8
+ = javascript_include_tag "turbo", type: "module"
9
+ = yield :head
10
+ %body{class: "flex flex-col space-y-6 p-4"}
11
+ %ul{class: "flex justify-end items-center space-x-2 text-blue-600"}
12
+ %li= link_to "审查(#{CensorBear::ModLog.pending.count})", mod_logs_path
13
+ %li= link_to "敏感词", stop_words_path
14
+ %li= link_to "日志", logs_path
15
+ %li= link_to "回主站", "/"
16
+ %li= current_user.email
17
+ %div
18
+ = yield
data/config/cable.yml ADDED
@@ -0,0 +1,9 @@
1
+ development:
2
+ adapter: redis
3
+ url: redis://localhost:6379/1
4
+ test:
5
+ adapter: test
6
+ production:
7
+ adapter: redis
8
+ url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
9
+ channel_prefix: dummy_production
@@ -0,0 +1,6 @@
1
+ CensorBear.configure do |config|
2
+ # class name of you User model, default: 'User'
3
+ # config.user_class = 'User'
4
+ # current_user method name in your Controller, default: 'current_user'
5
+ # config.user_name_method = 'current_user'
6
+ end
@@ -0,0 +1,7 @@
1
+ en:
2
+ censor_log:
3
+ action:
4
+ mod: 审核
5
+ banned: 禁用
6
+ ignore: 忽略
7
+ replace: 替换
data/config/routes.rb ADDED
@@ -0,0 +1,12 @@
1
+ CensorBear::Engine.routes.draw do
2
+ resources :mod_logs do
3
+ get :ignore
4
+ get :approve
5
+ get :delete
6
+ get :ban
7
+ end
8
+ resources :logs
9
+ resources :stop_words
10
+
11
+ root to: "stop_words#index"
12
+ end
@@ -0,0 +1,16 @@
1
+ class CreateCensorBearStopWords < ActiveRecord::Migration[6.1]
2
+ def change
3
+ create_table :censor_bear_stop_words do |t|
4
+ t.string :key
5
+ t.bigint :user_id
6
+ t.string :ugc
7
+ t.string :username
8
+ t.string :nickname
9
+ t.string :signature
10
+ t.string :dialog
11
+ t.string :replacement
12
+
13
+ t.timestamps
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ class CreateCensorBearLogs < ActiveRecord::Migration[6.1]
2
+ def change
3
+ create_table :censor_bear_logs do |t|
4
+ t.text :original_content
5
+ t.string :action
6
+ t.text :filtered_content
7
+ t.string :mod_words, array: true, default: []
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,18 @@
1
+ class CreateCensorBearModLogs < ActiveRecord::Migration[6.1]
2
+ def change
3
+ create_table :censor_bear_mod_logs do |t|
4
+ t.bigint :record_id
5
+ t.string :record_type
6
+ t.text :content
7
+ t.string :reason
8
+ t.string :mod_words, array: true, default: []
9
+ t.integer :status, default: 0
10
+ t.bigint :user_id
11
+
12
+ t.timestamps
13
+
14
+ t.index %w[record_type record_id], using: :btree
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,64 @@
1
+ module CensorBear
2
+ class Result
3
+ attr_accessor :is_mod, :mod_words, :content
4
+
5
+ def initialize(content, is_mod = false, mod_words = [])
6
+ @is_mod = is_mod
7
+ @mod_words = mod_words
8
+ @content = content || ''
9
+ end
10
+ end
11
+
12
+ class Censor
13
+ def initialize(content, type = 'ugc')
14
+ @is_mod = false
15
+ @mod_words = []
16
+ @content = content
17
+ @type = type.to_s
18
+ end
19
+
20
+ def check_text
21
+ return Result.new(@content) if @content.blank?
22
+ return Result.new(@content) unless CensorBear::StopWord::FIELDS.include?(@type)
23
+
24
+ local_check
25
+
26
+ # 用户相关类型直接封禁,速错
27
+ raise NotPassedException if @is_mod && %w[username signature dialog nickname].include?(@type)
28
+
29
+ Result.new(@content, @is_mod, @mod_words.uniq)
30
+ end
31
+
32
+ def local_check
33
+ original_content = @content.dup
34
+ stop_words = CensorBear::StopWord.where("#{@type} != 'IGNORE'")
35
+ stop_words.each do |word|
36
+ finder = Regexp.new(Regexp.escape(word.key))
37
+ action = word.send(@type.to_sym).upcase
38
+ next unless finder.match(@content)
39
+ @mod_words.push(word.key)
40
+ case action
41
+ when 'REPLACE'
42
+ @content = @content.gsub(finder, word.replacement)
43
+ CensorBear::Log.create(original_content: original_content, action: "#{@type}_#{action}", filtered_content: @content, mod_words: [word.key])
44
+ when 'MOD'
45
+ @is_mod = true
46
+ CensorBear::Log.create(original_content: original_content, action: "#{@type}_#{action}", filtered_content: nil, mod_words: [word.key])
47
+ when 'BANNED'
48
+ @is_mod = true
49
+ # 禁止的直接抛出异常
50
+ CensorBear::Log.create(original_content: original_content, action: "#{@type}_#{action}", filtered_content: nil, mod_words: [word.key])
51
+ raise NotPassedException
52
+ end
53
+ end
54
+ end
55
+
56
+ def cloud_check() end
57
+
58
+ private
59
+
60
+ def tencent_check() end
61
+
62
+ def aliyun_check() end
63
+ end
64
+ end
@@ -0,0 +1,12 @@
1
+ module CensorBear
2
+ class Configuration
3
+ # class name of you User model, default: 'User'
4
+ attr_accessor :user_class
5
+
6
+ # current_user method name in your Controller, default: 'current_user'
7
+ attr_accessor :current_user_method
8
+
9
+ # user name method, default: "name"
10
+ attr_accessor :user_name_method
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ require "turbo-rails"
2
+
3
+ module CensorBear
4
+ class Engine < ::Rails::Engine
5
+ isolate_namespace CensorBear
6
+
7
+ initializer "censor_bear.assets.precompile" do |app|
8
+ app.config.assets.precompile += %w( censor_bear/application.css )
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module CensorBear
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,36 @@
1
+ require "censor_bear/version"
2
+ require "censor_bear/engine"
3
+ require "censor_bear/censor"
4
+ require "censor_bear/configuration"
5
+
6
+ require "hamlit"
7
+ require 'pagy'
8
+
9
+ module CensorBear
10
+ class NotPassedException < StandardError; end
11
+
12
+ class << self
13
+ def config
14
+ return @config if defined?(@config)
15
+
16
+ @config = Configuration.new
17
+ @config.user_class = 'User'
18
+ @config.current_user_method = 'current_user'
19
+ @config.user_name_method = 'name'
20
+ @config
21
+ end
22
+
23
+ def configure
24
+ yield(config)
25
+ end
26
+
27
+ def check_text(content, type = 'ugc')
28
+ Censor.new(content, type).check_text
29
+ end
30
+
31
+
32
+ def action_options
33
+ I18n.t('censor_log.action').map { |k, v| [v, k.to_s] }
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :censor_bear do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,177 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: censor_bear
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - 42up
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-11-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 6.1.4
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 6.1.4.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: 6.1.4
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 6.1.4.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: hamlit
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: haml-rails
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '2.0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '2.0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: turbo-rails
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: pagy
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '5.6'
82
+ type: :runtime
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '5.6'
89
+ description: Description of CensorBear.
90
+ email:
91
+ - foobar@v2up.com
92
+ executables: []
93
+ extensions: []
94
+ extra_rdoc_files: []
95
+ files:
96
+ - MIT-LICENSE
97
+ - README.md
98
+ - Rakefile
99
+ - app/assets/config/censor_bear_manifest.js
100
+ - app/assets/stylesheets/censor_bear/application.css
101
+ - app/assets/stylesheets/censor_bear/logs.css
102
+ - app/assets/stylesheets/censor_bear/mod_logs.css
103
+ - app/assets/stylesheets/censor_bear/stop_words.css
104
+ - app/assets/stylesheets/censor_bear/tailwind.min.css
105
+ - app/assets/stylesheets/scaffold.css
106
+ - app/controllers/censor_bear/application_controller.rb
107
+ - app/controllers/censor_bear/logs_controller.rb
108
+ - app/controllers/censor_bear/mod_logs_controller.rb
109
+ - app/controllers/censor_bear/stop_words_controller.rb
110
+ - app/helpers/censor_bear/application_helper.rb
111
+ - app/helpers/censor_bear/logs_helper.rb
112
+ - app/helpers/censor_bear/mod_logs_helper.rb
113
+ - app/helpers/censor_bear/stop_words_helper.rb
114
+ - app/jobs/censor_bear/application_job.rb
115
+ - app/mailers/censor_bear/application_mailer.rb
116
+ - app/models/censor_bear/application_record.rb
117
+ - app/models/censor_bear/log.rb
118
+ - app/models/censor_bear/mod_log.rb
119
+ - app/models/censor_bear/stop_word.rb
120
+ - app/views/censor_bear/logs/_form.html.erb
121
+ - app/views/censor_bear/logs/edit.html.erb
122
+ - app/views/censor_bear/logs/index.html.erb
123
+ - app/views/censor_bear/logs/new.html.erb
124
+ - app/views/censor_bear/logs/show.html.erb
125
+ - app/views/censor_bear/mod_logs/_form.html.erb
126
+ - app/views/censor_bear/mod_logs/edit.html.erb
127
+ - app/views/censor_bear/mod_logs/index.html.erb
128
+ - app/views/censor_bear/mod_logs/new.html.erb
129
+ - app/views/censor_bear/mod_logs/show.html.erb
130
+ - app/views/censor_bear/stop_words/_form.html.haml
131
+ - app/views/censor_bear/stop_words/_stop_word.html.haml
132
+ - app/views/censor_bear/stop_words/destroy.turbo_stream.haml
133
+ - app/views/censor_bear/stop_words/edit.html.haml
134
+ - app/views/censor_bear/stop_words/index.html.haml
135
+ - app/views/censor_bear/stop_words/new.html.haml
136
+ - app/views/censor_bear/stop_words/show.html.haml
137
+ - app/views/layouts/censor_bear/application.html.haml
138
+ - config/cable.yml
139
+ - config/initializers/censor_bear.rb
140
+ - config/locales/censor_bear.yml
141
+ - config/routes.rb
142
+ - db/migrate/20211126133758_create_censor_bear_stop_words.rb
143
+ - db/migrate/20211129093508_create_censor_bear_logs.rb
144
+ - db/migrate/20211129110218_create_censor_bear_mod_logs.rb
145
+ - lib/censor_bear.rb
146
+ - lib/censor_bear/censor.rb
147
+ - lib/censor_bear/configuration.rb
148
+ - lib/censor_bear/engine.rb
149
+ - lib/censor_bear/version.rb
150
+ - lib/tasks/censor_bear_tasks.rake
151
+ homepage: https://github.com/42up/censor_bear
152
+ licenses:
153
+ - MIT
154
+ metadata:
155
+ homepage_uri: https://github.com/42up/censor_bear
156
+ source_code_uri: https://github.com/42up/censor_bear
157
+ changelog_uri: https://github.com/42up/censor_bear
158
+ post_install_message:
159
+ rdoc_options: []
160
+ require_paths:
161
+ - lib
162
+ required_ruby_version: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ required_rubygems_version: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ requirements: []
173
+ rubygems_version: 3.2.22
174
+ signing_key:
175
+ specification_version: 4
176
+ summary: Summary of CensorBear.
177
+ test_files: []