Skip to content

added pyrogram support#5

Open
chizumeiji wants to merge 3 commits into
DedInc:mainfrom
chizumeiji:main
Open

added pyrogram support#5
chizumeiji wants to merge 3 commits into
DedInc:mainfrom
chizumeiji:main

Conversation

@chizumeiji

@chizumeiji chizumeiji commented Jun 13, 2026

Copy link
Copy Markdown

приветик
реализовал поддержку pyrogram, которой как по мне сильно не хватало проекту, протестировал на одном из своих аккаунтов сконвертировав сессию во все возможные форматы и обратно, и все работает отлично
буду благодарен если примешь пулл реквест, и обновишь либу

Summary by CodeRabbit

  • New Features
    • Added support for loading and saving Pyrogram session files
    • Enabled bidirectional conversion between Pyrogram, Telethon, and TDesktop session formats
    • Introduced Pyrogram session string serialization and deserialization capabilities

@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@chizumeiji, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 39 minutes and 17 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 79ffaaf2-7d9e-4d2e-b8cf-b72cb4170be0

📥 Commits

Reviewing files that changed from the base of the PR and between 0045fa7 and 42d983d.

📒 Files selected for processing (3)
  • src/pg/client.py
  • src/pg/pyrogram_io.py
  • src/pg/session_string.py
📝 Walkthrough

Walkthrough

This PR introduces a new pg module that enables bidirectional Pyrogram session format support. It implements session string encoding/decoding, Pyrogram SQLite file I/O, a PyrogramSession abstraction class, and integration points in both TelegramClient and TDesktop for seamless format conversion across the library.

Changes

Pyrogram Session Format and Conversion

Layer / File(s) Summary
Session String Encoding and Decoding
src/pg/session_string.py
encode_session_string and decode_session_string implement Pyrogram-style base64 session serialization using struct packing, with support for both current and legacy session string formats.
Configuration: DC Addresses and Schema
src/pg/configs.py
Defines production and test datacenter address mappings and session string struct formats with precomputed sizes for encoding/decoding.
Pyrogram File I/O: SQLite Session Read/Write
src/pg/pyrogram_io.py
Provides write_pyrogram_session and read_pyrogram_session for low-level SQLite file operations, plus save_pyrogram_session and from_pyrogram_session to convert between Telethon clients and Pyrogram .session files.
PyrogramSession: Session Abstraction and Converters
src/pg/client.py
Core PyrogramSession class with constructors to load from Pyrogram files/strings or convert from Telethon/TDesktop, and methods to export as files/strings or convert to Telethon/TDesktop; includes internal API preset resolution helpers.
TDesktop: Pyrogram Format Conversion
src/td/tdesktop.py
Adds FromPyrogram static factory and SavePyrogram instance method to TDesktop, enabling bidirectional Pyrogram conversion with proper client lifecycle management. Also wraps SaveSessionJson disconnect in try/finally.
TelegramClient: Pyrogram Format Conversion
src/tl/telethon.py
Adds ToPyrogram and FromPyrogram methods to TelegramClient, delegating to pyrogram_io helpers for exporting to and loading from Pyrogram .session files.
Package Exports and Re-exports
src/pg/shared.py, src/pg/__init__.py, src/__init__.py
Creates src/pg module hierarchy with shared.py aggregating session symbols, pkg/init.py re-exporting at package level, and root src/init.py adding pg module to main package exports.

🎯 3 (Moderate) | ⏱️ ~25 minutes

🐰 A Pyrogram bridge so fine,
Telethon and TDesktop align!
Sessions convert with base64 flair,
SQLite schemas with care and care,
Format translation—magic in the air! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'added pyrogram support' accurately describes the main change—implementing Pyrogram session interoperability across the codebase with new modules, classes, and conversion methods.
Docstring Coverage ✅ Passed Docstring coverage is 88.89% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (1)
src/pg/client.py (1)

275-301: 💤 Low value

Use explicit is not None check for consistency.

Line 294 uses api or API.TelegramDesktop, whereas line 210 in FromTDesktop uses api if api is not None else .... While functionally safe for APIData types, the inconsistency reduces readability. Use is not None consistently across the class.

