Skip to content

Instantly share code, notes, and snippets.

@PedroHLC
Created June 26, 2017 18:57
Show Gist options
  • Save PedroHLC/b377a4f592c3e58677bba0c186518dfa to your computer and use it in GitHub Desktop.
Save PedroHLC/b377a4f592c3e58677bba0c186518dfa to your computer and use it in GitHub Desktop.
PixelCanvas.io Multi-threaded BOT
#!/usr/bin/ruby
# [INCOMPLETE]
# PixelCanvas.io Multi-threaded BOT
require 'free-image'
require 'socket'
require 'net/http'
require 'json'
# - Config
$offset_x = -254
$offset_y = -581
# - Paint request helper
def paint_msg(x, y, color, fingerprint)
return {
'x'=>($offset_x+x),
'y'=>($offset_y+y),
'color'=>color,
'fingerprint'=>fingerprint,
'token'=>nil
}
end
def rgb_to_bw(c)
(c[:green] > 127) ? 0 : 3
end
$baseURI = URI.parse('http://pixelcanvas.io/api/pixel')
$baseHeader = {
'Content-Type' => 'application/json',
'Referer' => "http://pixelcanvas.io/@#{$offset_x},-#{$offset_y}",
'User-Agent' => 'Mozilla/5.0 (X11; Linux x86_64; rv:54.0) Gecko/20100101 Firefox/54.0',
'Accept' => '*/*',
'Accept-Language' => 'en-US,en;q=0.5',
'Origin' => 'http://pixelcanvas.io',
'Connection' => 'close',
'Content-Length' => '91'
}
def conn(msg)
puts('Requesting: ' + msg.to_s)
begin
http = Net::HTTP.new($baseURI.host, $baseURI.port)
request = Net::HTTP::Post.new($baseURI.request_uri, $baseHeader)
request.body = msg.to_json
res = http.request(request)
if !res.body.start_with?("{")
return :bye
end
res_data = JSON.parse(res.body)
sucess = res_data.has_key?('success') and res_data['success']
if sucess
return true
else
if(res_data.has_key?('waitSeconds'))
ws = res_data['waitSeconds'].to_f
puts "Waiting #{ws}"
sleep(ws-1)
return :retry
elsif(res_data.has_key?('errors'))
errors = res_data['errors']
if errors.is_a?(Array)
errors.each do |error|
if(error['param'] == 'fingerprint')
return :invalidfgp
else
puts error['msg']
end
end
else
puts errors
end
else
puts res.body
end
return false
end
rescue Exception => e
puts e.message
puts e.backtrace
return false
end
end
# - Fingerprints
$fingerprints = IO.readlines('fingerprints.txt')
$queue_fgp = $fingerprints.dup
def add_fingerprint(new_)
return if($fingerprints.include?(new_))
$fp_file = File.new('fingerprints.txt', 'ab+')
$fp_file.print("\n"+new_)
$fp_file.close
$fingerprints.push(new_)
$queue_fgp.push(new_)
puts('Added: '+new_)
end
def rem_fingerprint(target_)
$fingerprints.delete(target_)
$queue_fgp.delete(target_)
$fp_file = File.new('fingerprints.txt', 'wb')
$fp_file.write($fingerprints.join("\n"))
$fp_file.close
end
# - Targets
$queue_tgt = []
$source = FreeImage::Bitmap.open('data.png')
def reset_targets
new_targets = []
$source.height.times do |y|
scanline = $source.scanline(y)
scanline.each_with_index do |color, x|
new_targets.push({:x => x, :y => y, :c => rgb_to_bw(color)})
end
end
$queue_tgt = new_targets
end
# - HANDLE WHICH PIXEL EACH THREADS TARGETS AND WHICH FGP ACT
def act(target, fgp)
Thread.new do
res = nil
connMsg = paint_msg(target[:x], target[:y], target[:c], fgp)
while (res = conn(connMsg)) == :retry
sleep(1)
end
if res == :invalidfgp
rem_fingerprint(msg['fingerprint'])
else
$queue_fgp.push(fgp)
end
if res == true
puts "Success"
sleep(1*60+40)
else
$queue_tgt.push(target)
end
end
end
Thread.new do
loop do
while $queue_tgt.empty?
sleep(1)
end
target = $queue_tgt.shift
while $queue_fgp.empty?
sleep(1)
end
fgp = $queue_fgp.shift
act(target, fgp)
end
end
# -- LISTEN TO NEW FGPs
Thread.new do
sock = TCPServer.open(5023)
loop do
Thread.fork(sock.accept) do |client|
while line = client.gets
fix = line.strip
add_fingerprint(fix) if(fix.size > 4)
end
end
sleep(0.001)
end
end
# -- KEEP TARGETS FRESH
loop do
if($queue_tgt.empty?)
reset_targets
end
sleep(60)
end
@PedroHLC
Copy link
Author

TODO:

  • Download actual canvas on "reset_targets" and compare which pixels are needing painting...
    They seems to be 64x64 chunks of raw 4bits colors...
  • Find why sometimes tokens are needed.
  • Prepare against "Too Many Requests" error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment