Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
"""Durable state for Discord reconnect message recovery."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import datetime as dt
|
||||
import logging
|
||||
import os
|
||||
import sqlite3
|
||||
import threading
|
||||
from contextlib import suppress
|
||||
from pathlib import Path
|
||||
from typing import Any, Callable
|
||||
|
||||
from hermes_constants import get_hermes_home
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
_DB_FILENAME = "discord_message_recovery.db"
|
||||
_RETENTION_DAYS = 30
|
||||
|
||||
|
||||
class DiscordRecoveryStore:
|
||||
"""Small profile-scoped SQLite ledger for completed Discord messages."""
|
||||
|
||||
def __init__(self, hermes_home: Path | None = None) -> None:
|
||||
self._lock = threading.Lock()
|
||||
self._initialized = False
|
||||
self._hermes_home = Path(hermes_home or get_hermes_home())
|
||||
|
||||
def path(self) -> Path:
|
||||
directory = self._hermes_home / "gateway"
|
||||
directory.mkdir(parents=True, exist_ok=True)
|
||||
return directory / _DB_FILENAME
|
||||
|
||||
def call(self, fn: Callable[[sqlite3.Connection], Any], default: Any = None) -> Any:
|
||||
try:
|
||||
with self._lock:
|
||||
path = self.path()
|
||||
conn = sqlite3.connect(path, timeout=0.1)
|
||||
try:
|
||||
if not self._initialized:
|
||||
self._initialize(conn)
|
||||
self._initialized = True
|
||||
with suppress(OSError):
|
||||
os.chmod(path, 0o600)
|
||||
result = fn(conn)
|
||||
conn.commit()
|
||||
return result
|
||||
finally:
|
||||
conn.close()
|
||||
except Exception as exc:
|
||||
logger.warning("Discord recovery ledger unavailable: %s", exc)
|
||||
return default
|
||||
|
||||
def _initialize(self, conn: sqlite3.Connection) -> None:
|
||||
from hermes_state import apply_wal_with_fallback
|
||||
|
||||
apply_wal_with_fallback(conn, db_label="discord_recovery.db")
|
||||
conn.execute("""
|
||||
CREATE TABLE IF NOT EXISTS discord_messages (
|
||||
message_id TEXT PRIMARY KEY,
|
||||
channel_id TEXT,
|
||||
thread_id TEXT,
|
||||
parent_channel_id TEXT,
|
||||
author_id TEXT,
|
||||
created_at TEXT,
|
||||
status TEXT NOT NULL,
|
||||
replied INTEGER NOT NULL DEFAULT 0,
|
||||
emoji_ack INTEGER NOT NULL DEFAULT 0,
|
||||
outage_response INTEGER NOT NULL DEFAULT 0,
|
||||
response_message_id TEXT,
|
||||
attempts INTEGER NOT NULL DEFAULT 0,
|
||||
last_attempt_at TEXT,
|
||||
last_error TEXT,
|
||||
updated_at TEXT NOT NULL
|
||||
)
|
||||
""")
|
||||
conn.execute("""
|
||||
CREATE TABLE IF NOT EXISTS discord_recovery_scans (
|
||||
scan_id TEXT PRIMARY KEY,
|
||||
started_at TEXT NOT NULL,
|
||||
completed_at TEXT,
|
||||
status TEXT NOT NULL,
|
||||
channels TEXT NOT NULL,
|
||||
window_seconds REAL NOT NULL,
|
||||
limit_count INTEGER NOT NULL,
|
||||
scanned INTEGER NOT NULL DEFAULT 0,
|
||||
missed INTEGER NOT NULL DEFAULT 0,
|
||||
dispatched INTEGER NOT NULL DEFAULT 0,
|
||||
error TEXT
|
||||
)
|
||||
""")
|
||||
conn.execute("""
|
||||
CREATE TABLE IF NOT EXISTS discord_recovery_cursors (
|
||||
channel_id TEXT PRIMARY KEY,
|
||||
last_message_id TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL
|
||||
)
|
||||
""")
|
||||
cutoff = (
|
||||
dt.datetime.now(dt.timezone.utc) - dt.timedelta(days=_RETENTION_DAYS)
|
||||
).isoformat()
|
||||
conn.execute("DELETE FROM discord_messages WHERE updated_at < ?", (cutoff,))
|
||||
conn.execute(
|
||||
"DELETE FROM discord_recovery_scans "
|
||||
"WHERE COALESCE(completed_at, started_at) < ?",
|
||||
(cutoff,),
|
||||
)
|
||||
conn.execute(
|
||||
"DELETE FROM discord_recovery_cursors WHERE updated_at < ?",
|
||||
(cutoff,),
|
||||
)
|
||||
Reference in New Issue
Block a user