Advertisement
illpastethat

VT Course Add

Apr 22nd, 2013
279
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 5.61 KB | None | 0 0
  1. #!/usr/bin/ruby
  2. require 'rubygems'
  3. require 'mechanize'
  4. require 'nokogiri'
  5. require 'highline/import'
  6. require 'stringio'
  7.  
  8. #Change based on Semester
  9. $term = '09'
  10. $year = '2012'
  11. $frequency = 4  #Number of Seconds between check requests
  12.  
  13. $agent = Mechanize.new
  14. $agent.redirect_ok = true
  15. $agent.user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.11 Safari/535.19"
  16. $agent.verify_mode = OpenSSL::SSL::VERIFY_NONE
  17.  
  18. #Uber simway to colorize outputin
  19. class String
  20.     def color(c)
  21.         colors = {
  22.             :black   => 30,
  23.             :red     => 31,
  24.             :green   => 32,
  25.             :yellow  => 33,
  26.             :blue    => 34,
  27.             :magenta => 35,
  28.             :cyan    => 36,
  29.             :white   => 37
  30.         }
  31.         return "\e[#{colors[c] || c}m#{self}\e[0m"
  32.     end
  33. end
  34.  
  35. #Logins, Gets the Courses, Returns Courses Obj with Name/URL/Tools for each
  36. def login(username, password)
  37.  
  38.     #Login to the system!
  39.     page = $agent.get("https://auth.vt.edu/login?service=https://webapps.banner.vt.edu/banner-cas-prod/authorized/banner/SelfService")
  40.     login = page.forms.first
  41.     login.set_fields({
  42.         :username => username,
  43.         :password => password
  44.     })
  45.     if (login.submit().body.match(/Invalid username or password/)) then
  46.         return false
  47.     else
  48.         return true
  49.     end
  50. end
  51.  
  52. #Gets Course Information
  53. def getCourse(crn) 
  54.     begin
  55.         courseDetails = Nokogiri::HTML( $agent.get(
  56.             "https://banweb.banner.vt.edu/ssb/prod/HZSKVTSC.P_ProcComments?CRN=#{crn}&TERM=#{$term}&YEAR=#{$year}"
  57.         ).body)
  58.     rescue
  59.         return false #Failed to get course
  60.     end
  61.  
  62.     #Flatten table to make it easier to work with
  63.     course = {}
  64.     dataSet = false
  65.  
  66.     course[:title] = courseDetails.css('td.title').last.text.gsub(/-\ +/, '')
  67.     course[:crn] = crn
  68.  
  69.     courseDetails.css('table table tr').each_with_index do |row|
  70.         #If we have a dataSet
  71.         case dataSet
  72.             when :rowA
  73.                 [ :i, :days, :end, :begin, :end, :exam].each_with_index do |el, i|
  74.                     if row.css('td')[i] then
  75.                         course[el] = row.css('td')[i].text
  76.                     end
  77.                 end
  78.             when :rowB
  79.                 [ :instructor, :type, :status, :seats, :capacity ].each_with_index do |el, i|
  80.                     course[el] = row.css('td')[i].text
  81.                 end
  82.         end
  83.  
  84.         dataSet = false
  85.         #Is there a dataset?
  86.         row.css('td').each do |cell|
  87.             case cell.text
  88.                 when "Days"
  89.                     dataSet = :rowA
  90.                 when "Instructor"
  91.                     dataSet = :rowB
  92.             end
  93.         end
  94.     end
  95.  
  96.     return course
  97. end
  98.  
  99. #Registers you for the given CRN, returns true if successful, false if not
  100. def registerCrn(crn)
  101.     #Follow Path
  102.     $agent.get("https://banweb.banner.vt.edu/ssb/prod/twbkwbis.P_GenMenu?name=bmenu.P_MainMnu")
  103.     reg = $agent.get("https://banweb.banner.vt.edu/ssb/prod/hzskstat.P_DispRegStatPage")
  104.     dropAdd = reg.link_with(:href => "/ssb/prod/bwskfreg.P_AddDropCrse?term_in=#{$year}#{$term}").click
  105.  
  106.     #Fill in CRN Box and Submit
  107.     crnEntry = dropAdd.form_with(:action => '/ssb/prod/bwckcoms.P_Regs')
  108.     crnEntry.fields_with(:id => 'crn_id1').first.value = crn
  109.     crnEntry['CRN_IN'] = crn
  110.     add = crnEntry.submit(crnEntry.button_with(:value => 'Submit Changes')).body
  111.  
  112.     if add =~ /#{crn}/ && !(add =~ /Registration Errors/) then
  113.         return true
  114.     else
  115.         return false
  116.     end
  117. end
  118.  
  119. #Main loop that checks the availaibility of each courses and fires to registerCrn on availaibility
  120. def checkCourses(courses)
  121.  
  122.     requestCount = 0
  123.     startTime = Time.new
  124.     loop do
  125.         system("clear")
  126.  
  127.         requestCount += 1
  128.         nowTime = Time.new
  129.  
  130.         puts "Checking Availaibility of CRNs".color(:yellow)
  131.         puts "--------------------------------\n"
  132.         puts "Started:\t#{startTime.asctime}".color(:magenta)
  133.         puts "Now:    \t#{nowTime.asctime}".color(:cyan)
  134.         puts "Request:\t#{requestCount} (Once every #{$frequency} seconds)".color(:green)
  135.         puts "--------------------------------\n\n"
  136.  
  137.         courses.each_with_index do |c, i|
  138.  
  139.             puts "#{c[:crn]} - #{c[:title]}".color(:blue)
  140.             course = getCourse(c[:crn])
  141.             next unless course #If throws error
  142.  
  143.             puts "Availaibility: #{course[:seats]} / #{course[:capacity]}".color(:red)
  144.  
  145.             if (course[:seats] =~ /Full/) then
  146.             else
  147.                 if (registerCrn(c[:crn])) then
  148.                     puts "CRN #{c[:crn]} Registration Sucessfull"
  149.                     courses.slice!(i)
  150.  
  151.                 else
  152.                     puts "Couldn't Register"
  153.                 end
  154.  
  155.             end
  156.  
  157.             print "\n"
  158.         end
  159.  
  160.         sleep $frequency
  161.     end
  162. end
  163.  
  164. #Add courses to be checked
  165. def addCourses
  166.     crns = []
  167.  
  168.     loop do
  169.         system("clear")
  170.         puts "Your CRNs:".color(:red)
  171.         crns.each do |crn|
  172.             puts "  -> #{crn[:title]} (CRN: #{crn[:crn]})".color(:magenta)
  173.         end
  174.  
  175.         #Prompt for CRN
  176.         alt = (crns.length > 0)  ? " (or just type 'start') " : " "
  177.         input = ask("\nEnter a CRN to add it#{alt}".color(:green) + ":: ") { |q| q.echo = true }
  178.  
  179.         #Validate CRN to be 5 Digits
  180.         if (input =~ /^\d{5}$/) then
  181.  
  182.             #Display CRN Info
  183.             c = getCourse(input.to_s)
  184.             puts "\nCourse: #{c[:title]} - #{c[:crn]}".color(:red)
  185.             puts "--> Time: #{c[:begin]}-#{c[:end]} on #{c[:days]}".color(:cyan)
  186.             puts "--> Teacher: #{c[:instructor]}".color(:cyan)
  187.             puts "--> Type: #{c[:type]} || Status: #{c[:status]}".color(:cyan)
  188.             puts "--> Availability: #{c[:seats]} / #{c[:capacity]}\n".color(:cyan)
  189.  
  190.             #Add Class Prompt
  191.             add = ask("Add This Class? (yes/no)".color(:yellow) + ":: ") { |q| q.echo = true }
  192.             crns.push(c) if (add =~ /yes/)
  193.  
  194.         elsif (input == "start") then
  195.             checkCourses(crns)
  196.         end
  197.     end
  198. end
  199.  
  200.  
  201. def main
  202.     system("clear")
  203.     puts "Welcome to CourseAdd by mil".color(:blue)
  204.  
  205.     username = ask("PID ".color(:green) + ":: ") { |q| q.echo = true }
  206.     password = ask("Password ".color(:green) + ":: " ) { |q| q.echo = "*" }
  207.  
  208.     system("clear")
  209.     if login(username, password) then
  210.         addCourses
  211.     else
  212.         puts "Invalid PID/Password"
  213.         exit
  214.     end
  215. end
  216.  
  217. main
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement