138 lines
3.4 KiB
Ruby
138 lines
3.4 KiB
Ruby
require 'http'
|
|
|
|
# Steps:
|
|
# - Go to login form, we need the temporal SID assigned by PHP
|
|
# - Submit the form
|
|
# - Go the PM edit form, we need the form_token
|
|
# - Load the user ID from the user name
|
|
# - Submit form with the user ID
|
|
# So we need to load 5 freaking pages just to send a single PM
|
|
# Luckily, the first 3 are only done once
|
|
|
|
class ForumBot
|
|
def initialize
|
|
@base_url = 'http://www.factorioforums.com/forum'
|
|
@cookies = HTTP::CookieJar.new
|
|
@authenticated = false
|
|
end
|
|
|
|
def authenticated?
|
|
@authenticated
|
|
end
|
|
|
|
# Login form
|
|
# ./ucp.php?mode=login
|
|
# username
|
|
# password
|
|
# autologin
|
|
# viewonline
|
|
# sid
|
|
# redirect ./ucp.php?mode=login
|
|
# login
|
|
def authenticate(forum_name, forum_password)
|
|
req :post, '/ucp.php?mode=login', {
|
|
username: forum_name,
|
|
password: forum_password,
|
|
autologin: 'on',
|
|
viewonline: 'on', # This means no
|
|
redirect: 'index.php',
|
|
sid: get_login_form_sid,
|
|
login: 'Login'
|
|
}
|
|
|
|
sid = @cookies.detect{|c| c.name == 'phpbb3_cobst_sid' }
|
|
@sid = sid && sid.value
|
|
cookie = @cookies.detect{|c| c.name == 'phpbb3_cobst_u' }
|
|
@authenticated = !!(cookie && cookie.value != '1')
|
|
end
|
|
|
|
# Submit form
|
|
# ../ucp.php?i=pm&mode=compose&action=post&sid=ae6184cabe88ec10dd036092de29d2f3
|
|
# username_list
|
|
# icon=0
|
|
# subject:Test
|
|
# addbbcode20:100
|
|
# message:Testtest
|
|
# lastclick:1438734772
|
|
# status_switch:0
|
|
# post:Submit
|
|
# attach_sig:on
|
|
# creation_time:1438734772
|
|
# form_token:0a846587ad71540c62824d729fb5af1dcd7ec3d7
|
|
def send_pm(user_id, subject, message)
|
|
raise 'user_id must be a number' unless user_id.to_i != 0
|
|
|
|
if authenticated?
|
|
params = get_pm_form_params
|
|
if params['form_token'].present?
|
|
params = get_pm_form_params.merge({
|
|
username_list: '',
|
|
"address_list[u][#{user_id}]" => 'to',
|
|
subject: subject,
|
|
message: message
|
|
})
|
|
|
|
req :post, "/ucp.php?i=pm&mode=compose&action=post&sid=#{@sid}", params
|
|
true # We wish for the best
|
|
else
|
|
false # No form_token, that means we are not logged in
|
|
end
|
|
else
|
|
false # We haven't called authenticate yet
|
|
end
|
|
end
|
|
|
|
def get_user_id(user_name)
|
|
params = {
|
|
username: user_name,
|
|
icq: '',
|
|
aim: '',
|
|
yahoo: '',
|
|
msn: '',
|
|
joined_select: 'lt',
|
|
joined: '',
|
|
count_select: 'eq',
|
|
count: '',
|
|
search_group_id: '0',
|
|
sk: 'c',
|
|
sd: 'a',
|
|
submit: 'Search'
|
|
}
|
|
|
|
res = req(:post, '/memberlist.php?form=postform&field=username_list&select_single=&mode=searchuser', params).to_s
|
|
id = res.match(/u=([0-9]+)">/)
|
|
id && id[1].to_i
|
|
end
|
|
|
|
private
|
|
|
|
# ./ucp.php?i=pm&mode=compose
|
|
def get_pm_form_params
|
|
doc = Nokogiri::HTML(req(:get, '/ucp.php?i=pm&mode=compose').to_s)
|
|
inputs = %w{icon lastclick status_switch post creation_time form_token}
|
|
params = {}
|
|
inputs.each do |i|
|
|
params[i] = doc.at("[name=\"#{i}\"]")['value']
|
|
end
|
|
params
|
|
end
|
|
|
|
def get_login_form_sid
|
|
if match = req(:get, '/ucp.php?mode=login').to_s.match(/name="sid" value="([a-z0-9]+)"/)
|
|
match[1].to_i
|
|
end
|
|
end
|
|
|
|
def req(verb, path, params = {})
|
|
options = {}
|
|
options[:params] = verb == :get ? params : {}
|
|
options[:form] = verb == :post ? params : {}
|
|
|
|
res = HTTP.cookies(@cookies).request(verb, @base_url + path, options)
|
|
res.cookies.each do |cookie|
|
|
@cookies.add cookie
|
|
end
|
|
res
|
|
end
|
|
end
|