If you've ever fired off "I can build that" within thirty seconds of seeing "looking for someone to make a landing page" in a Telegram chat, you already know freelance work's dirty little secret: whoever replies first usually gets the conversation. A developer who takes orders for websites and Telegram bots turned that reflex into a working setup for AI lead generation — a Python robot that watches dozens of chats and social feeds, throws out the junk, scores every promising post with a language model, and sends him a private card with a rating and a draft first reply. The whole thing is capped at $30 a month.
He wrote the build up on Habr, where it's picked up a healthy readership. Here's what the system actually does, why the robot is only allowed to talk to its owner, and how to copy the same idea — by hand this week, or with a weekend of Python if you're the tinkering type.
What happened
Four sources, one pipe
The radar drinks from four taps. A Telethon userbot — that's an ordinary Telegram user account where a script presses the buttons instead of a human thumb — sits in several dozen niche chats. A browser-based scraper on his Mac reads Threads and Instagram; he created a separate Instagram account for it, which also happens to be the key that opens Threads. The fourth tap was an RSS feed from a freelance job board (more on why he killed it below).
All four pour into one pipe: source → dictionary (no AI involved) → dedupe → "waiting for AI" queue → classifier → a card in Telegram.
He bought a separate phone number for the userbot rather than risk his main Telegram account, and made the same call with the throwaway Instagram profile. Cheap insurance.
The first filter costs nothing
Chats are loud. Handing every single message to a language model would burn the budget before lunch, so gate number one is a dumb keyword filter. A config file carries two lists: phrases like "need a website," "looking for a developer," "who can build a landing page," and stop words like "vacancy," "looking for work," and "offering services." A message gets through only if at least one phrase hits and no stop word does.
It's the bouncer at the door, not the detective inside. Everything interesting happens after.
Why "need a website" is harder than it looks
Exact string matching falls apart the second a real person types. "Need a Telegram bot." "Looking for an experienced fitter." "Who'll build the site?" Word order shifts, case endings pile up, people stuff extra words in the middle. So he reduces words to their stems — lowercase everything, normalize the letter ё to е, slice the common case endings off nouns and adjectives, keep a floor of three characters so short words don't get shredded — and leaves verbs alone on purpose. Trim a verb and "to make" starts colliding with half the dictionary.
He also allows a gap between the parts of a phrase. The window is configurable, so a couple of stray words between "need" and "site" don't kill the match — "need a quick site" still scores.
Dedupe, queue, classify
Once a message clears the dictionary it gets deduped, because the same gig cross-posted across five feeds shouldn't show up as five leads. Then it waits in a queue for the classifier — a language model reached through the official `openai` SDK pointed at OpenRouter — which rates the post and drafts an opening reply. The result arrives in his DMs as a card. He answers by hand, every time.
The stack is deliberately boring: Python, Telethon for the userbot, aiogram 3 for the bot that mails the cards, SQLite for storage, aiohttp for incoming HTTP, all running as one Docker process.
One recipient, hard-coded into the code
This is the part worth stealing. The robot never messages strangers. Cold-DMing at scale gets a Telegram account banned fast, and blasting people who never opted in can land you in legal trouble under advertising rules. So every outbound message in the codebase has exactly one addressee — his own chat_id — and all sending lives in a single module. The other modules don't even import the Telegram library, which means they physically can't message anyone else. He didn't trust willpower. He trusted an import statement.
Three places it hurt
First, the event loop locked up — the async engine that keeps everything moving seized, and messages stopped flowing. Second, the model occasionally returned invalid JSON, so the parser choked on responses it couldn't read. Third, a burst of findings arrived faster than the receiving server would accept them. Notice what's on that list: plumbing, not intelligence. That's the honest lesson of the build.
What the live numbers say
The hard cap is $30 a month, and that number is the real headline — the whole architecture is shaped around not blowing it. He also switched off the freelance job board's RSS feed. A source that mostly produces noise is a source you cut, even when it feels like it ought to work.
That same "cheap filter first, expensive brain last" pattern fits a dozen everyday jobs you'd never call lead generation. And if you just want to test the classifier half without building anything, there are free AI tools at MyKreaTool you can poke at first.
What it means for you
At home: the spare-room ad
Rent out a room, flip furniture, teach piano out of the front room — the buyers are already typing "does anyone know someone who..." into neighborhood groups. You don't need a scraper; you need the phrase list, so you know exactly what to watch for and can answer inside a minute.
At work: stop refreshing five tabs
If you're freelance, the radar replaces the 11 p.m. tab-hopping ritual. The dictionary runs free, the model only touches messages that already look like demand, and the card arrives with a draft so your reply takes thirty seconds instead of ten minutes.
In business: lead gen on a coffee budget
A two-person agency can't hire a sales team, but it can spend $30 a month. The one-recipient rule also means nobody on your team accidentally blasts a list and torches the company account.
When you're studying: tutoring and gig work
Students hunting tutoring clients or editing gigs sit in exactly the same chats. Same phrases, different stop words, and the first useful reply still wins.
For creators: the "who can edit this?" post
Every creator group has a weekly "anyone know a good editor, thumbnail artist, voice-over?" thread. The person who answers first gets the DM. The radar just makes sure that person is you.
The real change: you stop hoping
The mental shift matters more than the code. Instead of hoping the right post lands in front of you at the right hour, you build a machine that never blinks. That's the actual product.
How to try it right now
Start free. Don't touch an API key yet.
1. Write two lists. Open a notes file and write five phrases a real buyer would type — in their words, typos and all — plus three stop words for the stuff you don't want ("looking for work," "offering services," "unpaid"). This is the whole engine, and it costs nothing.
2. Turn on every native search and alert you've got. Telegram chat search, saved searches, notification rules, whatever your communities offer. You're simulating step one of the pipe by hand.
3. Run the filter in your head for a week. Log what you catch and what slips through. Most people discover their phrase list was wrong.
4. Build the dumb version in Python. Lowercase, strip a few endings, allow a gap of a couple of words, check for stop words. No model, no bill. If the dictionary alone gets you leads, you're done.
5. Add the classifier only when the dictionary gets noisy. Point the official `openai` SDK at OpenRouter, send one message at a time, and set a hard spending cap before you run anything. His cap: $30 a month.
6. Hard-code the single recipient. One chat_id, one sending module, and don't import the messaging library anywhere else. This is the rule that keeps your account alive.
7. Store everything in SQLite. Then you can see which phrases earn their keep and which just make noise — and cut the job board of your own life.
Upsides and what changes
You stop polling and start receiving. Cost becomes predictable — a fixed ceiling instead of a growing API bill, because the cheap filter does the volume work and the model only touches the survivors. The single-recipient rule turns a ban risk into a non-issue, and the source-by-source logging tells you which feeds actually pay for themselves.
The bigger change is tempo. Replying first is a timing game, and timing games are exactly what software is good at.
Limitations
Be honest about what this is. A userbot is a normal account doing abnormal things, so it can get restricted — that's why the author runs burner profiles and never lets the robot speak to strangers. Browser scraping Threads and Instagram from a Mac breaks whenever a page layout changes. The model still returns malformed JSON sometimes, and bursts of findings can outrun the server that receives them. Lead quality is only as good as your phrase list, so the first week is calibration, not profit. And the whole thing is one Docker process built for one person — it's a tool, not a product, and it won't find demand that nobody's typing.
Conclusion
The clever part of this build isn't the AI. It's the discipline: cheap filter first, model last, one recipient, a hard budget cap, and a human on the reply button. That's why it runs on a pocket-money budget instead of a small fortune, and why it hasn't gotten its owner banned.
One action for today: open a notes file and write the five phrases your ideal client would actually type — in their words, not yours. That list is your radar. Everything else is plumbing.



Comments 0