Files

191 lines
6.5 KiB
Markdown

# Telethon Session Repair — Full Recipes
Real repair scripts used in production. Copy-paste and run.
## Fix 7-column → 6-column (drop `number`)
Two 7-column variants exist. ALWAYS check actual column names first.
### Variant A: `number` column (Telethon v2, 2026+)
Columns: `dc_id, server_address, port, auth_key, takeout_id, tmp_auth_key, number`
Drop the extra `number` column:
```python
import sqlite3, shutil
from pathlib import Path
SESSION_DIR = Path("sessions_clean")
for f in SESSION_DIR.glob("*.session"):
db = sqlite3.connect(str(f))
cur = db.execute("PRAGMA table_info(sessions)")
cols = [r[1] for r in cur.fetchall()]
db.close()
if len(cols) == 7 and "number" in cols:
shutil.copy(str(f), str(f) + ".bak7cols")
db = sqlite3.connect(str(f))
db.execute("""
CREATE TABLE sessions_new (
dc_id INT PRIMARY KEY, server_address TEXT, port INT,
auth_key BLOB, takeout_id INTEGER, tmp_auth_key BLOB
)
""")
db.execute("INSERT INTO sessions_new SELECT dc_id, server_address, port, auth_key, takeout_id, tmp_auth_key FROM sessions")
db.execute("DROP TABLE sessions")
db.execute("ALTER TABLE sessions_new RENAME TO sessions")
db.commit()
db.close()
print(f"Fixed: {f.name}")
```
### Variant B: `auth_key_id` column (older)
Columns: `dc_id, server_address, port, auth_key, auth_key_id, takeout_id, tmp_auth_key`
Drop the extra `auth_key_id` column:
```python
import sqlite3, shutil
from pathlib import Path
for f in Path("sessions_clean").glob("*.session"):
db = sqlite3.connect(str(f))
cur = db.execute("PRAGMA table_info(sessions)")
cols = [r[1] for r in cur.fetchall()]
db.close()
if len(cols) == 7 and "auth_key_id" in cols:
shutil.copy(str(f), str(f) + ".bak7cols")
db = sqlite3.connect(str(f))
db.execute("""
CREATE TABLE sessions_new (
dc_id INT, server_address TEXT, port INT,
auth_key BLOB, takeout_id INTEGER, tmp_auth_key BLOB
)
""")
db.execute("INSERT INTO sessions_new SELECT dc_id, server_address, port, auth_key, takeout_id, tmp_auth_key FROM sessions")
db.execute("DROP TABLE sessions")
db.execute("ALTER TABLE sessions_new RENAME TO sessions")
db.commit()
db.close()
print(f"Fixed: {f.name}")
```
## Fix 5-column → 6-column
Two 5-column variants exist. ALWAYS check the actual column names before repairing.
### Variant A: missing `takeout_id` (cols: `dc_id, server_address, port, auth_key, auth_key_id`)
Older Telethon v7 sessions. Add `takeout_id` as NULL.
```python
import sqlite3, shutil
from pathlib import Path
for f in Path("sessions_clean").glob("*.session"):
db = sqlite3.connect(str(f))
cur = db.execute("PRAGMA table_info(sessions)")
cols = [r[1] for r in cur.fetchall()]
db.close()
if len(cols) == 5 and "auth_key_id" in cols:
shutil.copy(str(f), str(f) + ".bak5cols")
db = sqlite3.connect(str(f))
db.execute("""
CREATE TABLE sessions_new (
dc_id INT, server_address TEXT, port INT,
auth_key BLOB, auth_key_id BLOB, takeout_id INTEGER
)
""")
db.execute("INSERT INTO sessions_new SELECT dc_id, server_address, port, auth_key, auth_key_id, NULL FROM sessions")
db.execute("DROP TABLE sessions")
db.execute("ALTER TABLE sessions_new RENAME TO sessions")
db.commit()
db.close()
print(f"Fixed: {f.name}")
```
### Variant B: missing `auth_key_id` (cols: `dc_id, server_address, port, auth_key, takeout_id`)
Encountered on MAINTG1.session (2026-07-28). This schema has `takeout_id` but no `auth_key_id`. Add `auth_key_id` as NULL.
```python
# PROVEN on MAINTG1.session (C:\Users\User\Desktop\_PROJECTS\tg_content_agent\)
import sqlite3, shutil
f = "MAINTG1.session"
db = sqlite3.connect(f)
cols = [r[1] for r in db.execute("PRAGMA table_info(sessions)")]
print(f"Cols: {cols}")
# Expected: ['dc_id', 'server_address', 'port', 'auth_key', 'takeout_id']
if len(cols) == 5 and "takeout_id" in cols and "auth_key_id" not in cols:
shutil.copy(f, f + ".bak5cols_v2")
db.execute("""
CREATE TABLE sessions_new (
dc_id INT, server_address TEXT, port INT,
auth_key BLOB, auth_key_id BLOB, takeout_id INTEGER
)
""")
db.execute("INSERT INTO sessions_new SELECT dc_id, server_address, port, auth_key, NULL, takeout_id FROM sessions")
db.execute("DROP TABLE sessions")
db.execute("ALTER TABLE sessions_new RENAME TO sessions")
db.commit()
# Verify
new_cols = [r[1] for r in db.execute("PRAGMA table_info(sessions)")]
row = db.execute("SELECT * FROM sessions").fetchone()
assert len(new_cols) == 6, f"Expected 6 cols, got {len(new_cols)}"
print(f"Fixed: {new_cols}, auth_key_len={len(row[3]) if row[3] else 0}")
db.close()
```
## Bulk session health check
```python
import sqlite3
from pathlib import Path
for d in ["sessions5", "sessions_clean", "session", "sessions_archive"]:
sd = Path(d)
if not sd.exists():
continue
for f in sorted(sd.glob("*.session")):
try:
db = sqlite3.connect(str(f))
cur = db.execute("PRAGMA table_info(sessions)")
cols = [r[1] for r in cur.fetchall()]
cur = db.execute("SELECT * FROM sessions")
row = cur.fetchone()
db.close()
status = "OK" if len(cols) == 6 and row and len(row) == 6 else f"BAD cols={len(cols)} row={len(row) if row else 0}"
print(f"{d}/{f.stem}: {status}")
except Exception as e:
print(f"{d}/{f.stem}: ERROR {e}")
```
## Check for corrupted auth_key (causes `TypeError: Strings must be encoded before hashing`)
```python
import sqlite3
from pathlib import Path
for d in ["sessions5", "sessions_clean"]:
for f in Path(d).glob("*.session"):
db = sqlite3.connect(str(f))
cur = db.execute("SELECT auth_key FROM sessions")
row = cur.fetchone()
db.close()
if row and row[0] is not None:
ak = row[0]
if isinstance(ak, str):
print(f"BAD (string auth_key): {f}")
elif isinstance(ak, bytes):
if len(ak) < 100:
print(f"SUSPECT (short auth_key {len(ak)}b): {f}")
else:
print(f"BAD (type {type(ak).__name__}): {f}")
else:
print(f"NULL auth_key: {f}")
```