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

Библиотека

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

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

Под компонентами подразумеваются функции, таблицы базы данных, 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)