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
# Когда клиент запущен
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('Красивое оформление найденных кейсов включено')}")
# Включить/выключить копание
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)