class Lita::Handlers::EspnFantasyFootball

Lita Handler for scraping ESPN's Fantasy Football site

Constants

ESPN_POSITION_MAP

constants

ESPN_STATUS_MAP

Public Instance Methods

activity_timer(_response) click to toggle source
# File lib/lita/handlers/espn_fantasy_football.rb, line 68
def activity_timer(_response)
  Lita.logger.debug('Setting up activity_timer')

  # If config.activity_room wasn't specified, do not set timer
  return unless config.activity_room

  # If config.activity_interval is 0, do not set timer
  return if config.activity_interval.zero?

  every(config.activity_interval) do
    Lita.logger.debug('Running activity_timer')

    # Get last activity from redis or default to start of season
    since = DateTime.parse(redis.get('espn_fantasy_football_last_activity')) rescue DateTime.new(config.season_id.to_i)
    activity = espn_activity_scrape(since)

    if activity && activity.any?
      robot.send_message(Source.new(room: config.activity_room), activity)
    else
      Lita.logger.debug('No new activity found')
    end
  end
end
command_activity(response) click to toggle source
# File lib/lita/handlers/espn_fantasy_football.rb, line 56
def command_activity(response)
  # Get last activity from redis or default to start of season
  since = DateTime.parse(redis.get('espn_fantasy_football_last_activity')) rescue DateTime.new(config.season_id.to_i)
  activity = espn_activity_scrape(since)

  if activity && activity.any?
    response.reply(espn_activity_scrape(since))
  else
    response.reply("No new activity since #{since.to_time}")
  end
end
command_player(response) click to toggle source

chat controllers

# File lib/lita/handlers/espn_fantasy_football.rb, line 31
def command_player(response)
  player = response.matches.first.first
  Lita.logger.debug("#{response.user.name} asked about player #{player}")

  results = espn_player_search(player)

  if results['rows'].any?
    response.reply(format_results(results))
  else
    response.reply("No results found for '#{player}'")
  end
end
command_scoreboard(response) click to toggle source
# File lib/lita/handlers/espn_fantasy_football.rb, line 44
def command_scoreboard(response)
  week = response.matches.first[1]
  Lita.logger.debug("#{response.user.name} requested scoreboard for week '#{week}'")

  if week.empty? || (week.to_i >= 1 && week.to_i <= 13)
    matchups = espn_scoreboard_scrape(week)
    response.reply(format_results(matchups))
  else
    response.reply('Please specify a week from 1 - 13')
  end
end
espn_activity_scrape(since = DateTime.new(config.season_id.to_i)) click to toggle source
# File lib/lita/handlers/espn_fantasy_football.rb, line 227
def espn_activity_scrape(since = DateTime.new(config.season_id.to_i))
  resp = []
  params = {
    'leagueId' => config.league_id,
    'seasonId' => config.season_id
  }

  param_string = params.map { |key, val| "#{key}=#{val}" }.join('&')
  url = "http://games.espn.go.com/ffl/recentactivity?#{param_string}"
  Lita.logger.debug("Searching for league activity at #{url}")
  page = Nokogiri::HTML(open(url))

  # get activity and remove header rows
  activity = page.xpath('//*[@class="games-fullcol games-fullcol-extramargin"]/table/tr').drop(2)

  activity.each do |a|
    # Parse timestamp
    timestamp = DateTime.parse("#{a.css('td')[0].children[0].text} #{a.css('td')[0].children[2].text}")

    # Exit loop if we've passed the datetime passed into method
    break if timestamp <= since

    type = a.css('td')[1].children[1].text
    subtype = a.css('td')[1].children[4].text
    detail = a.css('td')[2].inner_html
              .delete('*') # remove asterisks, as they'll conflict with markdown
              .gsub(%r{<(/)?b>}, '*') # convert bold formatting
              .gsub(/<br>/, "\n") # convert breaks to newlines
    events = detail.split("\n")

    # add emoji
    if type == 'LM Changed League Settings'
      events.map! { |ev| ":gear: #{ev}" }
    elsif type == 'Transaction'
      events.map! do |ev|
        ev.gsub(/(\S+\sadded)/, ':green_heart: \\1')
          .gsub(/(\S+\sdropped)/, ':broken_heart: \\1')
          .gsub(/(\S+\straded)/, ':revolving_hearts: \\1')
          .gsub(/(\S+\sdrafted)/, ':heavy_plus_sign: \\1')
      end
    elsif type == 'Trophy Assigned'
      # subtype has more info in it than detail alone
      events = [
        "#{subtype.gsub(/.*(awarded to)/, ':trophy: \\1')} — #{detail}"
      ]
    end

    resp << events.join("\n")

    # Update redis timestamp if newer than latest activity
    latest_activity = DateTime.parse(redis.get('espn_fantasy_football_last_activity')) rescue DateTime.new(config.season_id.to_i)
    redis.set('espn_fantasy_football_last_activity', timestamp.to_s) if timestamp > latest_activity
  end

  # events are latest-first on espn, but we want to post earliest-first
  resp.reverse
end
espn_scoreboard_scrape(week) click to toggle source
# File lib/lita/handlers/espn_fantasy_football.rb, line 186
def espn_scoreboard_scrape(week)
  resp = {
    'headers' => %w[
      team
      score
    ],
    'rows' => []
  }

  params = {
    'leagueId' => config.league_id,
    'seasonId' => config.season_id
  }

  # If no period (aka, week) is specified, ESPN defaults to the
  # most recent (aka, current) matchup period
  params['matchupPeriodId'] = week unless week.empty?

  param_string = params.map { |key, val| "#{key}=#{val}" }.join('&')
  url = "http://games.espn.go.com/ffl/scoreboard?#{param_string}"
  Lita.logger.debug("Searching for score at #{url}")

  page = Nokogiri::HTML(open(url))
  matchups = page.xpath('//*[@class="ptsBased matchup"]')

  resp['rows'] = matchups.map do |m|
    rows = m.css('tr')
    team_top = rows[0].css('td.team div.name a').text
    team_bottom = rows[1].css('td.team div.name a').text
    score_top = rows[0].css('td.score').text
    score_bottom = rows[1].css('td.score').text

    {
      'team'  => "#{team_top}\n#{team_bottom}\n ",
      'score' => "#{score_top}\n#{score_bottom}\n "
    }
  end

  resp
end
format_results(raw) click to toggle source
# File lib/lita/handlers/espn_fantasy_football.rb, line 285
def format_results(raw)
  rows = raw['rows'].map { |r| r.map { |_k, v| v } }
  table = Terminal::Table.new(headings: raw['headers'], rows: rows)
  "```\n#{table}\n```"
end
troll_response() click to toggle source

helper methods

# File lib/lita/handlers/espn_fantasy_football.rb, line 112
def troll_response
  [
    'Your request was bad and you should feel bad.',
    'Stop wasting my time with your bullshit.',
    'Was that even English?'
  ].sample
end