pyrogram.go 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. package sessionimport
  2. import (
  3. "crypto/sha1"
  4. "database/sql"
  5. "fmt"
  6. "github.com/gotd/td/session"
  7. _ "modernc.org/sqlite"
  8. )
  9. // ConvertPyrogramSession reads a Pyrogram/Telethon SQLite session file and
  10. // builds a gotd/td session.Data representing the same authorization.
  11. //
  12. // Pyrogram schema (single row in `sessions` table):
  13. //
  14. // CREATE TABLE sessions (
  15. // dc_id INTEGER PRIMARY KEY,
  16. // api_id INTEGER,
  17. // test_mode INTEGER,
  18. // auth_key BLOB, -- 256 bytes
  19. // date INTEGER NOT NULL,
  20. // user_id INTEGER,
  21. // is_bot INTEGER);
  22. func ConvertPyrogramSession(sqlitePath string) (*session.Data, error) {
  23. // Open READ-ONLY + IMMUTABLE. Pyrogram .session files may be in-use by a
  24. // running Pyrogram client; a write-capable handle could corrupt them via
  25. // journal rollback on crash.
  26. dsn := fmt.Sprintf("file:%s?mode=ro&immutable=1", sqlitePath)
  27. db, err := sql.Open("sqlite", dsn)
  28. if err != nil {
  29. return nil, fmt.Errorf("open pyrogram sqlite: %w", err)
  30. }
  31. defer db.Close()
  32. var dcID int
  33. var authKey []byte
  34. err = db.QueryRow(`SELECT dc_id, auth_key FROM sessions LIMIT 1`).Scan(&dcID, &authKey)
  35. if err != nil {
  36. return nil, fmt.Errorf("read pyrogram sessions row: %w", err)
  37. }
  38. if len(authKey) != 256 {
  39. return nil, fmt.Errorf("invalid auth_key length: %d (want 256)", len(authKey))
  40. }
  41. addr, err := TGDCAddr(dcID)
  42. if err != nil {
  43. return nil, err
  44. }
  45. // auth_key_id = SHA-1(auth_key)[12:20] — lower 64 bits of the SHA-1 digest.
  46. sum := sha1.Sum(authKey)
  47. keyID := make([]byte, 8)
  48. copy(keyID, sum[12:20])
  49. return &session.Data{
  50. DC: dcID,
  51. Addr: addr,
  52. AuthKey: authKey,
  53. AuthKeyID: keyID,
  54. }, nil
  55. }