Skip to content

shitijkarsolia/ASU-Course-Notifier

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ASU Course Notifier

Automated monitoring system that tracks ASU course availability and sends real-time notifications via Telegram and email when seats open up.

ASU Course Notifier dashboard preview

Python AWS Lambda Docker Telegram

Architecture Overview

The system uses AWS serverless infrastructure to continuously monitor course enrollment and deliver notifications through multiple channels.

flowchart TB
    subgraph Deployment Pipeline
        Dev[Developer]
        Build[Docker Build]
        ECR[AWS ECR]
    end

    subgraph AWS Runtime
        EB[EventBridge<br/>Scheduled Rule]
        Lambda[Lambda Function<br/>Docker Container]
        SNS[AWS SNS Topic]
    end

    subgraph External
        ASU[ASU Catalog API]
        TG[Telegram Bot API]
        Email[Email Subscribers]
    end

    %% Deployment flow
    Dev -->|docker build| Build
    Build -->|docker push| ECR
    ECR -.->|Image URI| Lambda

    %% Runtime flow
    EB -->|Triggers on schedule| Lambda
    Lambda -->|Queries courses| ASU
    ASU -->|Returns enrollment data| Lambda
    Lambda -->|Sends alert| TG
    Lambda -->|Publishes notification| SNS
    SNS -->|Delivers email| Email
Loading

Features

  • Automated Monitoring - Runs on a configurable schedule via EventBridge, checking for open seats without manual intervention
  • Dual Notification Channels - Sends alerts through both Telegram (instant mobile push) and AWS SNS (email delivery)
  • Non-Reserved Seat Detection - Filters out reserved seats to report only seats available for general enrollment
  • Multi-Course Tracking - Monitors multiple courses simultaneously in a single invocation
  • Containerized Deployment - Packaged as Docker images for consistent, reproducible deployments via AWS ECR
  • Two Scraping Approaches - Includes both a REST API client (preferred) and a Selenium-based fallback

Tech Stack

Technology Purpose
Python 3.12 Core application language
AWS Lambda Serverless compute for the monitoring function
Docker Containerized packaging and deployment
AWS ECR Container image registry
AWS EventBridge Scheduled rule to trigger monitoring
AWS SNS Email notification fan-out
Telegram Bot API Real-time mobile push notifications
Pandas Data processing for API response parsing
Selenium + Chrome Headless browser scraping (fallback approach)

How It Works

  1. Trigger - An EventBridge scheduled rule invokes the Lambda function at a configured interval (e.g., every 5 minutes during enrollment windows).

  2. Data Retrieval - The Lambda function queries the ASU catalog API for current enrollment data on the specified courses.

  3. Availability Check - For each monitored course, the function compares enrollment capacity against current enrollment and reserved seats to compute available non-reserved seats.

  4. Notification - When open seats are detected:

    • A Telegram message is sent immediately for real-time mobile alerts
    • An SNS message is published, which triggers email delivery to all topic subscribers
  5. Response - The function returns a summary of findings, enabling CloudWatch logging for audit trails.

Project Structure

ASU-Course-Notifier/
├── .env.example                          # Environment variable template
├── .gitignore
├── README.md
├── docs/
│   └── architecture.md                   # Detailed architecture documentation
└── lambdas/
    ├── api-based/                        # REST API approach (preferred)
    │   ├── Dockerfile
    │   ├── lambda_function.py
    │   └── requirements.txt
    └── selenium-scraper/                 # Selenium scraping approach (fallback)
        ├── Dockerfile
        ├── lambda_function.py
        └── requirements.txt

Two Approaches

This project includes two implementations for retrieving course data:

API-Based (Preferred)

Located in lambdas/api-based/. Queries the ASU catalog REST API directly and parses the JSON response using Pandas. This is the recommended approach because it is:

  • Faster - Direct API calls without browser overhead
  • More Reliable - Not dependent on HTML structure or page rendering
  • Lighter - Smaller container image (~200MB vs ~800MB+)
  • Easier to Maintain - Structured JSON data instead of DOM parsing

Selenium Scraper (Fallback)

Located in lambdas/selenium-scraper/. Uses headless Chrome via Selenium to render the ASU course catalog website and parses the HTML with BeautifulSoup. This approach exists as a fallback if the REST API becomes unavailable or changes its access patterns.

Behavioral Differences

While both lambdas monitor for open seats and send notifications, they differ in behavior:

  • Seat calculation: The API-based lambda computes non-reserved seats (total available minus reserved capacity), giving a more accurate picture of seats you can actually enroll in. The Selenium scraper reports raw available seats as displayed on the page, without subtracting reservations.
  • Telegram notifications: The API-based lambda sends a Telegram message for every course with open seats. The Selenium scraper only sends Telegram notifications for courses whose title appears in the telegram_course_list event parameter, allowing more targeted alerting.
  • Return values: The API-based lambda returns an empty list when no seats are found. The Selenium scraper returns False, so callers need different truthy-check logic depending on which lambda is invoked.

