Skip to content

Commit

Permalink
[FEAT] Add code to bot detector
Browse files Browse the repository at this point in the history
  • Loading branch information
oded-zahavi committed Mar 15, 2017
1 parent adff2c1 commit 70aaafc
Show file tree
Hide file tree
Showing 14 changed files with 902 additions and 1 deletion.
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/.bundle/
/.yardoc
/Gemfile.lock
/_yardoc/
/coverage/
/doc/
/pkg/
/spec/reports/
/tmp/
4 changes: 4 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
source 'https://rubygems.org'

# Specify your gem's dependencies in bot_detector.gemspec
gemspec
42 changes: 41 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,41 @@
# bot_detector
# BotDetector

Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/bot_detector`. To experiment with that code, run `bin/console` for an interactive prompt.

TODO: Delete this and the text above, and describe your gem

## Installation

Add this line to your application's Gemfile:

```ruby
gem 'bot_detector'
```

And then execute:

$ bundle

Or install it yourself as:

$ gem install bot_detector

## Usage

TODO: Write usage instructions here

## Development

After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).

## Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/oded-zahavi/bot_detector.


## License

The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).

2 changes: 2 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
require "bundler/gem_tasks"
task :default => :spec
23 changes: 23 additions & 0 deletions bot_detector.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'bot_detector/version'

Gem::Specification.new do |spec|
spec.name = 'bot_detector'
spec.version = BotDetector::VERSION
spec.authors = ['Oded Zahavi']
spec.email = ['oded.z@fiverr.com']
spec.description = %q{This gem wraps perimeterx restful api to provide it with a ruby interface }
spec.summary = %q{This gem wraps perimeterx restful api to provide it with a ruby interface }
spec.homepage = 'https://github.com/oded-zahavi/bot_detector'
spec.license = 'MIT'

spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ['lib']

spec.add_development_dependency 'bundler', '~> 1.7'
spec.add_development_dependency 'rake'
end
5 changes: 5 additions & 0 deletions lib/bot_detector.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require "bot_detector/version"

module BotDetector
# Your code goes here...
end
121 changes: 121 additions & 0 deletions lib/bot_detector/perimeter_x.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
module BotDetector
class PerimeterX
class Config
attr_accessor :perimeterx_app_id
attr_accessor :perimeterx_secret
attr_accessor :perimeterx_cookie_name
attr_accessor :perimeterx_token

def initialize(&config)
self.instance_eval(&config) unless config.nil?
end

def time_measure_method(&block)
@time_measure = block if block_given?
@time_measure
end

def post_method(&block)
@post_method = block if block_given?
@post_method
end

def log_error_method(&block)
@log_error_method = block if block_given?
@log_error_method
end

def score_threshold_method(&block)
@score_threshold_method = block if block_given?
@score_threshold_method
end

def enabler_method(&block)
@enabler_method = block if block_given?
@enabler_method
end
end

attr_reader :cookie_info
attr_reader :xquery_info
attr_reader :xreset_info

@@settings = nil

def initialize(request, env, headers, cookies)
raise ArgumentError if request.nil?

encrypted_cookie = (cookies || {})[BotDetector::PerimeterX.cookie_name]
@cookie_info = RiskCookie.new(request.remote_ip, request.user_agent, encrypted_cookie)
BotDetector::PerimeterX.time_measure('bot_detection.xquery') do
@xquery_info = @cookie_info.query(request, env, headers)
end
end

def self.configure(&config)
@@config = Config.new(&config) unless config.nil?
@@config
end

def self.time_measure(name, &block)
@@config.time_measure_method.call(name, &block) unless @@config.time_measure_method.nil?
end

def self.post(perimeterx_route, request_body, auth_headers)
@@config.post_method.call(perimeterx_route, request_body, auth_headers) unless @@config.post_method.nil?
end

def self.log_error(klass, message, exception = nil)
@@config.log_error_method.call(klass, message, exception) unless @@config.log_error_method.nil?
end

def self.score_threshold
@@config.score_threshold_method.call
end

def self.enabled?
@@config.enabler_method.call
end

def self.app_id
@@config.perimeterx_app_id
end

def self.secret_key
@@config.perimeterx_secret
end

def self.cookie_name
@@config.perimeterx_cookie_name
end

def self.perimeterx_token
@@config.perimeterx_token
end

def self.delete_cookie!(cookies)
cookies.delete(self.cookie_name)
end

def to_h
{ action: action.to_s, cookie_info: cookie_info.to_h, xquery_info: xquery_info.to_h }
end

def reset(request, headers)
@xreset_info = cookie_info.reset(request, headers)
end

def exec_action(&block)
klass = Kernel.eval('self', block.binding)
action.run(klass, ActionCallback.new(&block))
end

private

def action
return cookie_info.action unless xquery_info.action.present?

xquery_info.action
end
end
end
25 changes: 25 additions & 0 deletions lib/bot_detector/perimeter_x/action_callback.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module BotDetector
class PerimeterX
class ActionCallback
def initialize(&block)
self.instance_eval(&block)
end

def captcha(&block)
@captcha = block if block_given?
@captcha
end

def block(&block)
@block = block if block_given?
@block
end

def none(&block)
@none = block if block_given?
@none
end
end
end
end

45 changes: 45 additions & 0 deletions lib/bot_detector/perimeter_x/actions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
module BotDetector
class PerimeterX
module Actions
class None
def self.to_s
'none'
end

def self.run(klass, action)
klass.instance_eval(&action.none) unless action.none.nil?
end
end

class Query
def self.to_s
'query'
end

def self.run(klass, action)
raise RuntimeError.new("#{__method__}: invalid action (Query)")
end
end

class Block
def self.to_s
'block'
end

def self.run(klass, action)
klass.instance_eval(&action.block) unless action.block.nil?
end
end

class Captcha
def self.to_s
'captcha'
end

def self.run(klass, action)
klass.instance_eval(&action.captcha) unless action.captcha.nil?
end
end
end
end
end
Loading

0 comments on commit 70aaafc

Please sign in to comment.