Personal project · 2026
Daftaar
A Telegram bot that tells Indian students which government jobs they're eligible for. About 30 students use it.
- Status
- Live on Telegram · private repo
- Users
- About 30 students
- Runs on
- Oracle Cloud free tier ($0/month)
From a new notice to a message in the right chats.
- 01
Sign up in chat
Users sign up inside Telegram with their date of birth, qualification, field of study and home state.
- 02
Collect notices
An hourly pipeline collects recruitment notices. The crawler is capped at 1 request per second and skips pages that haven't changed.
- 03
Rules first
A rules-based parser runs first and cross-checks itself against a second section of the page. It handles 60% of notices without calling an LLM.
- 04
LLM second
Only low-confidence or incomplete results go to an LLM: Claude, Groq or Gemini, swappable, with exponential backoff, rate-limit pacing, resumable batches and a rules-only fallback.
- 05
Match and send
The matching engine checks every user against the notice and sends the official PDF to the ones who qualify.
MATCH, MAYBE or NO.
Every answer is MATCH, MAYBE or NO. MAYBE exists so that incomplete data never wrongly rules anyone out: when the bot isn't sure, it says so instead of guessing.
- Age is worked out as of each notice's own cut-off date, which is why the bot stores a date of birth and not an age.
- OBC, SC and ST age relaxations.
- Diploma and ITI handled as parallel tracks.
- Domicile, from the home state given at sign-up.
- Field-of-study mapping between what a student studied and what a notice asks for.
# each notice has its own reference date,
# that's why we store the DOB and not the age
ref = job.age_as_on or job.apply_end or today
age = age_on(user.dob, ref)
relax = relaxation_for(user.category) # OBC +3, SC/ST +5
if age > job.max_age + relax:
return Verdict.NO, [f"age {age} is above the limit"]
if age > job.max_age: # in, but only just
reasons.append(f"qualifies only with {user.category} relaxation")Built to run unattended, on other people's data.
No overlapping runs
Lock-guarded systemd and cron runs can't overlap or send the same notice twice.
Polite crawling
Capped at 1 request per second, and unchanged pages are skipped.
Sends tested against the real API
A strict test double checks every send against the real Telegram API signature.
Private by default
Date of birth and category are hidden from admin views, built with India's DPDP Act in mind. Users can delete their data from the chat.
Small, live and tested.
- Students using it
- About 30
- Notices parsed without an LLM
- 60%
- Home state found
- 130 of 135
- Tests
- 103
- Python
- About 5k lines
- Hosting cost
- $0 / month
Stack
Hiring?
Send me the role and I'll reply within a day. Remote, full-time or contract, available immediately.