♻️ Proposed fix for consistency
-        use_api = api or API.TelegramDesktop
+        use_api = api if api is not None else API.TelegramDesktop()
         client = await self.ToTelethon(api=use_api)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pg/client.py` around lines 275 - 301, The code in ToTDesktop uses a
truthy check "use_api = api or API.TelegramDesktop" which is inconsistent with
FromTDesktop's explicit None check; change the assignment in ToTDesktop to
"use_api = api if api is not None else API.TelegramDesktop" (keeping the rest of
the method—calls to ToTelethon and TDesktop.FromTelethon—unchanged) so the API
selection is done via an explicit is not None check for consistency with the
class.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/pg/client.py`:
- Around line 106-129: The constructor __init__ currently assigns self.auth_key
(and other attrs) before running the Expects validation, leaving a
partially-initialized instance on failure; move the auth_key validation (the
Expects(...) call that raises SessionFileInvalid when auth_key is not 256 bytes)
to the top of __init__ before any assignments, then convert/assign self.auth_key
= bytes(auth_key) if valid and proceed to set self.dc_id, self.api_id,
self.user_id, self.is_bot, and self.test_mode; keep the same exception type and
message and leave other logic unchanged.
- Around line 49-85: The code in _build_telethon_session silently falls back to
a hardcoded datacenter when dc_id is missing from DC_ADDRESSES; add explicit
validation at the start of the function to ensure dc_id is an expected value
(e.g., 1–5 or membership in DC_ADDRESSES) and fail fast: if dc_id not in
DC_ADDRESSES, raise a ValueError (or alternatively log.warning and then raise)
with a clear message including the invalid dc_id so callers don't silently
connect to the hardcoded address; update _build_telethon_session to perform this
check before using DC_ADDRESSES.
- Around line 25-46: In _resolve_api_from_id, remove the unreachable "return api
# type: ignore[return-value]" path and instead make the function explicitly
handle invalid `api` inputs: when `api is not None` and it's neither an instance
of APIData nor a subclass of APIData (the branches covering isinstance(api,
APIData) and issubclass(api, APIData)), raise a clear TypeError or ValueError
indicating an invalid `api` argument; keep the rest of the function (the
pyro_api_id checks and default return API.TelegramAndroid()) unchanged so
callers get a deterministic error rather than the unreachable implicit return.
- Around line 150-196: The FromTelethon method currently swallows all exceptions
from client.get_me() which hides failures; change the try/except around the
await client.get_me() to catch narrower Telethon errors (e.g.,
telethon.errors.RPCError or telethon.errors.TelethonError) or, if those types
are not imported here, catch Exception as e but log it instead of suppressing
it; add a module logger (logger = logging.getLogger(__name__)) and in the except
block call logger.warning or logger.exception with context like "FromTelethon:
failed to fetch user info via get_me()" and include the exception (exc_info=True
or pass e) so the function still falls back to existing behavior (leave user_id
as None) but the failure is recorded for debugging.

In `@src/pg/pyrogram_io.py`:
- Around line 167-185: The export code never passes the account type flag to
write_pyrogram_session, so bot exports are serialized as user sessions; modify
the logic around fetch_user_info / client.get_me and the fallback using
client.UserId to also determine whether the current account is a bot (e.g., set
is_bot = True/False by checking me.is_bot when me is present, or by reading the
appropriate attribute from the client when using client.UserId), then pass that
is_bot value into the write_pyrogram_session(...) call so the exported session
preserves bot vs user semantics.
- Around line 34-35: The helper builds full_path with "full_path = path if
path.endswith('.session') else path + '.session'" but may leave relative paths;
normalize it to the canonical absolute path by wrapping the result with
os.path.abspath (e.g. full_path = os.path.abspath(path if
path.endswith('.session') else path + '.session')) before opening or returning
the session file so the written location and the returned value are aligned;
apply the same change to the other identical occurrence of that assignment.

In `@src/pg/session_string.py`:
- Around line 30-35: For src/pg/session_string.py (lines 30-35): avoid
evaluating len(auth_key) when auth_key may not be bytes by splitting the
validation into a type check first and only measuring length afterward (or by
guarding the length computation when constructing SessionFileInvalid); ensure
Expects() is passed a pre-built SessionFileInvalid that uses a safe length value
(e.g., 0 or "unknown") when auth_key is not a bytes-like object. For
src/pg/pyrogram_io.py (lines 127-133): apply the identical fix in the SQLite
reader — separate the isinstance(auth_key, (bytes, bytearray)) test from the
length check or guard the len() call when formatting the SessionFileInvalid
message so malformed files raise SessionFileInvalid rather than triggering
TypeError.

---

Nitpick comments:
In `@src/pg/client.py`:
- Around line 275-301: The code in ToTDesktop uses a truthy check "use_api = api
or API.TelegramDesktop" which is inconsistent with FromTDesktop's explicit None
check; change the assignment in ToTDesktop to "use_api = api if api is not None
else API.TelegramDesktop" (keeping the rest of the method—calls to ToTelethon
and TDesktop.FromTelethon—unchanged) so the API selection is done via an
explicit is not None check for consistency with the class.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: aacf96a1-d02c-4ac2-a8c9-8d1e99773342

📥 Commits

Reviewing files that changed from the base of the PR and between e55fc3f and 0045fa7.

📒 Files selected for processing (9)
  • src/__init__.py
  • src/pg/__init__.py
  • src/pg/client.py
  • src/pg/configs.py
  • src/pg/pyrogram_io.py
  • src/pg/session_string.py
  • src/pg/shared.py
  • src/td/tdesktop.py
  • src/tl/telethon.py

Comment thread src/pg/client.py
Comment thread src/pg/client.py
Comment thread src/pg/client.py
Comment thread src/pg/client.py
Comment thread src/pg/pyrogram_io.py
Comment on lines +34 to +35
full_path = path if path.endswith(".session") else path + ".session"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Return the canonical absolute path.

TelegramClient.ToPyrogram() documents an absolute path, but this helper returns a relative path unchanged when the caller passes one. Normalize full_path with os.path.abspath() before opening the database so the write location and return value stay aligned.

📌 Minimal fix
-    full_path = path if path.endswith(".session") else path + ".session"
+    full_path = os.path.abspath(
+        path if path.endswith(".session") else path + ".session"
+    )

Also applies to: 90-90

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pg/pyrogram_io.py` around lines 34 - 35, The helper builds full_path with
"full_path = path if path.endswith('.session') else path + '.session'" but may
leave relative paths; normalize it to the canonical absolute path by wrapping
the result with os.path.abspath (e.g. full_path = os.path.abspath(path if
path.endswith('.session') else path + '.session')) before opening or returning
the session file so the written location and the returned value are aligned;
apply the same change to the other identical occurrence of that assignment.

Comment thread src/pg/pyrogram_io.py
Comment thread src/pg/session_string.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant