agentsclimarketplace

Telethon development

Skill Lu1sDV/skillsmd/telethon-development

Use when working with Telethon (Telegram MTProto client) — debugging FloodWaitError, mocking for tests, handling None-as-False boolean fields, entity resolution, rate limiting, session management, or version compatibility issuesFrom its SKILL.md

Install
npx -y skills add Lu1sDV/skillsmd --skill telethon-development

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

6.1 KB, ~1.4k tokens by cl100k_base, as published. Nobody here has run it

Telethon Development Patterns

Production patterns and gotchas for the Telethon Telegram MTProto client library.

When to Use

  • Debugging FloodWaitError, account bans, or flood wait cycling
  • Mocking Telethon clients for unit/integration tests
  • Storing Telethon data in a database (boolean normalization, serialization)
  • Resolving/normalizing chat IDs before DB storage
  • Handling new or version-specific Telethon types

When NOT to Use

  • Bot API (python-telegram-bot) — different library, different patterns
  • Telethon v2 — major API changes; verify patterns still apply

Quick Reference

TaskCode
Create clientTelegramClient(StringSession(session_str), api_id, api_hash)
Connectawait client.connect()
Get entityentity = await client.get_entity(identifier)
Normalize IDfrom telethon.utils import get_peer_id; get_peer_id(entity)
Iterate messagesasync for msg in client.iter_messages(chat, limit=100):
Join by inviteawait client(ImportChatInviteRequest(hash_val))
Handle floodexcept FloodWaitError as e: await asyncio.sleep(e.seconds)
Save sessionsession_string = client.session.save()

Critical Gotchas

GotchaWhat BreaksFix
Boolean fields are None not FalseNOT NULL DB columnsgetattr(obj, field, False) or False
isinstance() fails with test mocksMedia/reaction type detectiontype(obj).__name__ string comparison
iter_messages() has no max_dateDate filtering silently skippedFilter post-fetch: if msg.date > max_date: continue
to_dict() returns bytes in pollsJSONB serialization crashesBase64-encode bytes before storage
New types missing in older versionsImportError at startupGuard with try/except ImportError
ReactionCount.chosen removed in 1.42AttributeErrorgetattr(r, 'chosen_order', None) is not None
get_peer_id() on non-standard objectsTypeErrortry/except, fallback getattr(entity, 'id', 0)
MessageDeleted non-channel eventschat_id is NoneAlways guard if event.chat_id is not None
Stop listener before poolDangling handler errorslistener.stop() then pool.stop()
aggressive=True on iter_participantsTriggers flood waits fasterUse ChannelParticipantsSearch("") with pagination
2FA detection is string-basedMissed 2FA promptsCatch SessionPasswordNeededError explicitly

Session Management

Always use StringSession — never file sessions. Store in env vars; treat as passwords (full account access).

from telethon import TelegramClient
from telethon.sessions import StringSession

client = TelegramClient(StringSession(os.getenv("TG_SESSION")), api_id, api_hash)
await client.connect()
if not await client.is_user_authorized():
    await client.send_code_request(phone)
    await client.sign_in(phone, code)
session_string = client.session.save()  # Save to env var after auth

FloodWaitError Handling

The raw pattern (basis for all wrappers):

except FloodWaitError as e:
    await asyncio.sleep(e.seconds)  # e.seconds = mandatory wait duration
    # then retry or rotate to next account

Three wrapper patterns — see telethon-reference.md for implementations:

PatternWhen to Use
DecoratorSingle async calls (get_entity, get_messages)
Iterator wrapperasync for loops — supports checkpoint resume on retry
Context managerComplex control flow, manual checkpoint tracking

Type Detection (Mock-Safe)

Use class name strings — works with both real Telethon objects AND test mocks:

attr_name = type(attr).__name__
if attr_name == "DocumentAttributeVideo":
    return "video_note" if getattr(attr, "round_message", False) else "video"

if type(reaction).__name__ == "ReactionEmoji":
    return reaction.emoticon

Version Guards

Always guard imports for types added in recent Telethon versions:

try:
    from telethon.tl.types import MessageMediaPaidMedia
except ImportError:
    MessageMediaPaidMedia = None

Entity Resolution & ID Normalization

from telethon.utils import get_peer_id

entity = await client.get_entity(identifier)  # str, int, or @username
normalized_id = get_peer_id(entity)            # Canonical ID for DB storage

See telethon-reference.md for channel type detection and all link format parsing.

Rate Limiting Guidelines

OperationSafe RateRisk
Messages in single chat1/secondFlood ban
Channel joins2-5s betweenAccount freeze
Participant scraping (no takeout)Don'tInstant ban
Channels scraped per day<20024h soft ban
Mass avatar downloadsDon'tBan after 3-5

Use takeout sessions for heavy participant scraping — see telethon-reference.md.

Common Errors

ErrorMeaningHandle
FloodWaitErrorRate limitedWait e.seconds, rotate account
AuthKeyUnregisteredErrorSession invalidDisable account permanently
ChannelPrivateErrorNo accessSkip, log
ChatAdminRequiredErrorNeed adminReturn empty, log
UserAlreadyParticipantErrorAlready joinedNot an error — treat as success
InviteRequestSentErrorNeeds approvalLog as pending
PhoneNumberBannedErrorAccount bannedDisable permanently

Test Mocking

See telethon-reference.md for complete patterns:

  • Mock client fixture with async generators
  • RPC call mocking (client(Request()))
  • spec= for isinstance() compatibility
  • FloodWaitError construction: FloodWaitError(request=None, capture=0.01)

What ships with it: 2 files

11.6 KB alongside SKILL.md

references/

Keep looking

Skills are one crate of 326,790. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.