#!/usr/bin/env ruby

# Add the path to your feedcache directory here
FCPIPES_DIR = '/path/to/your/feedcache-pipes/plugin/directory'
# How many characters from each feed item do you want to display (only used if formatting feed titles)
TITLE_CHAR_COUNT = 75
EXCERPT_CHAR_COUNT = 400
# Set to 'true' if you want to receive error emails from the CRON job
CRON_EMAILS = false
MYSQL_SOCKET = '/tmp/mysql.sock' # change this if your mysql socket is different

#################################################################
#                                                               #
#  DO NOT EDIT BELOW THIS LINE                                  #
#                                                               #
#################################################################
$:.unshift File.join( File.dirname(__FILE__), 'lib', 'feedtools-0.2.29', 'lib' )
$:.unshift File.join( File.dirname(__FILE__), 'lib', 'activerecord-2.2.2', 'lib' )

require 'rubygems'
require 'active_record'
require 'feed_tools'
require 'yaml'
require 'iconv'

XML_DIR = "#{FCPIPES_DIR}/files"

# Read config settings
CONFIG_FILE = "#{FCPIPES_DIR}/fcpipes-config.yml"
@yaml_config = YAML.load_file( CONFIG_FILE )
WPDB_PREFIX = @yaml_config['db_prefix']
@link_target = @yaml_config['target_blank'] ? '_blank' : '_self'

ActiveRecord::Base.establish_connection(
  :adapter  => 'mysql',
  :socket   => MYSQL_SOCKET,
  :host     => @yaml_config['db_host'],
  :username => @yaml_config['db_user'],
  :password => @yaml_config['db_password'] || '',
  :database => @yaml_config['db_name']
)

class WPFeed < ActiveRecord::Base
  set_table_name "#{WPDB_PREFIX}fcpipes_data"
end

class String
  def to_ascii_iconv
    converter = Iconv.new('ASCII//IGNORE//TRANSLIT', 'UTF-8')
    converter.iconv(self).unpack('U*').select { |cp| cp < 127 }.pack('U*')
  end
  def strip_html
    self.gsub(/<\/?[^>]*>/, "")
  end
end

# RSS formatting function
def shorten_text( txt, cnt=TITLE_CHAR_COUNT )
  return '' if txt.nil?
  if txt.size > cnt
    text = "#{txt} ".slice( 0, cnt )
    # need to break on the last space
    if text.include?(' ') and text.slice(text.size-1, 1) != ' '
      text = text.slice(0, text.size - (text.reverse.index(' ') + 1))
      text << '...'
    end
    return text
  else
    return txt
  end
end

def log_error(err, msg="Error caught")
  if CRON_EMAILS
    puts msg
    puts err.inspect
    puts err.backtrace
  end
end

def generate_xml_feed( items, count, url, group=1, strip_html=false )
  begin
    fname = "#{XML_DIR}/group#{group}.xml"

    feed = FeedTools::Feed.new
    feed.title = "FeedCache Pipes XML Feed"
    feed.link =  url
    feed.description = "FCPipes Feed for Group #{group}"
    feed.author = "FeedCacpe Pipes Wordpress Plugin"

    idx = 1
    items.sort {|a,b| b[0]<=>a[0]}.each do |key, item|
      break if idx > count
      entry = FeedTools::FeedItem.new
      entry.title = strip_html ? item.title.strip_html : item.title
      entry.link = item.link
      entry.content = strip_html ? item.content.strip_html : item.content
      entry.author = item.author
      entry.published = item.published
      feed.entries << entry
      idx += 1
    end

    xml = feed.build_xml
    File.open( fname, 'w' ) { |f| f.write( xml ) }
  rescue => e
    log_error( e, "Error generating XML feed output - Group #{group}" )
  end
end

begin # read the config files settings
  @all_feeds, @feed_excerpts, @display_count, @feed_urls = {}, {}, {}, {}
  1.upto(@yaml_config['group_num']) do |num|
    next if @yaml_config["group#{num}"].nil?
    feeds = []
    @yaml_config["group#{num}"]['feeds'].each { |x| feeds << x.strip if (!x.nil? && !x.strip.blank?) }
    @all_feeds[num] = feeds
    @feed_excerpts[num] = @yaml_config["group#{num}"]["excerpt"] || false
    @display_count[num]  = ( @yaml_config["group#{num}"]['count'].to_i > 0 ) ? @yaml_config["group#{num}"]['count'].to_i : @display_num
    @feed_urls[num] = @yaml_config["group#{num}"]['feed_url']
    feeds = nil
  end
rescue => e
  log_error(e, "Error reading YAML configuration file")
end  

# process the feed list
@entry_groups = {}
@all_feeds.each do |k, v| # k => group_num, v => [feed list]
  entries = {}
  # parse the feeds
  v.each do |feed|
    begin
      fp = FeedTools::Feed.open(feed)
      fp.items.each do |item|
        entries[item.published.to_i] = item
      end
    rescue Exception => e
      log_error(e, "Error processing feed - #{feed}")
    end
  end
  @entry_groups[k] = entries
end #--> @all_feeds.each do |k,v|
  
# now process each group by timestamp
@entry_groups.each do |k,v| # k => group_num, v => { timestmp => feed data }
  tmp, processed, count = '', false, 1
  html_text = "<ul class='fcpipes'>"
  
  generate_xml_feed( v, @display_count[k], @feed_urls[k], k, @yaml_config["group#{k}"]['strip_html'] ) if @feed_excerpts[k]
   
  begin
    # sort entries by timestamp and process
    v.sort {|a,b| b[0]<=>a[0]}.each do |key, item|
      break if count > @display_count[k]
      output, link_title = '', ''
      excerpt = shorten_text( item.content, EXCERPT_CHAR_COUNT ).gsub(/<\/?[^>]*>/, '').gsub(/\"|\'/, '')
      link_title = excerpt unless @feed_excerpts[k]
      output = "<li><a href='#{item.link}' target='#{@link_target}' title='#{link_title}'>"
      if @yaml_config['format_text']
        txt = "#{ item.title.downcase.gsub(/^[a-z]|\s+[a-z]/) {|a| a.upcase} }"
        output << ( @yaml_config["group#{k}"]['strip_html'] ? shorten_text( txt.strip_html ) : shorten_text( txt ) )
      else 
        output << ( @yaml_config["group#{k}"]['strip_html'] ? item.title.strip_html : item.title )
      end
      output << '</a>'
      if @feed_excerpts[k]
        output << "&nbsp;&nbsp;<span class='rssSummary fcpies-rss-excerpt'>#{excerpt}</span>"
      end
      output << "</li>\n"
      html_text << output
      output = nil
      count += 1
    end
    
    html_text << "</ul><br />\n"
    tmp << html_text
    processed, html_text = true, nil
  rescue => e
    log_error(e, "Error processing feed - Group #{k.to_i} - #{v}")
  end

  # if we had new feeds, move them to the database
  if processed
    wp_data = WPFeed.find_or_initialize_by_group_id(k)
    wp_data.update_attributes(:data => tmp, :updated_at => Time.now)
  end
end # end @entry_groups.each do |k,v|
