Skip to content

Instantly share code, notes, and snippets.

@shouya
Last active December 17, 2015 20:29
Show Gist options
  • Save shouya/5668226 to your computer and use it in GitHub Desktop.
Save shouya/5668226 to your computer and use it in GitHub Desktop.
Charged rice
require 'rest_client'
require_relative 'threadpool'
require 'ruby-progressbar'
HEADERS_HASH = {
"User-Agent" => "Mozilla/5.0 (Macintosh; Intel" \
"Mac OS X 10_7_4) AppleWebKit/534.57.5 (KHTML, like Gecko) V" \
"ersion/5.1.7 Safari/534.57.4"
}
result = RestClient.get('http://freerice.com/user/login')
cookies = result.cookies
result_str = result.to_str
start_pos = (result_str =~ /"form_build_id"\sid="form-([0-9a-f]{32})"/)
form_build_id = result_str[start_pos + 20, 32 + 5]
print 'input your username: '
USERNAME = gets.chomp.strip
print 'input your password: '
PASSWORD = gets.chomp.strip
print 'input the number of grains you want to get: '
NUM_GRAINS = gets.chomp.to_i
begin
result = RestClient.post('http://freerice.com/user/login', {
:name => USERNAME,
:pass => PASSWORD,
:form_build_id => form_build_id,
:form_id => 'user_login'
}, :cookies => cookies)
rescue RestClient::Found
else
puts "wrong password."
exit
end
pool = ThreadPool.new(170)
pbar = ProgressBar.create(:title => 'target: ' + NUM_GRAINS.to_s,
:total => NUM_GRAINS/10,
:format => '%t:|%b%i|%p%%|%E')
(NUM_GRAINS/10).times do |i|
pool.process do
RestClient.post('http://freerice.com/game.php', {
:op => 'next',
:token => '5c114de9f6aeb7d5214c93' \
'd9c00afbf4',
:answer => 3,
:list => 'finish|heat|lamb|soil',
:nid => 1557,
:nb => 0
}, :cookies => cookies)
pbar.increment
end
end
pool.join
#--
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
# Version 2, December 2004
#
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
#
# 0. You just DO WHAT THE FUCK YOU WANT TO.
#++
require 'thread'
class ThreadPool
class Task
Timeout = Class.new(Exception)
Asked = Class.new(Exception)
attr_reader :pool, :timeout, :exception, :thread, :started_at
def initialize (pool, *args, &block)
@pool = pool
@arguments = args
@block = block
end
def running?; @running; end
def finished?; @finished; end
def timeout?; @timedout; end
def terminated?; @terminated; end
def execute (thread)
return if terminated? || running? || finished?
@thread = thread
@running = true
@started_at = Time.now
pool.wake_up_timeout
begin
@block.call(*@arguments)
rescue Exception => e
if e.is_a? Timeout
@timedout = true
elsif e.is_a? Asked
return
else
@exception = e.reason
end
end
@running = false
@finished = true
@thread = nil
end
def terminate! (exception = Asked)
return if terminated? || finished? || timeout?
@terminated = true
return unless running?
@thread.raise exception
end
def timeout!
terminate! Timeout
end
def timeout_after (time)
@timeout = time
pool.timeout_for self, time
self
end
end
attr_reader :min, :max, :spawned
def initialize (min, max = nil, &block)
@min = min
@max = max || min
@block = block
@cond = ConditionVariable.new
@mutex = Mutex.new
@todo = []
@workers = []
@timeouts = {}
@spawned = 0
@waiting = 0
@shutdown = false
@trim_requests = 0
@auto_trim = false
@mutex.synchronize {
min.times {
spawn_thread
}
}
end
def shutdown?; @shutdown; end
def auto_trim?; @auto_trim; end
def auto_trim!; @auto_trim = true; end
def no_auto_trim!; @auto_trim = false; end
def resize (min, max = nil)
@min = min
@max = max || min
trim!
end
def backlog
@mutex.synchronize {
@todo.length
}
end
def process (*args, &block)
unless block || @block
raise ArgumentError, 'you must pass a block'
end
task = Task.new(self, *args, &(block || @block))
@mutex.synchronize {
raise 'unable to add work while shutting down' if shutdown?
@todo << task
if @waiting == 0 && @spawned < @max
spawn_thread
end
@cond.signal
}
task
end
alias << process
def trim (force = false)
@mutex.synchronize {
if (force || @waiting > 0) && @spawned - @trim_requests > @min
@trim_requests -= 1
@cond.signal
end
}
self
end
def trim!
trim true
end
def shutdown!
@mutex.synchronize {
@shutdown = true
@cond.broadcast
}
wake_up_timeout
end
def shutdown
shutdown!
join
end
def join
@timeout.join if @timeout
@workers.first.join until @workers.empty?
self
end
def timeout_for (task, timeout)
unless @timeout
spawn_timeout_thread
end
@mutex.synchronize {
@timeouts[task] = timeout
wake_up_timeout
}
end
def shutdown_after (timeout)
Thread.new {
sleep timeout
shutdown
}
self
end
def wake_up_timeout
if @pipes
@pipes.last.write_nonblock 'x' rescue nil
end
end
private
def spawn_thread
@spawned += 1
thread = Thread.new {
loop do
task = @mutex.synchronize {
if @todo.empty?
while @todo.empty?
if @trim_requests > 0
@trim_requests -= 1
break
end
break if shutdown?
@waiting += 1
@cond.wait @mutex
@waiting -= 1
break !shutdown?
end or break
end
@todo.shift
} or break
task.execute(thread)
break if shutdown?
trim if auto_trim? && @spawned > @min
end
@mutex.synchronize {
@spawned -= 1
@workers.delete thread
}
}
@workers << thread
thread
end
def spawn_timeout_thread
@pipes = IO.pipe
@timeout = Thread.new {
loop do
now = Time.now
timeout = @timeouts.map {|task, timeout|
next unless task.started_at
now - task.started_at + task.timeout
}.compact.min unless @timeouts.empty?
readable, = IO.select([@pipes.first], nil, nil, timeout)
break if shutdown?
if readable && !readable.empty?
readable.first.read_nonblock 1024
end
now = Time.now
@timeouts.each {|task, time|
next if !task.started_at || task.terminated? || task.finished?
if now > task.started_at + task.timeout
task.timeout!
end
}
@timeouts.reject! { |task, _| task.terminated? || task.finished? }
break if shutdown?
end
}
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment