|
@@ -0,0 +1,62 @@
|
|
|
|
|
+package sessionimport
|
|
|
|
|
+
|
|
|
|
|
+import (
|
|
|
|
|
+ "crypto/sha1"
|
|
|
|
|
+ "database/sql"
|
|
|
|
|
+ "fmt"
|
|
|
|
|
+
|
|
|
|
|
+ "github.com/gotd/td/session"
|
|
|
|
|
+ _ "modernc.org/sqlite"
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
|
|
+// ConvertPyrogramSession reads a Pyrogram/Telethon SQLite session file and
|
|
|
|
|
+// builds a gotd/td session.Data representing the same authorization.
|
|
|
|
|
+//
|
|
|
|
|
+// Pyrogram schema (single row in `sessions` table):
|
|
|
|
|
+//
|
|
|
|
|
+// CREATE TABLE sessions (
|
|
|
|
|
+// dc_id INTEGER PRIMARY KEY,
|
|
|
|
|
+// api_id INTEGER,
|
|
|
|
|
+// test_mode INTEGER,
|
|
|
|
|
+// auth_key BLOB, -- 256 bytes
|
|
|
|
|
+// date INTEGER NOT NULL,
|
|
|
|
|
+// user_id INTEGER,
|
|
|
|
|
+// is_bot INTEGER);
|
|
|
|
|
+func ConvertPyrogramSession(sqlitePath string) (*session.Data, error) {
|
|
|
|
|
+ // Open READ-ONLY + IMMUTABLE. Pyrogram .session files may be in-use by a
|
|
|
|
|
+ // running Pyrogram client; a write-capable handle could corrupt them via
|
|
|
|
|
+ // journal rollback on crash.
|
|
|
|
|
+ dsn := fmt.Sprintf("file:%s?mode=ro&immutable=1", sqlitePath)
|
|
|
|
|
+ db, err := sql.Open("sqlite", dsn)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return nil, fmt.Errorf("open pyrogram sqlite: %w", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ defer db.Close()
|
|
|
|
|
+
|
|
|
|
|
+ var dcID int
|
|
|
|
|
+ var authKey []byte
|
|
|
|
|
+ err = db.QueryRow(`SELECT dc_id, auth_key FROM sessions LIMIT 1`).Scan(&dcID, &authKey)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return nil, fmt.Errorf("read pyrogram sessions row: %w", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ if len(authKey) != 256 {
|
|
|
|
|
+ return nil, fmt.Errorf("invalid auth_key length: %d (want 256)", len(authKey))
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ addr, err := TGDCAddr(dcID)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return nil, err
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // auth_key_id = SHA-1(auth_key)[12:20] — lower 64 bits of the SHA-1 digest.
|
|
|
|
|
+ sum := sha1.Sum(authKey)
|
|
|
|
|
+ keyID := make([]byte, 8)
|
|
|
|
|
+ copy(keyID, sum[12:20])
|
|
|
|
|
+
|
|
|
|
|
+ return &session.Data{
|
|
|
|
|
+ DC: dcID,
|
|
|
|
|
+ Addr: addr,
|
|
|
|
|
+ AuthKey: authKey,
|
|
|
|
|
+ AuthKeyID: keyID,
|
|
|
|
|
+ }, nil
|
|
|
|
|
+}
|