Skip to content

Commit 1241cb0

Browse files
committed
fix: resolve unmarked channel/chat IDs passed as positive integers
Telethon's get_entity(int) maps positive integers to PeerUser. When callers pass a bare channel ID like 1676885811 (without the -100 prefix), Telethon looks for a user with that ID and fails with ValueError. The existing fallback (get_dialogs cache warming) doesn't help because Telethon still interprets the positive int as PeerUser on retry. Add _marked_id_candidates() that generates -100X (PeerChannel) and -X (PeerChat) variants from a positive int. Both resolve_entity() and resolve_input_entity() now try these variants as a last resort before raising, so unmarked IDs from any source (LLMs, cached values, manual input) resolve correctly.
1 parent a050889 commit 1241cb0

1 file changed

Lines changed: 58 additions & 4 deletions

File tree

main.py

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -341,27 +341,81 @@ def format_entity(entity) -> Dict[str, Any]:
341341
return result
342342

343343

344+
def _marked_id_candidates(identifier: Union[int, str]) -> list:
345+
"""Return alternative marked IDs to try when a positive int fails to resolve.
346+
347+
Telethon's get_entity(int) uses resolve_id() internally, which maps:
348+
positive int -> PeerUser
349+
-100XXXXXXXXXX -> PeerChannel
350+
-XXXXXXXXXX -> PeerChat
351+
352+
Callers (LLMs, other tools) often pass unmarked channel/chat IDs as
353+
bare positive integers. When get_entity fails on a positive int, we
354+
try the marked variants before giving up.
355+
"""
356+
if not isinstance(identifier, int) or identifier <= 0:
357+
return []
358+
return [
359+
-1000000000000 - identifier, # PeerChannel (most common: channels, supergroups)
360+
-identifier, # PeerChat (legacy groups)
361+
]
362+
363+
344364
async def resolve_entity(identifier: Union[int, str]) -> Any:
345-
"""Resolve entity with automatic cache warming on miss.
365+
"""Resolve entity with automatic cache warming and unmarked ID fallback.
346366
347367
StringSession has no persistent entity cache. If get_entity() fails
348368
because the cache is cold (ValueError on PeerUser lookup for group IDs),
349369
warm the cache via get_dialogs() and retry.
370+
371+
If that still fails and identifier is a positive int, try marked
372+
variants (-100X for channels, -X for chats) before raising.
350373
"""
351374
try:
352375
return await client.get_entity(identifier)
353376
except ValueError:
354377
await client.get_dialogs()
355-
return await client.get_entity(identifier)
378+
try:
379+
return await client.get_entity(identifier)
380+
except ValueError:
381+
pass
382+
383+
for candidate in _marked_id_candidates(identifier):
384+
try:
385+
return await client.get_entity(candidate)
386+
except ValueError:
387+
continue
388+
389+
raise ValueError(
390+
f"Could not resolve entity for {identifier!r}, "
391+
f"including marked variants {_marked_id_candidates(identifier)}"
392+
)
356393

357394

358395
async def resolve_input_entity(identifier: Union[int, str]) -> Any:
359-
"""Like resolve_entity() but returns an InputPeer."""
396+
"""Like resolve_entity() but returns an InputPeer.
397+
398+
Same fallback logic: cache warming, then marked ID variants.
399+
"""
360400
try:
361401
return await client.get_input_entity(identifier)
362402
except ValueError:
363403
await client.get_dialogs()
364-
return await client.get_input_entity(identifier)
404+
try:
405+
return await client.get_input_entity(identifier)
406+
except ValueError:
407+
pass
408+
409+
for candidate in _marked_id_candidates(identifier):
410+
try:
411+
return await client.get_input_entity(candidate)
412+
except ValueError:
413+
continue
414+
415+
raise ValueError(
416+
f"Could not resolve input entity for {identifier!r}, "
417+
f"including marked variants {_marked_id_candidates(identifier)}"
418+
)
365419

366420

367421
def format_message(message) -> Dict[str, Any]:

0 commit comments

Comments
 (0)