censor_bear 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []