require "sinbotra" require "sinatra" require "json" module Sinbotra class Server < Sinatra::Base configure do raise ArgumentError, "You need to set a FACEBOOK_PAGE_TOKEN environmental variable to run the server!" unless ENV["FACEBOOK_PAGE_TOKEN"] raise ArgumentError, "You need to set a FACEBOOK_APP_SECRET environmental variable to run the server!" unless ENV["FACEBOOK_APP_SECRET"] raise ArgumentError, "You need to set a FACEBOOK_CHALLENGE environmental variable to run the server!" unless ENV["FACEBOOK_CHALLENGE"] end helpers do def verify_facebook_signature!(payload_body) digest = OpenSSL::HMAC.hexdigest( OpenSSL::Digest.new("sha1"), ENV["FACEBOOK_APP_SECRET"], payload_body ) signature = "sha1=" + digest return halt 403, "Signatures didn't match!" unless Rack::Utils.secure_compare(signature, request.env["HTTP_X_HUB_SIGNATURE"]) end def match_facebook_challenge(params) matching = params["hub.mode"] == "subscribe" && params["hub.verify_token"] == ENV.fetch("FACEBOOK_CHALLENGE") matching ? params["hub.challenge"] : nil end end get "/facebook/webhook" do if challenge = match_facebook_challenge(params) challenge else status 403 end end post "/facebook/webhook" do payload = request.body.read verify_facebook_signature!(payload) begin msg = JSON.load(payload) Sinbotra::Bot.handle(:facebook, msg) "OK" rescue Exception => e STDERR.puts e.message STDERR.puts e.backtrace status 500 "ERROR" end end end end