class Ubcbooker::Scraper::Cs

Constants

CS_BOOK_URL
CS_ROOMS
CS_ROOM_BASE_URL

Public Instance Methods

ampm_to_time(str) click to toggle source

05:00pm -> 17:99

# File lib/ubcbooker/scrapers/cs.rb, line 170
def ampm_to_time(str)
  time = Time.parse(str)
  return time.strftime("%H:%M")
end
batch_request(room_list, book_date) click to toggle source
# File lib/ubcbooker/scrapers/cs.rb, line 73
def batch_request(room_list, book_date)
  cookie = @agent.cookies.join("; ")
  spinner = get_spinner("Checking room availabilities")

  hydra = Typhoeus::Hydra.new
  requests = room_list.map do |room_id|
    room_url = get_room_cal_url(book_date, room_id)
    request = Typhoeus::Request.new(room_url, headers: { Cookie: cookie })
    hydra.queue(request)
    request
  end
  hydra.run # Start requests
  spinner.success("Done!")
  return typhoeus_to_mechanize(requests)
end
book(options) click to toggle source
# File lib/ubcbooker/scrapers/cs.rb, line 10
def book(options)
  login
  title = options[:name]
  book_date = Date.parse(options[:date])
  book_slot = get_time_slot(options[:time])

  room_pages = batch_request(CS_ROOMS, book_date)
  room_pages.select! { |r| is_available(r, book_date, book_slot) }

  if room_pages.any?
    # TODO: If -c CHOOSE option then run CLI-UI here
    room = room_pages.first  # Choose the first available room
    submit_booking(room, title, book_date, book_slot)
    return get_room_page_id(room)
  else
    raise Ubcbooker::Error::NoAvailableRoom.new(options[:time])
  end
end
get_date_div_id(date) click to toggle source
# File lib/ubcbooker/scrapers/cs.rb, line 148
def get_date_div_id(date)
  date_div_base = "calendar_space_entity_project_room-"
  date_div_base += "#{date.year}-#{date.strftime("%m")}-#{date.strftime("%d")}-0"
  return date_div_base
end
get_room_cal_url(book_date, room_id) click to toggle source
# File lib/ubcbooker/scrapers/cs.rb, line 89
def get_room_cal_url(book_date, room_id)
  if CS_ROOMS.include?(room_id)
    room_url = CS_ROOM_BASE_URL + "ICCS" + room_id
    if is_next_month(book_date)
      today = Date.today
      month_query = "?month=" + today.year + "-" + (today.month + 1)
      return room_url + month_query
    else
      return room_url
    end
  end
end
get_room_page_id(page) click to toggle source
# File lib/ubcbooker/scrapers/cs.rb, line 69
def get_room_page_id(page)
  return page.form.action.split("/").last
end
get_slot_booked(room_page, book_date) click to toggle source
# File lib/ubcbooker/scrapers/cs.rb, line 132
def get_slot_booked(room_page, book_date)
  day_div_id = get_date_div_id(book_date)
  day_div = room_page.search("td##{day_div_id}").first
  slot_num = day_div.search("div.item").size
  start_times = day_div.search("span.date-display-start")
  end_times = day_div.search("span.date-display-end")

  slot_booked = []
  (0..slot_num-1).each do |i|
    slot_start = ampm_to_time(start_times[i].text) # 01:00
    slot_end = ampm_to_time(end_times[i].text) # 05:00
    slot_booked.push((slot_start..slot_end))
  end
  return slot_booked
end
get_spinner(text) click to toggle source
# File lib/ubcbooker/scrapers/cs.rb, line 154
def get_spinner(text)
  spinner = ::TTY::Spinner.new("[:spinner] #{text} ... ", format: :dots)
  spinner.auto_spin # Automatic animation with default interval
  return spinner
end
get_time_slot(time_str) click to toggle source

Expect HH:MM-HH:MM

# File lib/ubcbooker/scrapers/cs.rb, line 164
def get_time_slot(time_str)
  times = time_str.split("-")
  return (times[0]..times[1])
end
is_available(room_page, book_date, book_slot) click to toggle source
# File lib/ubcbooker/scrapers/cs.rb, line 115
def is_available(room_page, book_date, book_slot)
  slot_booked = get_slot_booked(room_page, book_date)
  return !is_slot_booked(slot_booked, book_slot)
end
is_next_month(date) click to toggle source
# File lib/ubcbooker/scrapers/cs.rb, line 111
def is_next_month(date)
  return date.month != Date.today.month
end
is_slot_booked(slot_booked, book_slot) click to toggle source
# File lib/ubcbooker/scrapers/cs.rb, line 120
def is_slot_booked(slot_booked, book_slot)
  booked = false
  slot_booked.each do |s|
    if (s.include?(book_slot.min) ||
        s.include?(book_slot.max) ||
        book_slot.include?(s))
      booked = true
    end
  end
  return booked
end
login() click to toggle source
# File lib/ubcbooker/scrapers/cs.rb, line 29
def login
  spinner = get_spinner("Logging into CWL")
  booking_url = BOOKING_URL[:cs]
  @agent.get(booking_url) do |page|
    login_page = page.link_with(text: "CWL Login Redirect").click
    login_ubc_cwl(login_page)
  end
  spinner.success("Done!") # Stop animation
end
select_room_option(booking_form, page) click to toggle source

Select the form otpion with right room id

# File lib/ubcbooker/scrapers/cs.rb, line 59
def select_room_option(booking_form, page)
  room_id = get_room_page_id(page)
  select_options = booking_form.field_with(name: "field_space_project_room[und]").options
  select_options.each do |o|
    if o.text.include?(room_id)
      o.click
    end
  end
end
submit_booking(room, title, book_date, book_slot) click to toggle source
# File lib/ubcbooker/scrapers/cs.rb, line 39
def submit_booking(room, title, book_date, book_slot)
  spinner = get_spinner("Submitting booking request")
  booking_form = @agent.get(CS_BOOK_URL).forms[1]
  booking_form["title"] = title
  book_date_str = book_date.strftime("%Y/%m/%d")  # ex 2018/03/08
  select_room_option(booking_form, room)
  booking_form["field_date[und][0][value][date]"] = book_date_str
  booking_form["field_date[und][0][value][time]"] = time_to_ampm(book_slot.min)
  booking_form["field_date[und][0][value2][date]"] = book_date_str
  booking_form["field_date[und][0][value2][time]"] = time_to_ampm(book_slot.max)
  confirmation_page = booking_form.submit
  if confirmation_page.search("div.alert-error").empty?
    spinner.success("Done!")
  else
    spinner.fail("Booking rejected")
    raise Ubcbooker::Error::BookingFailed.new
  end
end
time_to_ampm(str) click to toggle source

17:00 -> 05:00pm

# File lib/ubcbooker/scrapers/cs.rb, line 176
def time_to_ampm(str)
  time = Time.parse(str)
  return time.strftime("%I:%M%P")
end
typhoeus_to_mechanize(requests) click to toggle source

Turn typhoneus obj to mechanize page obj

# File lib/ubcbooker/scrapers/cs.rb, line 103
def typhoeus_to_mechanize(requests)
  pages = requests.map do |request|
    html = request.response.body
    Mechanize::Page.new(nil, {"ontent-type" => "text/html"}, html, nil, @agent)
  end
  return pages
end