dudemcbacon/goodwill

View on GitHub
lib/goodwill/account.rb

Summary

Maintainability
A
45 mins
Test Coverage
# frozen_string_literal: true

require 'goodwill/auction'
require 'goodwill/mechanize'
require 'goodwill/urlpaths'
require 'goodwill/csspaths'

require 'json'
require 'mechanize'
require 'parallel'

module Goodwill
  #
  # Allows for basic account interaction
  #
  class Account
    include Goodwill::Mechanize
    include URLPaths
    include CSSPaths

    PER_PAGE = 25

    attr_reader :username, :password, :threads

    def initialize(username, password = '', threads = 10)
      @username  = username
      @password  = password
      @threads   = threads
      Goodwill::Mechanize.username = @username
      Goodwill::Mechanize.password = @password
    end

    def in_progress
      in_progress_page = mechanize.get(OPEN_ORDERS_URL)
      Parallel.map(in_progress_page.search(IN_PROGRESS_ROWS), in_threads: @threads) do |row|
        Goodwill::BiddingAuction.new(itemid_from_open_order_row(row), mechanize)
      end
    end

    def search(item_title)
      search_page = mechanize.get(SEARCH_URL + item_title)
      Array.new(pages(total_items(search_page))) do |i|
        search_page = search_page.link_with(text: '>').click unless i.zero?
        Parallel.map(search_page.search(SEARCH_ROWS), in_threads: @threads) do |row|
          Goodwill::Auction.new(itemid_from_search_row(row))
        end
      end.flatten
    end

    def bid(itemid, bid)
      item = mechanize.get(ITEM_SEARCH_URL + itemid.to_s)
      href = item.search(SELLER_ID_LINK).attribute('href').value
      seller_id = href.split('/').last

      params = {
        itemId: itemid,
        bidAmount: bid,
        quantity: 1,
        sellerId: seller_id
      }

      # bidresult
      # 1 - success (check message for 'Bid Received!')
      # 1 - outbid (check message for 'You have already been outbid.')
      # -5 - bid less than minimum
      mechanize.get(BID_URL, params) do |page|
        res = JSON.parse(page.body)
        case res['BidResult']
        when 1
          return true if res['BidResultMessage'].include?('Bid Received')

          return false if res['BidResultMessage'].include?('You have already been outbid.')

          raise Goodwill::BidError, res['BidResultMessage']
        when -5
          raise Goodwill::BidError, res['BidResultMessage']
        end
      end
    end

    private

    def buyer_token
      mechanize.cookies.select { |c| c.name == 'AuthenticatedBuyerToken' }.first.value
    end

    def itemid_from_open_order_row(row)
      row.search('a').text
    end

    def itemid_from_search_row(row)
      row.search('a').first.attributes['href'].value.split('/').last
    end

    def pages(items)
      (items / 40.to_f).ceil
    end

    def request_token
      mechanize.cookies.select { |c| c.name == '__RequestVerificationToken' }.first.value
    end

    def total_items(page)
      return 0 unless page.search(NO_ITEMS_FOUND_PATH).empty?

      page.search(ITEMS_COUNT_PATH).first.text.split(' of ')[1].split(' ').first.to_i
    end
  end
end