#!/usr/bin/env ruby # Plugin to announce new posts in the channel class Hackerthreads require 'net/http' # HTTP requests require 'nokogiri' # XML/HTML parsing # This method is called when the plugin is first loaded def initialize( status, config, output, irc, timer ) @status = status @config = config @output = output @irc = irc @timer = timer # Post announce settings @channel = "#hackerthreads" @rss_host = "www.hackerthreads.org" @rss_path = "/rss.php" @timeout = 120 @last = "" # Pending post announce settings @conf_file = 'hackerthreads.json' @conf_pending = [] @reports = [] @reported_empty = false load_config # Kick off threads if( @status.threads && @config.threads) @rss_thread = Thread.new{ check_rss } @pen_thread = Thread.new{ check_pending } end end # Method to be called when the plugin is unloaded def unload if( @status.threads && @config.threads) @rss_thread.exit @pen_thread.exit end return true end # Default method def main( _nick, _user, _host, _from, _msg, _arguments, _con ) check_rss end private # Thread to check for new posts def check_rss loop do begin # Grab rss xml = Net::HTTP.get( @rss_host, @rss_path ) xml = Nokogiri::XML( xml ) # Parse out info title, link = "", "" title = xml.xpath( '//item/title' ).first.text link = xml.xpath( '//item/link' ).first.text author = xml.xpath( '//item/author' ).first.text if( author =~ /\((.+?)\)$/ ) author = $1 end # Check if this is a new post if( @last != link ) @last = link # If the tinyurl plugin is loaded, use it if( @status.checkplugin( "tinyurl" ) ) plugin = @status.getplugin( "tinyurl" ) link = plugin.main( nil, nil, nil, nil, nil, link, false ) end @irc.message( @channel, "New post by #{author} | #{title} | #{link}" ) end rescue # Silently fail @output.debug( "Failure while retreiving rss feed.\n" ) end # Wait for a bit before fetching again sleep( @timeout ) end end # Check posts pending approval def check_pending loop do begin base_url = @conf_pending['phpbb']['url'] # Get authenticated sid = '' uri = URI( "#{base_url}#{@conf_pending['phpbb']['ucp']}?mode=login" ) req = Net::HTTP::Post.new( uri ) req.set_form_data( 'username' => @conf_pending['phpbb']['auth']['user'], 'password' => @conf_pending['phpbb']['auth']['pass'], 'redirect' => 'index.php', 'login' => 'Login' ) res = Net::HTTP.start( uri.hostname, uri.port ) do |http| http.request( req ) end if( res.get_fields( 'set-cookie' ).last =~ /^phpbb3_kjrto_sid=([0-9a-f]{32});/ ) sid = $1 else raise Exception.new( "Could not get a phpbb session." ) end # Retreive pending posts page uri = URI( "#{base_url}#{@conf_pending['phpbb']['mcp']}" ) params = { :i => 'main', :mode => 'front', :sid => sid } uri.query = URI.encode_www_form( params ) res = Net::HTTP.get_response( uri ) # Parse reponse html_doc = Nokogiri::HTML( res.body ) if( html_doc.css('form#mcp_queue p').to_s =~ /no posts waiting for approval/ ) if( not @reported_empty ) @reports = [] report_pending( 'No pending posts in queue.' ) @reported_empty = true end else html_doc.css('form#mcp_queue ul.topiclist li.row').each do |e| report_pending( "Pending post \"#{e.css('a')[0].inner_html}\" by \"#{e.css('a')[1].inner_html}\" in \"#{e.css('a')[4].inner_html}\"" ) end @reported_empty = false end rescue Exception => e # Silently fail @output.debug( "Failure while retreiving pending posts.\n" ) @output.debug_extra( "#{e.inspect}\n" ) end # Wait for a bit before fetching again sleep( @conf_pending['fetch']['repeat'] ) end end # Reporting function for pending messages def report_pending( message ) # Check if new if( !@reports.include? message ) @reports.push( message ) # Notify @conf_pending['report'].each do |r| case r['type'] when "notice" @irc.notice( r['to'], message ) when "message" @irc.message( r['to'], message ) end end end end # Load config for pending post checks def load_config if File.exist?( @config.datadir + '/' + @conf_file ) jsonline = "" File.open( @config.datadir + '/' + @conf_file ) do |file| file.each do |line| jsonline << line end end @conf_pending = JSON.parse( jsonline ) end end end