# Telethon Playbook > Gabay sa pag-automate ng sarili mong Telegram account gamit ang Telethon at Claude. > Para sa hindi programmer. Sinulat ni Jeff Lim (https://jeff-lim.com). > Huling review Agosto 2026. Dalawa ang API ng Telegram. Sa bot ang isa. Ang isa, ikaw: ang mga chat mo, ang mga group mo, ang pangalan mo sa bawat message na lalabas. Hindi mo kailangang maging programmer para dito. Kailangan mo lang maintindihan kung ano ang ginagawa mo at kung saan ka pwedeng masaktan. --- ## 1. Una sa lahat: bot ba, o ikaw mismo? Ang **bot** ay bagong account na gagawin mo. May sarili siyang pangalan, sarili niyang larawan, at may nakasulat na BOT sa tabi nito. Sinadya ng Telegram na limitado siya: hindi niya mababasa ang usapan bago siya sumali, at hindi siya pwedeng mauna magmessage sa kahit sino. Ang **MTProto** naman ang totoong wika ng mga opisyal na Telegram app. Ang Telethon ay isang Python library na marunong nito. Mag-lo-login ka gamit ang number mo at ang code na itetext sa iyo, katulad lang ng pag-install ng Telegram sa bagong laptop. Pagkatapos noon, parang isa nang device mo ang script mo. Lahat ng nakikita mo, nakikita niya. Lahat ng ipapadala niya, galing sa iyo. | Paghambingin | Bot | Ikaw mismo | | --- | --- | --- | | Ano ang makikita ng iba | Bagong account na may BOT sa tabi | Pangalan mo at larawan mo | | Paano mag-login | Token mula sa BotFather | Number mo at code, tapos may session file | | Mababasa ang lumang usapan | Hindi | Oo, buong history mo | | Pwedeng mauna magmessage | Hindi | Oo, pero dito nagsisimula ang halos lahat ng ban | | May button sa ilalim | Oo, ito ang gimik ng bot | Wala. Bawal sa protocol mismo | | Makikita kung sino nag-react | Kapag admin lang, naka-off pa by default | Oo, kasama kung sino ang nag-tap | | Paano makapasok sa group | May magdadagdag sa kanya | Nandoon ka na | | Saan tatakbo | Kahit saan | Program na laging bukas | | Pinakamasamang mangyayari | Titigil ang bot, gagawa ka ng bago | Ma-limit ang totoong number mo | **Ang isang linyang magdedesisyon para sa iyo.** Kapag ikaw ang nagpadala, bawal ang button. Kung susubukan mong ilagay, error ang isasagot ng Telegram, hindi keyboard. Kaya kung ang gusto mo ay "magpost ako tapos may pipindutin sila sa ilalim", hindi mo iyon magagawa mula sa account mo. Reaction ang kapalit, at kadalasan mas maganda pa nga. --- ## 2. Bago ka magsimula 1. **Computer na kayang mag-install ng program.** Windows, Mac, o Linux, pareho lang. Hindi ito kayang gawin sa cellphone lang. 2. **Python 3.10 pataas.** Libre sa python.org. Sa Windows, huwag mong kalimutang lagyan ng tsek ang "Add Python to PATH" habang nag-i-install. 3. **Terminal, o Command Prompt.** Yung itim na window kung saan ka nagta-type ng utos. Sa Windows, PowerShell. Sa Mac, Terminal. 4. **Telegram account mo na may naka-on na 2FA.** Settings, Privacy and Security, Two-Step Verification. Gawin mo ito bago pa ang lahat. 5. **Si Claude, o kahit anong AI na marunong mag-code.** Siya ang magsusulat. Ikaw ang magsasabi ng gusto mo, at ikaw ang magtsetsek kung tama. **Isang tanong bago tumuloy:** may totoo ka bang gagamitan nito? Ang pinakaligtas na gamit ay sa mga group na kasapi ka na, at ilang message lang bawat araw. Ang delikado ay ang magpadala sa mga taong hindi ka naman kinakausap. --- ## 3. Paano ito gumagana **Ang isang ideya:** ang script mo ay hindi kumakatok sa account mo mula sa labas, tulad ng ginagawa ng bot. Naka-login siya, katabi ng cellphone at laptop mo. Bawat device na naka-login sa account mo ay parehong nakakakita ng lahat, at parehong pwedeng magpadala. Ganito talaga gawa ang Telegram. Session = device. Ang apat na parte: 1. **Pangalan ng app.** Isang api_id at api_hash mula sa my.telegram.org. Ito ang pangalan ng program mo, hindi ikaw. Isang beses mo lang kukunin. 2. **Session.** Gagawin sa unang login mo. Isusulat ito ng Telethon sa isang file. Sa susunod na patakbo mo, babasahin na lang niya ito. 3. **Client.** Ang buhay na koneksyon. May bukas siyang linya sa Telegram kaya alam niya agad kapag may bago. Kaya kailangan itong laging bukas, hindi naka-schedule. 4. **Handler.** Mga function na nagsasabing "kapag ganito ang dumating, gawin mo ito". Dito lang talaga nakatira ang gusto mong mangyari. --- ## 4. Limang bagay na magbabago kapag ikaw ang nagpapadala 1. **Walang button, kahit kailan.** Ang reply_markup ay para lang sa bot. Ilipat mo ang pipindutin nila sa reaction, reply, o isang salitang ita-type nila. 2. **Reaction ang magiging pindutan mo.** Sa kahit anong message na nakikita mo, kaya mong itanong kung sino ang nag-react. Buong sistema na iyon ng "sino ang nakabasa". 3. **Ikaw na ang bahala sa saklaw.** Buong Telegram mo ang nakikita ng script mo. Ang unang linya ng bawat handler ay tsek kung tama ba ang chat. 4. **May sasabihin ang Telegram kapag sobra ka na.** FloodWaitError na may bilang ng segundo. Matulog ka ng ganoon kadami. Huwag mong uulitin agad. 5. **Ang session file ay parang password mo.** Kung sino ang may hawak nito, siya ang naka-login bilang ikaw, at hindi na hihingian ng 2FA. --- ## 5. Sundan mo ito nang paisa-isa Mas mahalaga ang pagkakasunod kaysa sa code mismo. **Hakbang 0, mga 30 minuto. Patunayan mong gumagana.** Pumunta sa my.telegram.org, mag-login, gumawa ng bagong app para makuha ang api_id at api_hash. Sa terminal: `pip install telethon`. Tapos patakbuhin ang pinakamaliit na script na nagpi-print lang ng pangalan mo. Iyon lang muna. **Hakbang 1, isang gabi. Manood muna, huwag magpadala.** Isang handler lang, i-print lahat ng nakikita niya, huwag mo munang isulat ang parteng nagpapadala. Patakbuhin sa buong araw. Dito mo idagdag ang tsek ng chat, habang wala pa siyang kayang sirain. **Hakbang 2, isang oras. Unang padala, walang makakakita.** Ipadala mo muna lahat sa Saved Messages, `"me"` lang ang ilalagay mong padadalhan. Subukan doon ang padala, edit, at bura, pati ang mga pangit na kaso: mag-edit ng message na wala na, magpadala ng text na may weird na character, at sadyain mong maabot ang limit. **Hakbang 3. Ituro mo na sa totoong group.** Palitan ang padadalhan ng totoong chat ID, nasa config at hindi nakasulat sa gitna ng code. Panatilihing maliit ang parteng nagpapadala. Lahat ng nagdedesisyon kung ano ang laman ng message, ilagay sa hiwalay na function na kaya mong subukan kahit walang internet. **Hakbang 4, habambuhay. Panatilihing buhay.** May bukas siyang koneksyon, kaya hindi ito cron job. Maliit na server na laging bukas, o container na kusang nagre-restart. Ilagay ang session file sa labas at i-mount lang kapag tumatakbo. I-log ang bawat reconnect at bawat flood wait. --- ## 6. Halimbawa: announcement na kailangang i-acknowledge Magpost sa group, tapos makita kung sino ang nakabasa na at sino ang hinihintay pa, nasa loob mismo ng message. Kung bot ito, maglalagay ka ng button. Hindi mo iyon kayang gawin dito, kaya reaction ang gagamitin. BABALA: nakasulat ito base sa kasalukuyang dokumentasyon ng Telethon at MTProto, at HINDI pa ito napapatakbo sa totoong account. Ituring mong hugis ng solusyon, hindi tapos na produkto. Ang pag-verify nito ang mismong dahilan kung bakit may Hakbang 0 hanggang 2. Kapag may pangalan na nagbago, ang https://tl.telethon.dev/ ang masusunod. ### Hakbang 1: ipadala Ang mahalaga dito ay ang `render`. Binibigyan mo siya ng listahan kung sino ang nakabasa, at text ang isinasagot niya. Walang internet, walang Telegram. Doon nagtatago ang halos lahat ng mali sa ganitong feature. ```python # announce.py import os from telethon import TelegramClient # Galing sa environment, hindi nakasulat dito, para walang # masamang aksidente kapag na-share mo ang code. API_ID = int(os.environ["TG_API_ID"]) API_HASH = os.environ["TG_API_HASH"] GROUP = int(os.environ["TG_GROUP_ID"]) # -100... kapag supergroup # Sino ang hinihintay. Kunin mo ang mga ID sa Hakbang 1. ROSTER = { 5205736813: "Jeff", 286255193: "Glenn", 935778918: "Yoyot", } client = TelegramClient(os.environ["TG_SESSION"], API_ID, API_HASH) def render(body, acked): """Malinis na function. State ang papasok, text ang lalabas.""" nakabasa = [n for uid, n in ROSTER.items() if uid in acked] hinihintay = [n for uid, n in ROSTER.items() if uid not in acked] linya = [body, "", f"Nakabasa {len(nakabasa)}/{len(ROSTER)}"] linya += [f" {n}" for n in nakabasa] or [" wala pa"] if hinihintay: linya += ["", "Hinihintay pa"] + [f" {n}" for n in hinihintay] else: linya += ["", "Kumpleto na."] return "\n".join(linya) async def post(body): msg = await client.send_message(GROUP, render(body, acked={})) return msg.id # itago mo ito. ito ang susi sa lahat sa baba ``` ### Hakbang 2: pansinin ang tap Hindi maganda ang dating ng reaction sa Telethon. Wala siyang madaling handler, kaya raw update ang sasaluhin natin. Hindi rin maaasahan kung sino ang sinasabi ng update na nag-react, kaya ituring mo na lang itong tapik sa balikat. ```python # watch.py from telethon import events from telethon.tl.types import UpdateMessageReactions TRACKED = set() # mga message id na atin @client.on(events.Raw(types=[UpdateMessageReactions])) async def on_reaction(update): # Tsek muna, palagi. Buong account mo ang nakikita nito. if update.msg_id not in TRACKED: return await refresh(update.msg_id) # Pansinin: msg_id ang pangalan dito, hindi message_id. # Ganito talaga sa raw types. Kapag may hindi ka sigurado, # tingnan mo muna sa tl.telethon.dev bago mo isulat. ``` ### Hakbang 3: bilangin ulit Bilangin ulit mula sa umpisa, huwag mong dagdagan ang luma. Ang bilang na dinadagdagan ay nalilito kapag sabay-sabay ang nag-tap. Ang bilang na kinukuha ulit mula sa Telegram, hindi. ```python # refresh.py import asyncio from telethon.errors import FloodWaitError, MessageNotModifiedError from telethon.tl.functions.messages import GetMessageReactionsListRequest BODIES = {} # msg_id -> orihinal na text async def refresh(msg_id): try: res = await client(GetMessageReactionsListRequest( peer=GROUP, id=msg_id, limit=100, )) except FloodWaitError as e: # Matulog nang eksakto sa hinihingi niya. Huwag uulitin agad. await asyncio.sleep(e.seconds) return acked = {} for r in res.reactions: uid = getattr(r.peer_id, "user_id", None) if uid is not None: acked.setdefault(uid, r.date) # unang tap ang bibilangin try: await client.edit_message(GROUP, msg_id, render(BODIES[msg_id], acked)) except MessageNotModifiedError: pass # dalawang beses nag-tap. wala namang bago except FloodWaitError as e: await asyncio.sleep(e.seconds) ``` ### Hakbang 4: patakbuhin Isang program lang ito na laging bukas. Ang `run_until_disconnected` ang naghihintay. Walang polling, walang cron. Ito rin ang pinakamadalas na pagkakamali ng bago: nakakalimutan ang linyang ito, kaya lumalabas na walang nangyayari kahit tama ang code. ```python # main.py import asyncio async def main(): await client.start() # hihingi ng code sa unang takbo lang body = "Alis tayo bukas ng 6am. Mag-react kapag nabasa mo na." msg_id = await post(body) BODIES[msg_id] = body TRACKED.add(msg_id) print("naipadala", msg_id) await client.run_until_disconnected() # dito siya maghihintay if __name__ == "__main__": asyncio.run(main()) # Nasa memory lang ang TRACKED at BODIES dito para madaling # basahin. Sa totoong gamit, ilagay mo sa SQLite para hindi # mawala ang lahat kapag nag-restart. ``` --- ## 7. Ipagawa mo kay Claude **Magaling siya dito:** ang gawing gumaganang code ang sinasabi mong "kapag nangyari ang ganito, gusto ko ganito". Pati ang mga nakakainip na parte tulad ng paghihintay at pag-uulit. Pati ang lohika kung ano ang isusulat sa message, na doon naman talaga nagtatago ang mga bug. **Dito ka niya masasaktan:** ang eksaktong pangalan ng mga bahagi ng MTProto. Isusulat niyang `update.message_id` kahit `msg_id` pala talaga, o gagamit siya ng function na wala naman. At kumpiyansa pa siya habang ginagawa niya. Hindi ito matatapos ng "mag-ingat ka ha". **Ang solusyon:** bigyan mo siya ng reference, hindi lang ng utos. Nasa https://tl.telethon.dev/ ang bawat function at bawat type. Sabihin mo sa kanya na buksan muna ang page bago siya magsulat, at pabasahin mo sa kanya pabalik ang mga pangalan. ### Ang unang mensahe mo kay Claude ``` Gusto kong gumawa ng script na tatakbo sa sarili kong Telegram account gamit ang Telethon. Hindi bot, ako mismo. Ang gusto kong mangyari: [isulat mo dito, halimbawa: "kapag nagpost ako ng announcement sa group namin, gusto kong makita kung sino na ang nakabasa"] Hindi ako programmer, kaya: - Ipaliwanag mo sa simpleng salita kung ano ang ginagawa ng bawat file - Sabihin mo kung ano mismo ang ita-type ko sa terminal - Sabihin mo kung ano ang dapat kong makita kapag tama - Kapag may error, ipaliwanag mo muna bago mo ayusin Simulan natin sa Hakbang 0: patunayan lang na naka-connect ako at mapa-print ang pangalan ko. Huwag muna tayong magpadala kahit kanino. ``` ### Mga patakaran, isang beses kada project ``` Tutulungan mo akong gumawa ng Telethon script na tatakbo sa personal kong Telegram account. Hindi ito bot. Lahat ng ipapadala nito ay lalabas na galing sa akin. Mahigpit na patakaran sa lahat ng code na isusulat mo dito: 1. Huwag kang magpapadala, mag-e-edit, magbubura o magfo-forward sa kahit anong chat maliban sa "me" (Saved Messages), maliban na lang kung may binigay akong chat ID sa mismong mensaheng humihingi. 2. Bawat handler, magsisimula sa pagtsek ng chat o message ID, at agad na titigil kapag hindi tugma, bago pa ang kahit anong logic. 3. Balutin mo ng FloodWaitError handler ang bawat tawag na pwedeng umabot sa limit, at matulog ng e.seconds. Huwag uulitin agad, huwag mo ring tatahimikin. 4. Huwag mong ipi-print, ilo-log, o ipapakita ang laman ng session file, ang api_hash, o ang login code. 5. Bawal ang inline keyboard sa user account. Kapag ang hinihingi ko ay kailangan ng button, sabihin mong hindi ito kaya, huwag kang magsusulat ng reply_markup. 6. Bago ka gumamit ng raw type o Request class, buksan mo muna ang page nito sa tl.telethon.dev at ibalik mo sa akin ang eksaktong pangalan ng mga attribute. Huwag kang manghuhula, at huwag mong kukunin sa Bot API dahil magkaiba ang pangalan doon. 7. Ilagay mo sa hiwalay na malilinis na function ang pagbuo ng text ng message: state ang papasok, string ang lalabas, walang tawag sa internet, para matest ito offline. ``` ### CLAUDE.md para sa project folder mo ```markdown # Telegram automation, personal account Telethon sa totoong user account. Walang bot dito. Lahat ng ipapadala ng repo na ito, lalabas sa chat na ako ang nagsabi. ## Hindi pwedeng labagin - Ang test na padala ay sa Saved Messages ("me"). Ang totoong chat ID ay galing sa config, at pagkatapos lang ma-test ang render. - Ang session file ay katumbas ng password ko. Hindi ico-commit, hindi ilo-log, hindi isasama sa kahit anong image. - Bawat handler, tsek muna ng chat o message ID bago ang lahat. - Ang FloodWaitError ay sinasagot ng pagtulog ng e.seconds. Hindi inuulit agad. - Walang inline keyboard dito. Reaction at reply lang. ## Ayos ng mga file config.py api_id, api_hash, chat ids galing sa env. Walang literal. client.py Paggawa at pagbukas ng client lang. handlers/ Isang file kada feature. Tsek muna, saka gagalaw. render.py Malilinis na function. State papasok, text lalabas. store.py SQLite. Para hindi mawala ang message ids kapag nag-restart. ## Paano ko titsekin ang bago Patakbuhin muna sa Saved Messages. Ilipat lang sa totoong group kapag may test na ang render.py sa lahat ng pwedeng lumabas. ## Reference Raw types at requests: tl.telethon.dev. Doon tingnan ang pangalan bago isulat. Hindi pareho ang pangalan sa Bot API. ``` **Isang ugali na sulit panatilihin.** Ipagawa mo muna kay Claude ang function na bumubuo ng text, kasama ang test nito, bago pa may humipo sa Telegram. Matatapos mo ang parteng nagdedesisyon kung ano ang babasahin ng tao, nasubukan na lahat, tumatakbo sa isang segundo, walang account na kasama. Ang matitira ay padala na lang, at ang padala ay gumagana o may error, walang gitna. --- ## 8. Ano ang pwedeng masira **Ang session file ay buong login (kritikal).** Kapag nakuha ito ng iba, nakuha na nila ang account mo. Hindi ka masasagip ng 2FA kasi nakalampas na doon ang session. Ilagay sa labas ng project folder, `chmod 600` kung Mac o Linux, huwag isasama sa backup na naka-share. Kapag naghinala kang nakuha ito: Telegram, Settings, Devices, tanggalin ang session na iyon, tapos mag-login ulit. **Ang bagong number ang pinakamadaling ma-limit (babala).** Ang account na kaka-join lang last week tapos biglang nagpadala ng automated na message, iyan mismo ang hinahanap ng anti-spam. Kung bago ang account, hayaan mo muna itong kumilos na parang tao. **Ang flood wait ay countdown, hindi error na binabalewala (babala).** Matulog ka ng buong bilang ng segundo. Kapag umaabot na ng oras-oras, patayin mo muna at tingnan kung ano ang ginagawa niya. Normal lang ang ilang segundo kapag sabay-sabay ang padala. **May ligtas na parte dito, at totoong ligtas.** Ang pagbabasa ng group na kasapi ka na, at pagpost ng ilang message kada araw sa bilis ng tao, hindi iyon ang hinahabol ng anti-spam. Tumataas nang matarik ang panganib kapag nagmessage ka sa hindi mo kilala, sumali sa maraming group nang sabay, kinuha ang listahan ng members, o dumami ang padala. Tungkol sa patakaran: ang API terms ng Telegram ay nakasulat para sa mga gumagawa ng client app, at hindi nito sinasabi nang diretso kung pwede bang i-automate ang sarili mong account. Kaya walang malinis na masasabing oo o hindi. Sa totoong buhay, ang ugali ang binabantayan, hindi ang gamit. Walang naghahanap ng Telethon. Ang hinahanap nila, mukhang spam. --- ## 9. Kapag na-stuck ka | Ano ang nakikita mo | Ano ang ibig sabihin | | --- | --- | | Walang nangyayari kahit tama ang code | Kulang ang huling linya. Kapag walang `run_until_disconnected()`, natatapos agad ang program bago pa dumating ang kahit anong message. | | PeerIdInvalidError | Hindi pa kilala ng script ang chat na iyon. Magpadala ka muna ng message doon mula sa app mo, o pabasahin muna sa script ang listahan ng chats mo. | | database is locked | Dalawang script ang sabay na gumagamit ng parehong session file. Isa lang ang pwede. | | FloodWaitError: 3600 | Sobra ka na, isang oras ang hinihintay. Huwag mong lusutan. Patayin, hintayin, bawasan ang bilis. | --- ## 10. Ang mga tawag na talagang gagamitin mo | Ang gusto mong mangyari | Ang tawag | | --- | --- | | Gumawa ng client, gamit ang naka-save na session | `TelegramClient("pangalan", api_id, api_hash)` | | Mag-login, hihingi ng code sa unang takbo lang | `await client.start()` | | Tsekan kung sino ang naka-login | `await client.get_me()` | | Magpadala ng message | `await client.send_message(peer, text)` | | I-edit ang naipadala mo na | `await client.edit_message(peer, msg_id, text)` | | Mag-react sa isang message | `client(SendReactionRequest(peer, msg_id, reaction=[ReactionEmoji("thumbsup")]))` | | Tingnan kung sino ang nag-react | `client(GetMessageReactionsListRequest(peer, id, limit=100))` | | Salubungin ang bagong message sa isang chat | `@client.on(events.NewMessage(chats=[chat_id]))` | | Salubungin ang raw update | `@client.on(events.Raw(types=[UpdateMessageReactions]))` | | Panatilihing bukas ang program | `await client.run_until_disconnected()` | Dalawang reference ang bahala sa lahat ng iba. Ang https://docs.telethon.dev/ ang madaling parte: ang mga client method, ang mga event, ang mga karaniwang halimbawa. Ang https://tl.telethon.dev/ naman ang listahan ng bawat raw MTProto type at request, at ito ang bubuksan mo sa sandaling lumabas ka sa mga madaling method.