initial
This commit is contained in:
+501
@@ -0,0 +1,501 @@
|
||||
import aiosqlite
|
||||
from datetime import datetime
|
||||
import json
|
||||
|
||||
|
||||
DB_NAME = "database/database.db"
|
||||
|
||||
|
||||
async def init_db():
|
||||
|
||||
async with aiosqlite.connect(DB_NAME) as db:
|
||||
|
||||
# Пользователи
|
||||
await db.execute("""
|
||||
CREATE TABLE IF NOT EXISTS users(
|
||||
|
||||
user_id INTEGER PRIMARY KEY,
|
||||
|
||||
username TEXT,
|
||||
|
||||
first_name TEXT,
|
||||
|
||||
last_name TEXT,
|
||||
|
||||
phone TEXT,
|
||||
|
||||
email TEXT,
|
||||
|
||||
group_id INTEGER,
|
||||
|
||||
group_name TEXT,
|
||||
|
||||
subgroup TEXT,
|
||||
|
||||
created_at TEXT,
|
||||
|
||||
last_seen TEXT
|
||||
|
||||
)
|
||||
""")
|
||||
|
||||
# Кэш расписания
|
||||
await db.execute("""
|
||||
CREATE TABLE IF NOT EXISTS schedule_cache(
|
||||
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
|
||||
group_id INTEGER NOT NULL,
|
||||
|
||||
date TEXT NOT NULL,
|
||||
|
||||
data TEXT NOT NULL,
|
||||
|
||||
created_at TEXT NOT NULL,
|
||||
|
||||
UNIQUE(group_id, date)
|
||||
|
||||
)
|
||||
""")
|
||||
|
||||
# Индекс
|
||||
await db.execute("""
|
||||
CREATE INDEX IF NOT EXISTS idx_schedule_cache
|
||||
ON schedule_cache(group_id, date)
|
||||
""")
|
||||
|
||||
# Поддержка
|
||||
await db.execute("""
|
||||
CREATE TABLE IF NOT EXISTS support(
|
||||
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
|
||||
user_id INTEGER NOT NULL,
|
||||
|
||||
message TEXT NOT NULL,
|
||||
|
||||
answer TEXT,
|
||||
|
||||
status TEXT DEFAULT 'open',
|
||||
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
|
||||
)
|
||||
""")
|
||||
|
||||
await db.commit()
|
||||
|
||||
async def save_group(
|
||||
user_id: int,
|
||||
group_id: int,
|
||||
group_name: str,
|
||||
subgroup: str | None = None
|
||||
):
|
||||
|
||||
async with aiosqlite.connect(DB_NAME) as db:
|
||||
|
||||
await db.execute(
|
||||
"""
|
||||
INSERT INTO users(
|
||||
user_id,
|
||||
group_id,
|
||||
group_name,
|
||||
subgroup
|
||||
)
|
||||
|
||||
VALUES(?,?,?,?)
|
||||
|
||||
ON CONFLICT(user_id)
|
||||
|
||||
DO UPDATE SET
|
||||
|
||||
group_id = excluded.group_id,
|
||||
|
||||
group_name = excluded.group_name,
|
||||
|
||||
subgroup = excluded.subgroup
|
||||
|
||||
""",
|
||||
(
|
||||
user_id,
|
||||
group_id,
|
||||
group_name,
|
||||
subgroup
|
||||
)
|
||||
)
|
||||
|
||||
await db.commit()
|
||||
|
||||
|
||||
|
||||
async def get_group(
|
||||
user_id: int
|
||||
):
|
||||
|
||||
async with aiosqlite.connect(DB_NAME) as db:
|
||||
|
||||
cursor = await db.execute(
|
||||
"""
|
||||
SELECT
|
||||
|
||||
group_id,
|
||||
|
||||
group_name,
|
||||
|
||||
subgroup
|
||||
|
||||
FROM users
|
||||
|
||||
WHERE user_id=?
|
||||
|
||||
""",
|
||||
(
|
||||
user_id,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
row = await cursor.fetchone()
|
||||
|
||||
|
||||
if row is None:
|
||||
return None
|
||||
|
||||
|
||||
return {
|
||||
|
||||
"group_id": row[0],
|
||||
|
||||
"group_name": row[1],
|
||||
|
||||
"subgroup": row[2]
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
async def delete_group(
|
||||
user_id: int
|
||||
):
|
||||
|
||||
async with aiosqlite.connect(DB_NAME) as db:
|
||||
|
||||
await db.execute(
|
||||
"""
|
||||
DELETE FROM users
|
||||
|
||||
WHERE user_id=?
|
||||
|
||||
""",
|
||||
(
|
||||
user_id,
|
||||
)
|
||||
)
|
||||
|
||||
await db.commit()
|
||||
|
||||
|
||||
|
||||
async def update_subgroup(
|
||||
user_id: int,
|
||||
subgroup: str
|
||||
):
|
||||
|
||||
async with aiosqlite.connect(DB_NAME) as db:
|
||||
|
||||
await db.execute(
|
||||
"""
|
||||
UPDATE users
|
||||
|
||||
SET subgroup=?
|
||||
|
||||
WHERE user_id=?
|
||||
|
||||
""",
|
||||
(
|
||||
subgroup,
|
||||
user_id
|
||||
)
|
||||
)
|
||||
|
||||
await db.commit()
|
||||
|
||||
async def create_ticket(
|
||||
user_id: int,
|
||||
message: str
|
||||
):
|
||||
|
||||
async with aiosqlite.connect(DB_NAME) as db:
|
||||
|
||||
cursor = await db.execute(
|
||||
"""
|
||||
INSERT INTO support(
|
||||
user_id,
|
||||
message
|
||||
)
|
||||
VALUES(?,?)
|
||||
""",
|
||||
(
|
||||
user_id,
|
||||
message
|
||||
)
|
||||
)
|
||||
|
||||
await db.commit()
|
||||
|
||||
return cursor.lastrowid
|
||||
|
||||
#tickets
|
||||
async def get_ticket(ticket_id: int):
|
||||
|
||||
async with aiosqlite.connect(DB_NAME) as db:
|
||||
|
||||
cursor = await db.execute(
|
||||
"""
|
||||
SELECT
|
||||
id,
|
||||
user_id,
|
||||
message,
|
||||
status
|
||||
FROM support
|
||||
WHERE id=?
|
||||
""",
|
||||
(ticket_id,)
|
||||
)
|
||||
|
||||
row = await cursor.fetchone()
|
||||
|
||||
return row
|
||||
|
||||
async def get_tickets():
|
||||
|
||||
async with aiosqlite.connect(DB_NAME) as db:
|
||||
|
||||
cursor = await db.execute(
|
||||
"""
|
||||
SELECT
|
||||
id,
|
||||
user_id,
|
||||
message,
|
||||
status
|
||||
FROM support
|
||||
WHERE status='open'
|
||||
ORDER BY id DESC
|
||||
"""
|
||||
)
|
||||
|
||||
rows = await cursor.fetchall()
|
||||
|
||||
return rows
|
||||
|
||||
async def close_ticket(ticket_id: int):
|
||||
|
||||
async with aiosqlite.connect(DB_NAME) as db:
|
||||
|
||||
await db.execute(
|
||||
"""
|
||||
UPDATE support
|
||||
SET status='closed'
|
||||
WHERE id=?
|
||||
""",
|
||||
(ticket_id,)
|
||||
)
|
||||
|
||||
await db.commit()
|
||||
|
||||
|
||||
async def update_user(
|
||||
user_id: int,
|
||||
username: str | None = None,
|
||||
first_name: str | None = None,
|
||||
last_name: str | None = None
|
||||
):
|
||||
|
||||
now = datetime.now().isoformat()
|
||||
|
||||
|
||||
async with aiosqlite.connect(DB_NAME) as db:
|
||||
|
||||
await db.execute(
|
||||
"""
|
||||
INSERT INTO users(
|
||||
user_id,
|
||||
username,
|
||||
first_name,
|
||||
last_name,
|
||||
created_at,
|
||||
last_seen
|
||||
)
|
||||
|
||||
VALUES(?,?,?,?,?,?)
|
||||
|
||||
ON CONFLICT(user_id)
|
||||
|
||||
DO UPDATE SET
|
||||
|
||||
username=excluded.username,
|
||||
first_name=excluded.first_name,
|
||||
last_name=excluded.last_name,
|
||||
last_seen=excluded.last_seen
|
||||
|
||||
""",
|
||||
|
||||
(
|
||||
user_id,
|
||||
username,
|
||||
first_name,
|
||||
last_name,
|
||||
now,
|
||||
now
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
await db.commit()
|
||||
|
||||
async def save_phone(
|
||||
user_id: int,
|
||||
phone: str
|
||||
):
|
||||
|
||||
async with aiosqlite.connect(DB_NAME) as db:
|
||||
|
||||
await db.execute(
|
||||
"""
|
||||
UPDATE users
|
||||
SET phone=?
|
||||
WHERE user_id=?
|
||||
""",
|
||||
(
|
||||
phone,
|
||||
user_id
|
||||
)
|
||||
)
|
||||
|
||||
await db.commit()
|
||||
|
||||
async def get_cached_schedule(
|
||||
group_id: int,
|
||||
schedule_date: str,
|
||||
ttl_minutes: int
|
||||
):
|
||||
|
||||
async with aiosqlite.connect(DB_NAME) as db:
|
||||
|
||||
cursor = await db.execute(
|
||||
"""
|
||||
SELECT
|
||||
data,
|
||||
created_at
|
||||
|
||||
FROM schedule_cache
|
||||
|
||||
WHERE group_id=?
|
||||
AND date=?
|
||||
|
||||
""",
|
||||
(
|
||||
group_id,
|
||||
schedule_date
|
||||
)
|
||||
)
|
||||
|
||||
row = await cursor.fetchone()
|
||||
|
||||
|
||||
if row is None:
|
||||
return None
|
||||
|
||||
|
||||
created = datetime.fromisoformat(
|
||||
row[1]
|
||||
)
|
||||
|
||||
|
||||
age = (
|
||||
datetime.now() - created
|
||||
).total_seconds() / 60
|
||||
|
||||
|
||||
# кэш устарел
|
||||
|
||||
if age > ttl_minutes:
|
||||
|
||||
return None
|
||||
|
||||
|
||||
return json.loads(row[0])
|
||||
|
||||
async def save_schedule_cache(
|
||||
group_id: int,
|
||||
schedule_date: str,
|
||||
data: dict
|
||||
):
|
||||
|
||||
async with aiosqlite.connect(DB_NAME) as db:
|
||||
|
||||
await db.execute(
|
||||
"""
|
||||
INSERT INTO schedule_cache(
|
||||
group_id,
|
||||
date,
|
||||
data,
|
||||
created_at
|
||||
)
|
||||
|
||||
VALUES(?,?,?,?)
|
||||
|
||||
ON CONFLICT(group_id, date)
|
||||
|
||||
DO UPDATE SET
|
||||
|
||||
data = excluded.data,
|
||||
created_at = excluded.created_at
|
||||
""",
|
||||
(
|
||||
group_id,
|
||||
schedule_date,
|
||||
json.dumps(
|
||||
data,
|
||||
ensure_ascii=False
|
||||
),
|
||||
datetime.now().isoformat()
|
||||
)
|
||||
)
|
||||
|
||||
await db.commit()
|
||||
|
||||
|
||||
async def clear_old_cache(days: int = 30):
|
||||
|
||||
async with aiosqlite.connect(DB_NAME) as db:
|
||||
|
||||
cursor = await db.execute(
|
||||
"""
|
||||
DELETE FROM schedule_cache
|
||||
WHERE datetime(created_at)
|
||||
< datetime('now', ?)
|
||||
""",
|
||||
(f"-{days} days",)
|
||||
)
|
||||
|
||||
await db.commit()
|
||||
|
||||
return cursor.rowcount
|
||||
|
||||
|
||||
async def get_active_groups():
|
||||
|
||||
async with aiosqlite.connect(DB_NAME) as db:
|
||||
|
||||
cursor = await db.execute(
|
||||
"""
|
||||
SELECT DISTINCT group_id
|
||||
FROM users
|
||||
WHERE group_id IS NOT NULL
|
||||
"""
|
||||
)
|
||||
|
||||
rows = await cursor.fetchall()
|
||||
|
||||
return [row[0] for row in rows]
|
||||
Reference in New Issue
Block a user