Перейти к основному содержимому
Версия: Latest

SQL DataBase (db)

Основное, постоянное хранилище. Используется SQLite база данных.

Для каждого модуля создается своя база данных (при чем для каждого аккаунта своя). Эти базы данных находятся по пути /databases/<ModuleName>/database_<user_id>.db. Этот путь можно получить с помощью mod.db_path

Методы

Система set-get.

Данные хранятся в формате ключ - значение. Хранится могут только простые типы и структуры данных: str, int, float, bool, None, list, dict

к сведению

Ниже, под типом данных Any будет подразумеваться вышеперечисленные простые типы и структуры данных

  • async set

    Устанавливает значение.

    Аргументы:

    • variable (str) - Имя переменной (ключ)
    • value (Any) - Значение.

    Возвращает: None

    Пример:

    await mod.db.set('count', 10)
  • async get

    Получить значение. Если записи с таким ключем не существует - вернется default

    Аргументы:

    • variable (str) - Имя переменной (ключ)
    • default (optional) = None - Значение по умолчанию. Вернется если variable не найден

    Возвращает: Any - значение переменной

    Пример:

    count = await mod.db.get('count', 0)
  • async getall

    Получить все значения.

    Аргументы:

    • default (optional) = None - Значение по умолчанию. Вернется если никаких переменных нет в БД.

    Возвращает: List[str, Any] - Словарь значений, где ключи это имена переменных

    Пример:

    all_values = await mod.db.getall()
  • async remove / delete

    Удаляет переменную из базы данных

    Аргументы:

    • variable (str) - имя переменной, которую надо удалить

    Возвращает: None

    Пример:

    await mod.db.remove('count')

SQL

Кроме set-get можно использовать SQL БД напрямую - через сам SQL!

  • async sql

    Выполнить SQL запрос.

    Аргументы:

    • sql (str) - SQL запрос
    • asdict (optional, bool) = False - Вернуть результат в формате словаря (колонка: значение)
    • **params - значения для передачи в SQL запрос.
    осторожно

    Всегда используйте параметры запроса (**params) для подстановки значений!

    Нельзя вставлять данные напрямую через f-строки или +, это открывает уязвимость для SQL-инъекций.

    Правильно:

    await mod.db.sql("SELECT * FROM users WHERE age > :age", age=18)

    НЕправильно:

    await mod.db.sql(f"SELECT * FROM users WHERE age > {age}")  # Уязвимость!!!!

    Передача параметров через **params автоматически защищает от атак и делает код безопасным.

    Возвращает: None | Tuple[Tuple[Any]] | Dict[str, Any] - Результат SQL запроса.

    к сведению

    Если запрос возвращает данные, то вывод будет таким:

    • При asdict=True: [{колонка: значение, ...}, ...]
    • При asdict=False: [(значение1, значение2, ...), ...]

    Пример:

    result = await mod.db.sql("SELECT id, name FROM users WHERE age > :age", asdict=True, age=18)
    # Пример результата: [{"id": 1, "name": "Алиса"}, {"id": 2, "name": "Боб"}]

Примеры:

к сведению

Данные примеры взяты из модуля MineEvoMiner (версия 2.5) стороннего разработчика @Kotcananacom

MineEvoMiner/miner/mine.py, lines 25-42
# Когда клиент запущен
async def stats_ready(app: Client, mod: Module):
AutoStopTimer(app, mod)
mod.add_task(miner(app, mod))
if await mod.db.get('mine', False):
await mod.db.set('start_mine', time.time())
await mod.db.sql("CREATE TABLE IF NOT EXISTS mineevo_stats (type_case TEXT, type_bust TEXT, count INTEGER, timee TEXT)")
await initialization_found(app, mod)


# Включить/выключить красивое оформление для найденных кейсов
async def beautiful_case_found(app: Client, msg: Message, mod: Module):
beautiful = await mod.db.get('beautiful_found', False)
await mod.db.set('beautiful_found', not beautiful)
if beautiful:
await msg.edit(f"{Emojis.YES_2} {b('Оформление найденных кейсов выключено')}")
else:
await msg.edit(f"{Emojis.YES} {b('Красивое оформление найденных кейсов включено')}")
MineEvoMiner/miner/mine.py, lines 161-177
# Включить/выключить копание
async def mine_cmd(app: Client, msg: Message, mod: Module):
mine = await mod.db.get('mine', False)
clicks = await mod.db.get('clicks', 0)
get_mine_bot_value = await get_mine_bot(mod)
await mod.db.set('mine', not mine)
if mine:
await mod.db.set('end_mine', time.time())
start = await mod.db.get('start_mine', 0)
end = await mod.db.get('end_mine', 0)
if end > start:
session_time = end - start
total_time = await mod.db.get('mine_total_time', 0)
total_time += session_time
await mod.db.set('mine_total_time', total_time)
cases = await mod.db.sql("SELECT type_case, SUM(count) FROM mineevo_stats WHERE timee BETWEEN :start_time AND :end_time GROUP BY type_case", start_time=start, end_time=end)
busts = await mod.db.sql("SELECT type_bust, SUM(count) FROM mineevo_stats WHERE timee BETWEEN :start_time AND :end_time GROUP BY type_bust", start_time=start, end_time=end)