autoreg-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
191
skills/telegram-automation/references/session-repair-recipes.md
Normal file
191
skills/telegram-automation/references/session-repair-recipes.md
Normal file
@@ -0,0 +1,191 @@
|
||||
# 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}")
|
||||
```
|
||||
Reference in New Issue
Block a user