Setup & Deployment

Prerequisites

  • AWS CLI configured with appropriate permissions
  • Docker installed locally
  • A Telegram bot token (create one via @BotFather)
  • An AWS SNS topic with email subscribers configured

1. Configure Environment Variables

Copy the example environment file and fill in your values:

cp .env.example .env

Edit .env with your actual values (see Environment Variables below).

2. Build the Docker Image

docker build --platform linux/amd64 -t asu-course-notifier:latest lambdas/api-based/

3. Push to ECR

aws ecr get-login-password --region $AWS_REGION | \
  docker login --username AWS --password-stdin <your-account-id>.dkr.ecr.$AWS_REGION.amazonaws.com

docker tag asu-course-notifier:latest \
  <your-account-id>.dkr.ecr.$AWS_REGION.amazonaws.com/<your-ecr-repo>:latest

docker push <your-account-id>.dkr.ecr.$AWS_REGION.amazonaws.com/<your-ecr-repo>:latest

4. Update Lambda Function

aws lambda update-function-code \
  --function-name <your-function-name> \
  --image-uri <your-account-id>.dkr.ecr.$AWS_REGION.amazonaws.com/<your-ecr-repo>:latest

5. Configure EventBridge Schedule

Create a scheduled rule in EventBridge to trigger the Lambda function at your desired interval:

aws events put-rule \
  --name "asu-course-check" \
  --schedule-expression "rate(5 minutes)"

aws events put-targets \
  --rule "asu-course-check" \
  --targets "Id"="1","Arn"="<your-lambda-arn>"

Environment Variables

Variable Description Example
TELEGRAM_BOT_TOKEN Telegram bot API token from BotFather 123456:ABC-DEF1234...
TELEGRAM_CHAT_ID Target Telegram chat/group ID -1001234567890
SNS_TOPIC_ARN ARN of the SNS topic for email notifications arn:aws:sns:us-east-1:<account-id>:<topic>
AWS_REGION AWS region for SNS client us-east-1
ASU_TERM ASU term code to monitor 2257 (Fall 2025)

See .env.example for a ready-to-use template.

Local Development

Build and Run Locally

# Build the container
docker build --platform linux/amd64 -t asu-course-notifier:test lambdas/api-based/

# Run with environment variables
docker run --platform linux/amd64 -p 9000:8080 \
  -e TELEGRAM_BOT_TOKEN=$TELEGRAM_BOT_TOKEN \
  -e TELEGRAM_CHAT_ID=$TELEGRAM_CHAT_ID \
  -e SNS_TOPIC_ARN=$SNS_TOPIC_ARN \
  -e AWS_REGION=$AWS_REGION \
  -e ASU_TERM=$ASU_TERM \
  -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
  -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
  asu-course-notifier:test

Invoke the Function

# Trigger the Lambda handler locally
curl -s "http://localhost:9000/2015-03-31/functions/function/invocations" \
  -d '{"course_list": ["64343", "88366"]}'

Run the Selenium Scraper Locally

docker build --platform linux/amd64 -t asu-selenium:test lambdas/selenium-scraper/

docker run --platform linux/amd64 -p 9000:8080 \
  -e TELEGRAM_BOT_TOKEN=$TELEGRAM_BOT_TOKEN \
  -e TELEGRAM_CHAT_ID=$TELEGRAM_CHAT_ID \
  -e SNS_TOPIC_ARN=$SNS_TOPIC_ARN \
  -e AWS_REGION=$AWS_REGION \
  -e ASU_TERM=$ASU_TERM \
  -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
  -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
  asu-selenium:test

Future Improvements

  • Web Dashboard - Add a simple web UI to view monitored courses and notification history
  • Multi-Subject Support - Extend beyond CSE to monitor any ASU department
  • Seat Reservation Tracking - Track reserved vs. unreserved seats over time with historical data
  • Waitlist Monitoring - Alert when waitlist positions change or when courses re-open
  • Configurable Schedules - Allow per-course monitoring frequency via DynamoDB configuration
  • SMS Notifications - Add SMS delivery via SNS for critical alerts
  • Cost Optimization - Implement conditional scheduling (pause during non-enrollment periods)

The original class_search.py was derived from remiliacn/ASU-Class-Search.

About

Serverless AWS Lambda system that monitors ASU course availability and sends Telegram/SNS alerts when seats open.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors