Skip to content

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)
Open the bot on TelegramPrivate repo, happy to walk you through it
How it works

From a new notice to a message in the right chats.

  1. 01

    Sign up in chat

    Users sign up inside Telegram with their date of birth, qualification, field of study and home state.

  2. 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.

  3. 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.

  4. 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.

  5. 05

    Match and send

    The matching engine checks every user against the notice and sends the official PDF to the ones who qualify.

Matching engine

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.
jobs/matching.py
# 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")
Reliability and privacy

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.

By the numbers

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

PythonDjango 5SQLitepython-telegram-bothttpxselectolaxClaude / Groq / Geminipytestsystemd + cronOracle Cloud free tier

Hiring?

Send me the role and I'll reply within a day. Remote, full-time or contract, available immediately.