153 lines
5.5 KiB
Python
153 lines
5.5 KiB
Python
import sqlite3
|
|
from contextlib import closing
|
|
|
|
|
|
class BridgeStorage:
|
|
def __init__(self, db_path: str) -> None:
|
|
self._db_path = db_path
|
|
self._init_db()
|
|
|
|
def _connect(self) -> sqlite3.Connection:
|
|
return sqlite3.connect(self._db_path)
|
|
|
|
def _init_db(self) -> None:
|
|
with closing(self._connect()) as conn:
|
|
conn.execute(
|
|
"""
|
|
CREATE TABLE IF NOT EXISTS forwarded_messages (
|
|
message_id TEXT NOT NULL,
|
|
chat_id TEXT NOT NULL,
|
|
forwarded_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (message_id, chat_id)
|
|
)
|
|
"""
|
|
)
|
|
conn.execute(
|
|
"""
|
|
CREATE TABLE IF NOT EXISTS message_mapping (
|
|
telegram_chat_id TEXT NOT NULL,
|
|
telegram_message_id TEXT NOT NULL,
|
|
max_chat_id TEXT NOT NULL,
|
|
max_message_id TEXT NOT NULL,
|
|
media_group_id TEXT,
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (telegram_chat_id, telegram_message_id)
|
|
)
|
|
"""
|
|
)
|
|
conn.execute(
|
|
"CREATE INDEX IF NOT EXISTS idx_message_mapping_max ON message_mapping (max_chat_id, max_message_id)"
|
|
)
|
|
conn.execute(
|
|
"CREATE INDEX IF NOT EXISTS idx_message_mapping_media_group ON message_mapping (telegram_chat_id, media_group_id)"
|
|
)
|
|
conn.execute(
|
|
"""
|
|
CREATE TABLE IF NOT EXISTS chat_routes (
|
|
max_chat_title_norm TEXT PRIMARY KEY,
|
|
telegram_chat_id TEXT NOT NULL,
|
|
telegram_chat_title TEXT,
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
)
|
|
"""
|
|
)
|
|
conn.commit()
|
|
|
|
def was_forwarded(self, message_id: str, chat_id: str) -> bool:
|
|
with closing(self._connect()) as conn:
|
|
row = conn.execute(
|
|
"SELECT 1 FROM forwarded_messages WHERE message_id = ? AND chat_id = ?",
|
|
(message_id, chat_id),
|
|
).fetchone()
|
|
return row is not None
|
|
|
|
def mark_forwarded(self, message_id: str, chat_id: str) -> None:
|
|
with closing(self._connect()) as conn:
|
|
conn.execute(
|
|
"INSERT OR IGNORE INTO forwarded_messages (message_id, chat_id) VALUES (?, ?)",
|
|
(message_id, chat_id),
|
|
)
|
|
conn.commit()
|
|
|
|
def save_mapping(
|
|
self,
|
|
*,
|
|
telegram_chat_id: str,
|
|
telegram_message_id: str,
|
|
max_chat_id: str,
|
|
max_message_id: str,
|
|
media_group_id: str | None = None,
|
|
) -> None:
|
|
with closing(self._connect()) as conn:
|
|
conn.execute(
|
|
"""
|
|
INSERT OR REPLACE INTO message_mapping
|
|
(telegram_chat_id, telegram_message_id, max_chat_id, max_message_id, media_group_id)
|
|
VALUES (?, ?, ?, ?, ?)
|
|
""",
|
|
(telegram_chat_id, telegram_message_id, max_chat_id, max_message_id, media_group_id),
|
|
)
|
|
conn.commit()
|
|
|
|
def get_max_message_id_for_telegram(
|
|
self, *, telegram_chat_id: str, telegram_message_id: str
|
|
) -> str | None:
|
|
with closing(self._connect()) as conn:
|
|
row = conn.execute(
|
|
"""
|
|
SELECT max_message_id
|
|
FROM message_mapping
|
|
WHERE telegram_chat_id = ? AND telegram_message_id = ?
|
|
""",
|
|
(telegram_chat_id, telegram_message_id),
|
|
).fetchone()
|
|
if not row:
|
|
return None
|
|
return str(row[0])
|
|
|
|
def get_telegram_message_id_for_max(
|
|
self, *, telegram_chat_id: str, max_chat_id: str, max_message_id: str
|
|
) -> str | None:
|
|
"""Обратный поиск: какое сообщение в Telegram соответствует паре MAX chat/message."""
|
|
with closing(self._connect()) as conn:
|
|
row = conn.execute(
|
|
"""
|
|
SELECT telegram_message_id
|
|
FROM message_mapping
|
|
WHERE telegram_chat_id = ? AND max_chat_id = ? AND max_message_id = ?
|
|
ORDER BY telegram_message_id
|
|
LIMIT 1
|
|
""",
|
|
(telegram_chat_id, max_chat_id, max_message_id),
|
|
).fetchone()
|
|
if not row:
|
|
return None
|
|
return str(row[0])
|
|
|
|
def set_chat_route(
|
|
self,
|
|
*,
|
|
max_chat_title_norm: str,
|
|
telegram_chat_id: str,
|
|
telegram_chat_title: str | None = None,
|
|
) -> None:
|
|
with closing(self._connect()) as conn:
|
|
conn.execute(
|
|
"""
|
|
INSERT OR REPLACE INTO chat_routes (max_chat_title_norm, telegram_chat_id, telegram_chat_title)
|
|
VALUES (?, ?, ?)
|
|
""",
|
|
(max_chat_title_norm, telegram_chat_id, telegram_chat_title),
|
|
)
|
|
conn.commit()
|
|
|
|
def get_chat_route(self, *, max_chat_title_norm: str) -> str | None:
|
|
with closing(self._connect()) as conn:
|
|
row = conn.execute(
|
|
"SELECT telegram_chat_id FROM chat_routes WHERE max_chat_title_norm = ?",
|
|
(max_chat_title_norm,),
|
|
).fetchone()
|
|
if not row:
|
|
return None
|
|
return str(row[0])
|