Advertisement
Dubslow

UIUC Open Section detector

Jan 5th, 2013
399
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.28 KB | None | 0 0
  1. #! /usr/bin/env python3
  2. courses = []
  3.  
  4. ########################################################################################
  5. # This is a script to detect open sections of classes at UIUC. For every course and CRN
  6. # given, it will check to see if that course is open, and let you know if it is.
  7. # It is meant to be run once by the user, and then every so often it will check again.
  8. #
  9. # You can set how long it waits between each check.
  10. # Please go through the following section and set everything to how you like.
  11. #
  12. # You can choose to have this email you if a section opens up, or just write this fact
  13. # to a file. The former will require some setup (like setting up Thunderbird or Outlook)
  14. # while the latter is perhaps harder to check, or not much better than just doing it
  15. # manually. The default is configured for your illinois.edu address (but others, like
  16. # Gmail, can also be setup as well).
  17. ########################################################################################
  18. #
  19. # Fill this in to suit your needs
  20. # One line per course, multiple CRNs per course is okay
  21. # Copy the format here (including the double parentheses)
  22. # The department and course title must be EXACTLY as displayed at courses.illinois.edu
  23. # They ARE case sensitive
  24. courses.append(('Mathematics', 'Probability Theory', 38063, 40671))
  25. courses.append(('Psychology', 'Intro to Social Psych', 37034, 37040, 37032))
  26.  
  27. # How long to wait between each check
  28. # The more you check, the more likely you'll catch an open section
  29. # But then the people controlling the website might get suspicious
  30. # I recommend 6-12 hour intervals, or absolutely no less than 3 hours
  31. wait_time = 6
  32.  
  33. # Set to False to put results in the file below
  34. # Otherwise results will be emailed
  35. use_email = True
  36.  
  37. # Used if use_email is False
  38. file = 'C:\\Users\\Public\\opencourses.txt'
  39.  
  40. # The email setup
  41. email_domain = 'smtp.illinois.edu'
  42. email_port = 587  # For other emails, this might be 25
  43. email_acct = 'NetID'
  44. email_addr = 'NetID@illinois.edu'
  45. email_pswd = 'ADPassword'
  46.  
  47. # Set this to true if you want the script to send a test email
  48. # This would only happen on the first run, to both make sure the
  49. # script is running and that your email info is setup correctly
  50. send_test_email = True
  51.  
  52. # You should be able to safely ignore everything below here
  53. ########################################################################################
  54. ########################################################################################
  55.  
  56. import re
  57. from time import sleep
  58. from urllib import request, parse, error
  59. from http.cookiejar import CookieJar
  60.  
  61. def main():
  62.      good = []
  63.      for course in courses:
  64.           dpmt, title = course[:2]
  65.           for crn in course[2:]:
  66.                print(dpmt, title, crn)
  67.                request.install_opener(request.build_opener(request.HTTPCookieProcessor(CookieJar())))
  68.                # In my testing, checking two courses wouldn't work on the same cookie *shrug*
  69.                result = is_open(dpmt, title, crn)
  70.                if result > 0:
  71.                     good.append((title, crn))
  72.                elif result < 0:
  73.                     print('Error: something went wrong for {} section {}'.format(title, str(crn)))
  74.      msg = ''
  75.      for title, crn in good:
  76.           msg += '{} section {} is open!\n'.format(title, crn)
  77.      if msg: email('Good news, everyone!', msg)
  78.  
  79. def blogotubes(url):
  80.      req = request.Request(url,
  81.           headers={'User-Agent': 'Open the courses I want!'})
  82.           # Confuse UIUC sysadmins (and make our point clear)
  83.      try:
  84.           contents = request.urlopen(req).read().decode('utf-8')
  85.      except error.URLError as u:
  86.           print(u)
  87.      except error.HTTPError as e:
  88.           print(e)
  89.      else:
  90.           return contents
  91.      return None
  92.  
  93. def geturl(txt, title):
  94.      # Parse the link out of an <a> tag holding "title"
  95.      m = re.search(r'<a href="(.*?)">\s*?{}</a>'.format(title), txt)
  96.      if m: return m.group(1)
  97.      else: return None
  98.  
  99. def parse(page, crn):
  100.      page = page[page.find(str(crn)):] # Shorten the text to everything after the crn
  101.      result = re.search(r'Availability:</div>\s*?<div.*?>(.*?)</div>', page).group(1) # Matches the first occurence
  102.      print(result)
  103.      return 'Open' in result # (Could be restricted)
  104.  
  105. def is_open(dpmt, course, crn):
  106.      base = "http://my.illinois.edu"
  107.      page = blogotubes('http://www.courses.illinois.edu')
  108.      if not page:
  109.           print(page); return -1
  110.      url = geturl(page, 'Class Schedule')
  111.      if not url:
  112.           print(url); return -1
  113.      page = blogotubes(base+url)
  114.      if not page:
  115.           print('lol'+page); return -1
  116.      url = geturl(page, dpmt)
  117.      if not url:
  118.           print(url); return -1
  119.      page = blogotubes(base+url) # Get list of courses in dpmt
  120.      if not page:
  121.           print(page); return -1
  122.      url = geturl(page, course)
  123.      if not url:
  124.           print(url); return -1
  125.      page = blogotubes(base+url) # Get list of sections in course
  126.      if not page:
  127.           print(page); return -1
  128.      result = parse(page, crn) # Parse openness of section
  129.      if result:
  130.           return 1
  131.      else:
  132.           return 0
  133.  
  134. ########################################################################################
  135. # Email stuff
  136. import smtplib
  137. from email.utils import formatdate
  138. from email.mime.multipart import MIMEMultipart
  139. from email.mime.text import MIMEText
  140.  
  141. def send_email(to, sbjct, txt, host, port, acct, pswd, sndr):
  142.     msg = MIMEMultipart()
  143.  
  144.     if isinstance(to, list):
  145.         to = ', '.join(to)
  146.  
  147.     msg['To'] = to
  148.     msg['Subject'] = sbjct
  149.     msg['From'] = sndr
  150.     msg['Date'] = formatdate(localtime=True)
  151.  
  152.     msg.attach(MIMEText(txt))
  153.  
  154.     server = smtplib.SMTP(host, port)
  155.     server.starttls()
  156.     server.login(acct, pswd)
  157.     server.send_message(msg)
  158.  
  159. def email(sbjct, text):
  160.      if use_email:
  161.           send_email(email_addr, sbjct, text, email_domain, email_port, email_acct, email_pswd, email_addr)
  162.      else:
  163.           with open(file, 'a') as f:
  164.                f.write(sjbct+'\n'+text+'\n\n')
  165.  
  166.  
  167. # Now we start actually doing things
  168. if send_test_email:
  169.      email("Open course detector is working", "It appears you've setup the course detecting script fine!")
  170. while True: # Never stop
  171.      main()
  172.      print("Sleeping")
  173.      sleep(wait_time * 3600)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement