antispam 0.1.7 → 0.2.3

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +20 -20
  3. data/README.md +129 -113
  4. data/Rakefile +18 -18
  5. data/app/assets/config/antispam_manifest.js +1 -1
  6. data/app/assets/stylesheets/antispam/application.css +15 -15
  7. data/app/assets/stylesheets/antispam/blocks.css +4 -4
  8. data/app/assets/stylesheets/antispam/challenges.css +4 -4
  9. data/app/assets/stylesheets/antispam/clears.css +4 -4
  10. data/app/assets/stylesheets/scaffold.css +80 -80
  11. data/app/controllers/antispam/application_controller.rb +11 -11
  12. data/app/controllers/antispam/blocks_controller.rb +28 -28
  13. data/app/controllers/antispam/challenges_controller.rb +50 -50
  14. data/app/controllers/antispam/clears_controller.rb +28 -28
  15. data/app/controllers/antispam/validate_controller.rb +12 -12
  16. data/app/helpers/antispam/application_helper.rb +4 -4
  17. data/app/helpers/antispam/blocks_helper.rb +4 -4
  18. data/app/helpers/antispam/challenges_helper.rb +4 -4
  19. data/app/helpers/antispam/clears_helper.rb +4 -4
  20. data/app/jobs/antispam/application_job.rb +4 -4
  21. data/app/mailers/antispam/application_mailer.rb +6 -6
  22. data/app/models/antispam/application_record.rb +5 -5
  23. data/app/models/antispam/block.rb +4 -4
  24. data/app/models/antispam/challenge.rb +26 -26
  25. data/app/models/antispam/clear.rb +4 -4
  26. data/app/models/antispam/ip.rb +11 -6
  27. data/app/views/antispam/blocks/index.html.erb +38 -38
  28. data/app/views/antispam/blocks/show.html.erb +24 -24
  29. data/app/views/antispam/challenges/_form.html.erb +32 -32
  30. data/app/views/antispam/challenges/edit.html.erb +6 -6
  31. data/app/views/antispam/challenges/index.html.erb +31 -31
  32. data/app/views/antispam/challenges/new.html.erb +5 -5
  33. data/app/views/antispam/challenges/show.html.erb +19 -19
  34. data/app/views/antispam/clears/index.html.erb +32 -32
  35. data/app/views/antispam/clears/show.html.erb +29 -29
  36. data/app/views/antispam/validate/index.html.erb +16 -14
  37. data/app/views/layouts/antispam/application.html.erb +25 -15
  38. data/config/routes.rb +7 -7
  39. data/db/migrate/20210130213708_create_antispam_ips.rb +12 -12
  40. data/db/migrate/20210130214835_create_antispam_challenges.rb +11 -11
  41. data/db/migrate/20210130234107_create_antispam_blocks.rb +12 -12
  42. data/db/migrate/20210130235537_create_antispam_clears.rb +13 -13
  43. data/db/migrate/20210131165122_add_threat_to_antispam_blocks.rb +5 -5
  44. data/lib/antispam/blacklists/httpbl.rb +49 -48
  45. data/lib/antispam/checker.rb +30 -19
  46. data/lib/antispam/engine.rb +5 -5
  47. data/lib/antispam/results.rb +18 -10
  48. data/lib/antispam/spamcheckers/defendium.rb +29 -28
  49. data/lib/antispam/tools.rb +59 -57
  50. data/lib/antispam/version.rb +3 -3
  51. data/lib/antispam.rb +21 -17
  52. data/lib/tasks/antispam_tasks.rake +4 -4
  53. metadata +6 -6
@@ -1,19 +1,19 @@
1
- <p id="notice"><%= notice %></p>
2
-
3
- <p>
4
- <strong>Question:</strong>
5
- <%= @challenge.question %>
6
- </p>
7
-
8
- <p>
9
- <strong>Answer:</strong>
10
- <%= @challenge.answer %>
11
- </p>
12
-
13
- <p>
14
- <strong>Code:</strong>
15
- <%= @challenge.code %>
16
- </p>
17
-
18
- <%= link_to 'Edit', edit_challenge_path(@challenge) %> |
19
- <%= link_to 'Back', challenges_path %>
1
+ <p id="notice"><%= notice %></p>
2
+
3
+ <p>
4
+ <strong>Question:</strong>
5
+ <%= @challenge.question %>
6
+ </p>
7
+
8
+ <p>
9
+ <strong>Answer:</strong>
10
+ <%= @challenge.answer %>
11
+ </p>
12
+
13
+ <p>
14
+ <strong>Code:</strong>
15
+ <%= @challenge.code %>
16
+ </p>
17
+
18
+ <%= link_to 'Edit', edit_challenge_path(@challenge) %> |
19
+ <%= link_to 'Back', challenges_path %>
@@ -1,32 +1,32 @@
1
- <p id="notice"><%= notice %></p>
2
-
3
- <h1>Clears</h1>
4
-
5
- <table>
6
- <thead>
7
- <tr>
8
- <th>Ip</th>
9
- <th>Result</th>
10
- <th>Answer</th>
11
- <th>Threat before</th>
12
- <th>Threat after</th>
13
- <th colspan="3"></th>
14
- </tr>
15
- </thead>
16
-
17
- <tbody>
18
- <% Antispam::Clear.all.order(created_at: :desc).limit(50).each do |clear| %>
19
- <tr>
20
- <td><%= clear.ip %></td>
21
- <td><%= clear.result %></td>
22
- <td><%= clear.answer %></td>
23
- <td><%= clear.threat_before %></td>
24
- <td><%= clear.threat_after %></td>
25
- <td><%= time_ago_in_words clear.created_at %> ago</td>
26
- <!-- <td><%#= link_to 'Show', clear %></td>-->
27
- <!-- <td><%#= link_to 'Edit', edit_clear_path(clear) %></td>-->
28
- <!-- <td><%#= link_to 'Destroy', clear, method: :delete, data: { confirm: 'Are you sure?' } %></td>-->
29
- </tr>
30
- <% end %>
31
- </tbody>
32
- </table>
1
+ <p id="notice"><%= notice %></p>
2
+
3
+ <h1>Clears</h1>
4
+
5
+ <table>
6
+ <thead>
7
+ <tr>
8
+ <th>Ip</th>
9
+ <th>Result</th>
10
+ <th>Answer</th>
11
+ <th>Threat before</th>
12
+ <th>Threat after</th>
13
+ <th colspan="3"></th>
14
+ </tr>
15
+ </thead>
16
+
17
+ <tbody>
18
+ <% Antispam::Clear.all.order(created_at: :desc).limit(50).each do |clear| %>
19
+ <tr>
20
+ <td><%= clear.ip %></td>
21
+ <td><%= clear.result %></td>
22
+ <td><%= clear.answer %></td>
23
+ <td><%= clear.threat_before %></td>
24
+ <td><%= clear.threat_after %></td>
25
+ <td><%= time_ago_in_words clear.created_at %> ago</td>
26
+ <!-- <td><%#= link_to 'Show', clear %></td>-->
27
+ <!-- <td><%#= link_to 'Edit', edit_clear_path(clear) %></td>-->
28
+ <!-- <td><%#= link_to 'Destroy', clear, method: :delete, data: { confirm: 'Are you sure?' } %></td>-->
29
+ </tr>
30
+ <% end %>
31
+ </tbody>
32
+ </table>
@@ -1,29 +1,29 @@
1
- <p id="notice"><%= notice %></p>
2
-
3
- <p>
4
- <strong>Ip:</strong>
5
- <%= @clear.ip %>
6
- </p>
7
-
8
- <p>
9
- <strong>Result:</strong>
10
- <%= @clear.result %>
11
- </p>
12
-
13
- <p>
14
- <strong>Answer:</strong>
15
- <%= @clear.answer %>
16
- </p>
17
-
18
- <p>
19
- <strong>Threat before:</strong>
20
- <%= @clear.threat_before %>
21
- </p>
22
-
23
- <p>
24
- <strong>Threat after:</strong>
25
- <%= @clear.threat_after %>
26
- </p>
27
-
28
- <%= link_to 'Edit', edit_clear_path(@clear) %> |
29
- <%= link_to 'Back', clears_path %>
1
+ <p id="notice"><%= notice %></p>
2
+
3
+ <p>
4
+ <strong>Ip:</strong>
5
+ <%= @clear.ip %>
6
+ </p>
7
+
8
+ <p>
9
+ <strong>Result:</strong>
10
+ <%= @clear.result %>
11
+ </p>
12
+
13
+ <p>
14
+ <strong>Answer:</strong>
15
+ <%= @clear.answer %>
16
+ </p>
17
+
18
+ <p>
19
+ <strong>Threat before:</strong>
20
+ <%= @clear.threat_before %>
21
+ </p>
22
+
23
+ <p>
24
+ <strong>Threat after:</strong>
25
+ <%= @clear.threat_after %>
26
+ </p>
27
+
28
+ <%= link_to 'Edit', edit_clear_path(@clear) %> |
29
+ <%= link_to 'Back', clears_path %>
@@ -1,14 +1,16 @@
1
- <% @challenge = Antispam::Challenge.create %>
2
- <h1>Human Challenge</h1>
3
-
4
- <p>Please prove that you are human.</p>
5
-
6
- <img src="/antispam/challenges/<%= @challenge.id %>.jpg" width="200" height="40">
7
-
8
- <%= form_for @challenge do |f| %>
9
- <%= f.hidden_field :id, value: @challenge.id %>
10
- <%= f.text_field :answer, value: '' %>
11
- <%= submit_tag "Submit" %>
12
- <% end %>
13
-
14
- <% flash.each do |type, msg| %><div><%= msg %></div><% end %>
1
+ <% @challenge = Antispam::Challenge.create %>
2
+ <div class="centerblock">
3
+ <h1>Human Challenge</h1>
4
+
5
+ <p>Please prove that you are human.</p>
6
+
7
+ <img src="/antispam/challenges/<%= @challenge.id %>.jpg" width="200" height="40">
8
+
9
+ <%= form_for @challenge do |f| %>
10
+ <%= f.hidden_field :id, value: @challenge.id %>
11
+ <%= f.text_field :answer, value: '' %>
12
+ <%= submit_tag "Submit" %>
13
+ <% end %>
14
+
15
+ <% flash.each do |type, msg| %><div><%= msg %></div><% end %>
16
+ </div>
@@ -1,15 +1,25 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <title>Antispam</title>
5
- <%= csrf_meta_tags %>
6
- <%= csp_meta_tag %>
7
- <style>.row { width:100%;display: flex;} .cx { width: 50%; }</style>
8
- <%#= stylesheet_link_tag "antispam/application", media: "all" %>
9
- </head>
10
- <body>
11
-
12
- <%= yield %>
13
-
14
- </body>
15
- </html>
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Antispam</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+ <style>
8
+ .row { width:100%;display: flex;}
9
+ .cx { width: 50%; }
10
+ .centerblock {
11
+ box-shadow: 1px 1px 7px #000;
12
+ max-width: 300px;
13
+ margin: 3em auto;
14
+ padding: 0.5em 2em 2em;
15
+ width: 100%;
16
+ }
17
+ </style>
18
+ <%#= stylesheet_link_tag "antispam/application", media: "all" %>
19
+ </head>
20
+ <body>
21
+
22
+ <%= yield %>
23
+
24
+ </body>
25
+ </html>
data/config/routes.rb CHANGED
@@ -1,7 +1,7 @@
1
- Antispam::Engine.routes.draw do
2
- resources :clears
3
- resources :blocks
4
- resources :challenges
5
- root to: 'ips#index'
6
- get 'validate', to: 'validate#index'
7
- end
1
+ Antispam::Engine.routes.draw do
2
+ resources :clears
3
+ resources :blocks
4
+ resources :challenges
5
+ root to: 'ips#index'
6
+ get 'validate', to: 'validate#index'
7
+ end
@@ -1,12 +1,12 @@
1
- class CreateAntispamIps < ActiveRecord::Migration[6.1]
2
- def change
3
- create_table :antispam_ips do |t|
4
- t.string :address
5
- t.string :provider
6
- t.integer :threat
7
- t.datetime :expires_at
8
-
9
- t.timestamps
10
- end
11
- end
12
- end
1
+ class CreateAntispamIps < ActiveRecord::Migration[6.1]
2
+ def change
3
+ create_table :antispam_ips do |t|
4
+ t.string :address
5
+ t.string :provider
6
+ t.integer :threat
7
+ t.datetime :expires_at
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+ end
@@ -1,11 +1,11 @@
1
- class CreateAntispamChallenges < ActiveRecord::Migration[6.1]
2
- def change
3
- create_table :antispam_challenges do |t|
4
- t.string :question
5
- t.string :answer
6
- t.string :code
7
-
8
- t.timestamps
9
- end
10
- end
11
- end
1
+ class CreateAntispamChallenges < ActiveRecord::Migration[6.1]
2
+ def change
3
+ create_table :antispam_challenges do |t|
4
+ t.string :question
5
+ t.string :answer
6
+ t.string :code
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -1,12 +1,12 @@
1
- class CreateAntispamBlocks < ActiveRecord::Migration[6.1]
2
- def change
3
- create_table :antispam_blocks do |t|
4
- t.string :ip
5
- t.string :provider
6
- t.string :controllername
7
- t.string :actionname
8
-
9
- t.timestamps
10
- end
11
- end
12
- end
1
+ class CreateAntispamBlocks < ActiveRecord::Migration[6.1]
2
+ def change
3
+ create_table :antispam_blocks do |t|
4
+ t.string :ip
5
+ t.string :provider
6
+ t.string :controllername
7
+ t.string :actionname
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+ end
@@ -1,13 +1,13 @@
1
- class CreateAntispamClears < ActiveRecord::Migration[6.1]
2
- def change
3
- create_table :antispam_clears do |t|
4
- t.string :ip
5
- t.string :result
6
- t.string :answer
7
- t.integer :threat_before
8
- t.integer :threat_after
9
-
10
- t.timestamps
11
- end
12
- end
13
- end
1
+ class CreateAntispamClears < ActiveRecord::Migration[6.1]
2
+ def change
3
+ create_table :antispam_clears do |t|
4
+ t.string :ip
5
+ t.string :result
6
+ t.string :answer
7
+ t.integer :threat_before
8
+ t.integer :threat_after
9
+
10
+ t.timestamps
11
+ end
12
+ end
13
+ end
@@ -1,5 +1,5 @@
1
- class AddThreatToAntispamBlocks < ActiveRecord::Migration[6.1]
2
- def change
3
- add_column :antispam_blocks, :threat, :integer
4
- end
5
- end
1
+ class AddThreatToAntispamBlocks < ActiveRecord::Migration[6.1]
2
+ def change
3
+ add_column :antispam_blocks, :threat, :integer
4
+ end
5
+ end
@@ -1,48 +1,49 @@
1
- require 'resolv'
2
- module Antispam
3
- module Blacklists
4
- class Httpbl
5
- def self.check(ip, key, verbose)
6
- threat = 0
7
- begin
8
- old_result = get_old_result(ip)
9
- if old_result
10
- Rails.logger.info "Returning old result for #{ip}." if verbose
11
- return get_old_result(ip)
12
- end
13
- check = ip.split('.').reverse.join('.')
14
- host = key + '.' + check + ".dnsbl.httpbl.org"
15
- address = Resolv::getaddress(host)
16
- z,days,threat,iptype = address.split('.')
17
- Rails.logger.info "Spam located: #{iptype} type at #{threat} threat. (#{ip} - #{address})" if verbose
18
- threat = threat.to_i
19
- # Create or update
20
- if (threat > 30)
21
- Rails.logger.info "Spamcheck: Very high, over 30!" if verbose
22
- end
23
- rescue Exception => e
24
- case e
25
- when Resolv::ResolvError #Not spam! This blacklist gives an error when there's no spam threat.
26
- Rails.logger.info "Spamcheck: OK! Resolve error means the httpbl does not consider this spam." if verbose
27
- when Interrupt #Something broke while trying to check blacklist.
28
- Rails.logger.info "Spamcheck: Interrupt when trying to resolve http blacklist. Possible timeout?" if verbose
29
- else # Time Out
30
- Rails.logger.info "Spamcheck: There was an error, possibly a time out, when checking this IP." if verbose
31
- Rails.logger.info e.to_s if verbose
32
- end
33
- end
34
- update_old_result(ip, threat)
35
- return threat
36
- end
37
- def self.get_old_result(ip)
38
- result = Antispam::Ip.find_by(address: ip, provider: 'httpbl')
39
- return nil if (result.nil? || result.expired?)
40
- return result.threat
41
- end
42
- def self.update_old_result(ip, threat)
43
- result = Antispam::Ip.find_or_create_by(address: ip, provider: 'httpbl')
44
- result.update(threat: threat, expires_at: 24.hours.from_now)
45
- end
46
- end
47
- end
48
- end
1
+ require 'resolv'
2
+ module Antispam
3
+ module Blacklists
4
+ class Httpbl
5
+ # Returns a threat-level number, or 0 if no threat / no result.
6
+ def self.check(ip, key, verbose)
7
+ threat = 0
8
+ begin
9
+ old_result = get_old_result(ip)
10
+ if old_result
11
+ Rails.logger.info "Returning old result for #{ip}." if verbose
12
+ return get_old_result(ip)
13
+ end
14
+ check = ip.split('.').reverse.join('.')
15
+ host = key + '.' + check + ".dnsbl.httpbl.org"
16
+ address = Resolv::getaddress(host)
17
+ z,days,threat,iptype = address.split('.')
18
+ Rails.logger.info "Spam located: #{iptype} type at #{threat} threat. (#{ip} - #{address})" if verbose
19
+ threat = threat.to_i
20
+ # Create or update
21
+ if (threat > 30)
22
+ Rails.logger.info "Spamcheck: Very high, over 30!" if verbose
23
+ end
24
+ rescue Exception => e
25
+ case e
26
+ when Resolv::ResolvError #Not spam! This blacklist gives an error when there's no spam threat.
27
+ Rails.logger.info "Spamcheck: OK! Resolve error means the httpbl does not consider this spam." if verbose
28
+ when Interrupt #Something broke while trying to check blacklist.
29
+ Rails.logger.info "Spamcheck: Interrupt when trying to resolve http blacklist. Possible timeout?" if verbose
30
+ else # Time Out
31
+ Rails.logger.info "Spamcheck: There was an error, possibly a time out, when checking this IP." if verbose
32
+ Rails.logger.info e.to_s if verbose
33
+ end
34
+ end
35
+ update_old_result(ip, threat)
36
+ return threat
37
+ end
38
+ def self.get_old_result(ip)
39
+ result = Antispam::Ip.find_by(address: ip, provider: 'httpbl')
40
+ return nil if (result.nil? || result.expired?)
41
+ return result.threat
42
+ end
43
+ def self.update_old_result(ip, threat)
44
+ result = Antispam::Ip.find_or_create_by(address: ip, provider: 'httpbl')
45
+ result.update(threat: threat, expires_at: 24.hours.from_now)
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,20 +1,31 @@
1
- module Antispam
2
- module Checker
3
- # Checks content for spam
4
- # check(options, spamcheck_providers)
5
- # Usage: check({content: "No spam here"}, {defendium: 'MY_API_KEY'}})
6
- def self.check(options = {}, spamcheck_providers = {defendium: 'YOUR_KEY'})
7
- Rails.logger.info "Content was nil for spamcheck." if options[:content].nil? && options[:verbose]
8
- return if options[:content].nil?
9
- Rails.logger.info "Spamcheckers should be a hash" if (!(options[:spamcheck_providers].is_a? Hash)) && options[:verbose]
10
- results = []
11
- spamcheck_providers.each do |spamchecker_name, spamchecker_api_key|
12
- if spamchecker_name == :defendium
13
- results.append Antispam::Spamcheckers::Defendium.check(options[:content], spamchecker_api_key, options[:verbose])
14
- end
15
- end
16
- result = Antispam::SpamcheckResult.new(results)
17
- return result
18
- end
19
- end
1
+ module Antispam
2
+ module Checker
3
+ # Checks content for spam
4
+ # check(options)
5
+ # Usage: check({content: "No spam here", providers: { defendium: 'MY_API_KEY'}})
6
+ def self.check(options = {})
7
+ # Default provider. 'YOUR_KEY' works temporarily, giving a warning but also giving results
8
+ # eventually add something to tell users to add their own keys
9
+ # or choose their preferred provider, when more provider options are added.
10
+ options[:providers] ||= {defendium: 'YOUR_KEY'}
11
+ Rails.logger.info "Content was nil for spamcheck." if options[:content].nil? && options[:verbose]
12
+ return if options[:content].nil?
13
+ Rails.logger.info "Spamcheckers should be a hash" if (!(options[:providers].is_a? Hash)) && options[:verbose]
14
+ results = []
15
+ options[:providers].each do |spamchecker_name, spamchecker_api_key|
16
+ results.append spamchecker(spamchecker_name).check(options[:content], spamchecker_api_key, options[:verbose])
17
+ # if spamchecker_name == :defendium
18
+ # results.append Antispam::Spamcheckers::Defendium.check(options[:content], spamchecker_api_key, options[:verbose])
19
+ # end
20
+ end
21
+ result = Antispam::SpamcheckResult.new(results)
22
+ return result
23
+ end
24
+ def self.spamchecker(provider)
25
+ class_name = provider.to_s.camelize
26
+ raise Antispam::NoSuchSpamcheckerError unless Antispam::Spamcheckers.const_defined? class_name
27
+ Antispam::Spamcheckers.const_get class_name
28
+ end
29
+ end
30
+ class NoSuchSpamcheckerError < StandardError; end
20
31
  end
