Automation.
Small serverless pipelines that remove repetitive work and run themselves. The flagship: a bot that watches my university's notice board so I never have to.
AIUB Notice Board
An AI-powered Telegram bot that watches the American International University-Bangladesh notices page and pings me the moment a new notice appears — already categorized and summarized in one line. It runs entirely on GitHub Actions, four times a day, with no server, no database and no API bill. $0 a month.
/ month
09 · 13 · 17 · 21 Dhaka
categories
free tier: 150
How it works.
Students and staff used to refresh the AIUB notices page hoping to catch
something important in time. The bot replaces that habit with a single
Telegram chat that only ever speaks when there's genuinely new news.
Each run is a short four-step pipeline, orchestrated by src/main.py.
-
1
Scrapesrc/scraper.py
Reads the AIUB notices listing as static HTML with BeautifulSoup, extracting each notice's title, date and detail-page URL.
-
2
Deduplicatestate/seen.json
Every scraped notice is checked against
seen.json. Only ones never seen before move forward — so nothing is sent twice, and nothing is missed even if a scheduled run is skipped. -
3
Classify & summarizesrc/classifier.py
Each new notice is sent to GitHub Models (free, via the workflow's
GITHUB_TOKEN) to assign one of eight categories and write a one-line summary. A keyword fallback keeps things sensible if the model is unavailable. -
4
Notify & persistsrc/notifier.py
Sends one Telegram message per new notice, then commits the updated
seen.jsonand alast_check.txtheartbeat back to the repo — keeping dedup persistent and the schedule alive.
Architecture.
There is no backend to maintain. A GitHub Actions cron job is the entire runtime: it boots a fresh runner four times a day, runs the pipeline, talks to three external services, and commits its own state back to the repository.
State is the clever part. Every run commits seen.json and a
last_check.txt heartbeat back to the repository. The heartbeat resets
GitHub's 60-day inactivity timer — so the scheduled workflow never gets
auto-disabled — while seen.json gives a serverless job the persistent
memory it would otherwise lack.
First-run seeding
On setup the bot silently records the ~20 existing notices with no messages, then only alerts on genuinely new ones.
Flood guard
If a run finds an abnormal burst of "new" notices, it re-seeds instead of flooding your chat — covering site redesigns and long downtime.
Fail-safe state
If scraping returns zero notices, main.py exits with an error and refuses to overwrite state — a layout change can't wipe history.
No run loops
State pushes use the built-in GITHUB_TOKEN, which doesn't trigger new workflow runs — preventing cascading automation.
Single run at a time
A concurrency group ensures only one workflow instance runs at once, so overlapping schedules can't race on state.
Free forever
Public-repo Actions minutes are unlimited and the free GitHub Models tier (150 calls/day) dwarfs the bot's ~20 — no paid keys, DB or server.
More automation.
Other scripts & pipelines that take repetitive work off my plate. More case studies on the way.