К содержимому

Библиотека

Работая над несколькими расширениями, у вас может возникнуть необходимость использовать общие компоненты. К примеру вы замечаете что вам нужны одинаковые функции в обоих расширениях. Это верный признак того, что пора выделить общий функционал в библиотеку.

Библиотека - набор общих компонентов с единой целью, доступный между несколькими расширениями.

Под компонентами подразумеваются функции, таблицы базы данных, view и прочее, что мы выделяем из расширений. Как и в случае с расширениями, хорошим тоном будет делать атомарные библиотеки. Чтобы их можно было легко переиспользовать другим разработчикам.

Все библиотеки находятся в директории libs/. Название библиотеки должно чётко отражать её суть. Вот пара примеров простых библиотек:

  • Директорияlibs
    • format.py Библиотека форматирования
    • music.py Музыкальный плеер (большой)
    • …

Если функционал библиотеки становится слишком большим для поддержания в одном файле, то для библиотеки выделяются отдельная директория. Можно привести пример с нашим любимым музыкальным плеером:

  • Директорияlibs
    • Директорияmusic Музыкальный плеер
      • player.py Класс музыкального плеера для сервера
      • events.py События, которые вызывает плеер во время работы
      • view.py Клавиатура для управления плеером
      • …
    • format.py Библиотека форматирования
    • …

При таком подходе хорошей практикой будет разделить модели по компонентам.

Предположим вы захотели создать библиотеку format, со вспомогательными функциями для красивого форматирования значений.

Тогда ваша они может выглядеть следующим образом:

def format_duration(n: int) -> str:
"""Возвращает обратный отсчёт по количеству секунд."""
def format_time(time: datetime) -> str:
"""Возвращает красивый формат времени."""
def format_pos(n: int) -> str:
"""Возвращает позицию участника в таблице лидеров."""

Здесь мы приведём только заголовки функций и описание к ним. Реализацию оставим на выше усмотрение.

Создание таблиц для базы данных это самый частый случай использование библиотек.

Вот шаблонный пример минимальной библиотеки с использование базы данных. В этот раз пусть это будет пример с активностью пользователя:

from chioricord.api import DBTable, DBModel
from dataclasses import dataclass
@dataclass(slots=True)
class UserActive(DBModel):
"""Активность пользователя на сервера."""
id: int
message: int
words: int
voice: int
class ActiveTable(DBTable, table="active"):
"""Таблица активности пользователя."""
async def create_table(self) -> None:
"""Создаёт таблицу базы данных."""
async def user(self, user_id: int) -> UserActive:
"""Получает активность пользователя по его ID."""

Опять же пример заголовков, без конкретной реализации.

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

from chioricord.api import DBTable, DBModel
from chioricord.event import DBEvent
from dataclasses import dataclass
@dataclass(slots=True)
class UserActive(DBModel):
"""Активность пользователя на сервера."""
id: int
message: int
words: int
voice: int
@dataclass(frozen=True, slots=True)
class LevelUpEvent(DBEvent):
"""Когда пользователь повышает свой уровень."""
user: UserActive # Предположим что он уже есть в вашем файле

Работая над большой библиотекой, у вас может возникнуть потребность переиспользовать компоненты уже из других библиотек. Вы можете так сделать, только будьте очень осторожны.

После того как мы создали нашу замечательную библиотеку, самое время использовать её в расширениях.

Это делается очень просто, через импорты. Давайте рассмотрим это на примере:

from datetime import datetime, UTC
from libs.format import format_time
@plugin.include
@arc.slash_command("now", description="Который сейчас час")
async def command_name_handler(ctx: ChioContext, ) -> None:
"""Возвращает отформатированное время."""
await ctx.respond(format_time(datetime.now(UTC)))

По такому же принципу, вы можете использовать и другие компоненты библиотек.

Как вы уже знаете, базы данных и настройки стоит регистрировать в боте. Для этого используется загрузчик расширений. А расширения, которые нужны для загрузки компонентов из библиотек, называют расширение-помощники.

import loader
from chioricord.plugin import ChioPlugin
from libs.active import ActiveTable
plugin = ChioPlugin("Active")
# Дальше тут ваши команды, события и прочее
@arc.loader
def loader(client: ChioClient) -> None:
"""Actions on plugin load."""
client.add_table(ActiveTable) # MyTable - таблица из библиотеки
client.add_plugin(plugin)