@@ -1,5 +1,5 @@
1
- module Antispam
2
- class Engine < ::Rails::Engine
3
- isolate_namespace Antispam
4
- end
5
- end
1
+ module Antispam
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Antispam
4
+ end
5
+ end
@@ -1,10 +1,18 @@
1
- module Antispam
2
- class SpamcheckResult
3
- def initialize(results)
4
- @results = results
5
- end
6
- def is_spam?
7
- @results.select{|x| x > 0}.present?
8
- end
9
- end
10
- end
1
+ module Antispam
2
+ class SpamcheckResult
3
+ def initialize(results)
4
+ @results = results
5
+ end
6
+ def is_spam?
7
+ @results.select{|x| x > 0}.present?
8
+ end
9
+ end
10
+ class BlacklistResult
11
+ def initialize(results)
12
+ @results = results
13
+ end
14
+ def is_bad?
15
+ @results.select{|x| x > 30}.present?
16
+ end
17
+ end
18
+ end
@@ -1,29 +1,30 @@
1
- #require 'resolv'
2
- module Antispam
3
- module Spamcheckers
4
- class Defendium
5
- def self.check(content, key, verbose)
6
- # nethttp2.rb
7
- require 'uri'
8
- require 'net/http'
9
-
10
- uri = URI('https://api.defendium.com/check')
11
- params = { secret_key: key, content: content }
12
- uri.query = URI.encode_www_form(params)
13
-
14
- res = Net::HTTP.get_response(uri)
15
- if res.is_a?(Net::HTTPSuccess)
16
- result = res.body.to_json
17
- if result["warnings"]
18
- Rails.logger.info result["warnings"]
19
- end
20
- if result["result"]
21
- return 1
22
- else
23
- return 0
24
- end
25
- end
26
- end
27
- end
28
- end
1
+ #require 'resolv'
2
+ module Antispam
3
+ module Spamcheckers
4
+ class Defendium
5
+ # Returns a boolean, 1 for spam, 0 for not spam.
6
+ def self.check(content, key, verbose)
7
+ # nethttp2.rb
8
+ require 'uri'
9
+ require 'net/http'
10
+
11
+ uri = URI('https://api.defendium.com/check')
12
+ params = { secret_key: key, content: content }
13
+ uri.query = URI.encode_www_form(params)
14
+
15
+ res = Net::HTTP.get_response(uri)
16
+ if res.is_a?(Net::HTTPSuccess)
17
+ result = res.body.to_json
18
+ if result["warnings"]
19
+ Rails.logger.info result["warnings"]
20
+ end
21
+ if result["result"]
22
+ return 1
23
+ else
24
+ return 0
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
29
30
  end