简体中文 English 繁體中文 日本語 Русский
本文为静态镜像,内容以交互版为准 在交互式文档中心打开 →

Характеристики платформы пользователей Yunhu

YunhuUserAdapter представляет собой адаптер, построенный на основе протокола учетных записей пользователей Yunhu. Он обеспечивает вход пользователя по электронной почте, получение событий через WebSocket и предоставляет единый интерфейс для обработки событий и операций сообщений.

Информация о документации

Основная информация

Обновление парадигмы v5 (4.2.0)

Список функций, подключённых к платформе

Получение событий (WebSocket, protobuf-кодирование)

WS cmd Событие Описание
push_message message Сообщения в личных/групповых чатах/чате с ботом (текст/HTML/Markdown/изображения/видео/аудио/файлы/эмодзи/формы/статьи/стикеры/кнопки/A2UI)
edit_message notice (message_edit) Уведомление об изменении сообщения
file_send_message notice (yunhu_user_file_send) Обмен суперфайлами
bot_board_message notice (yunhu_user_bot_board) Баннер с уведомлениями бота

Методы Api DSL (YunhuHTTPClient → конечные точки API v1 для пользователя)

Категория Метод Api Конечная точка Описание
Аккаунт get_self_info() /user/info Информация о пользователе (ник/аватар/user_id)
Пользователь get_user(user_id) /user/get-user Детальная информация о пользователе
Пользователь edit_nickname(nickname) /user/edit-nickname Изменить свой никнейм
Пользователь edit_avatar(url) /user/edit-avatar Изменить свой аватар
Друзья get_friend_address_book(md5) /friend/address-book-list Адресная книга (постраничный просмотр)
Друзья get_friend_requests() /friend/request-list Список запросов на добавление в друзья/в группы
Друзья friend_apply(user_id, desc) /friend/apply Запрос на добавление в друзья
Друзья friend_agree_apply(user_id) /friend/agree-apply Подтвердить запрос на добавление в друзья
Друзья friend_ignore_apply(user_id) /friend/ignore-apply Игнорировать запрос на добавление в друзья
Друзья friend_delete(user_id) /friend/delete-friend Удалить друга
Группы get_group_info(group_id) /group/info Информация о группе
Группы get_group_member_list(group_id) /group/list-member Список участников группы (поддержка поиска по ключевым словам)
Группы create_group(name, ...) /group/create-group Создать группу
Группы dismiss_group(group_id) /group/dismiss-group Распустить группу
Группы group_invite(group_id, user_ids) /group/invite Пригласить в группу
Группы group_remove_member(group_id, user_id) /group/remove-member Удалить участника из группы
Группы group_gag_member(group_id, user_id, секунды) /group/gag-member Замолчить участника (0=отменить)
Группы get_group_bot_list(group_id) /group/bot-list Список ботов в группе
Чаты get_conversation_list(md5) /conversation/list Список чатов (постраничный просмотр)
Сообщения get_message_list(chat_id, chat_type, ...) /msg/list-message Список сообщений (различные варианты прокрутки см. в HTTP-клиенте)
Сообщения delete_message(msg_id, chat_id, chat_type) /msg/recall-msg Отозвать сообщение (массовое удаление см. в HTTP-клиенте)
Сообщения button_report(...) /msg/button-report Отправить отчёт о нажатии кнопки
Операции get_status / get_version / get_supported_actions - Статус работы/версия/поддерживаемые действия

Функции, ещё не подключены (конечные точки известны, сообщения в full.proto полны, можно расширять по мере необходимости)

Способ расширения: добавить методы в YunhuHTTPClient по уже существующему шаблону (использовать общую обёртку _proto_request / _json_request), затем экспортировать в классе Api. Описание конечных точек и сообщений смотрите в yhchatAPI/src/api/v1/*.md и yhchatAPI/src/full.proto.

Пример использования API пользователя

from ErisPulse import sdk
yunhu_user = sdk.adapter.get("yunhu_user")

result = await yunhu_user.Api.get_self_info()
result = await yunhu_user.Api.get_friend_requests()          # Список запросов на добавление в друзья
await yunhu_user.Api.friend_agree_apply(user_id)             # Подтвердить запрос на добавление в друзья
result = await yunhu_user.Api.get_group_member_list(group_id)
result = await yunhu_user.Api.get_conversation_list()        # Список чатов
await yunhu_user.Api.delete_message(msg_id, chat_id, chat_type)  # Отозвать сообщение

Поддерживаемые типы отправки сообщений

Все методы отправки реализованы с использованием цепочечного синтаксиса, например:

from ErisPulse.Core import adapter
yunhu_user = adapter.get("yunhu_user")

await yunhu_user.Send.To("user", user_id).Text("Hello World!")

Поддерживаемые типы отправки включают:

Обработка медиафайлов

Все типы медиа (изображения, видео, аудио, файлы) поддерживают следующие способы ввода:

Медиафайлы автоматически загружаются в хранилище Qiniu, поддерживаются следующие функции:

Описание параметра кнопок

Параметр buttons представляет собой вложенный список, описывающий расположение и функции кнопок. Каждый объект кнопки содержит следующие поля:

Поле Тип Обязательно Описание
text string Да Текст на кнопке
actionType int Да Тип действия:
1: переход по URL
2: копирование
3: отправка события
url string Нет Используется, когда actionType=1, указывает целевой URL для перехода
value string Нет Когда actionType=2, значение копируется в буфер обмена
Когда actionType=3, значение отправляется подписчику

Пример:

buttons = [
    [
        {"text": "Копировать", "actionType": 2, "value": "xxxx"},
        {"text": "Перейти по ссылке", "actionType": 1, "url": "http://www.baidu.com"},
        {"text": "Отправить событие", "actionType": 3, "value": "xxxxx"}
    ]
]
await yunhu_user.Send.To("user", user_id).Buttons(buttons).Text("Сообщение с кнопками")

Методы цепочечного форматирования (можно комбинировать)

Методы цепочечного форматирования возвращают self, поддерживают цепочечное использование и должны вызываться до окончательного метода отправки:

Примечание: Поскольку учетная запись пользователя является особой, даже неадминистратор может упоминать всех, но AtAll() просто отправляет текст с упоминанием всех, это псевдоупоминание всех.

Примеры цепочечного вызова

# Базовая отправка
await yunhu_user.Send.To("user", user_id).Text("Hello")

# Ответ на сообщение
await yunhu_user.Send.To("group", group_id).Reply(msg_id).Text("Ответ на сообщение")

# Ответ + кнопки
await yunhu_user.Send.To("group", group_id).Reply(msg_id).Buttons(buttons).Text("Сообщение с ответом и кнопками")

# Указание аккаунта + ответ + кнопки
await yunhu_user.Send.Using("default").To("group", group_id).Reply(msg_id).Buttons(buttons).Text("Полный цепочечный вызов")

Поддержка OneBot12 сообщений

Адаптер поддерживает отправку сообщений в формате OneBot12, что обеспечивает совместимость сообщений между платформами:

# Отправка сообщения в формате OneBot12
ob12_msg = [{"type": "text", "data": {"text": "Hello"}}]
await yunhu_user.Send.To("user", user_id).Raw_ob12(ob12_msg)

# В сочетании с цепочечными методами
ob12_msg = [{"type": "text", "data": {"text": "Ответ на сообщение"}}]
await yunhu_user.Send.To("group", group_id).Reply(msg_id).Raw_ob12(ob12_msg)

.Raw_ob12 поддерживает автоматическую группировку смешанных сообщений:

Возвращаемые значения методов отправки

Все методы отправки возвращают объект Task, который можно напрямую ожидать с помощью await, чтобы получить результат отправки. Возвращаемый результат соответствует стандартизированному формату ответа адаптера ErisPulse:

{
    "status": "ok",           // Статус выполнения
    "retcode": 0,             // Код возврата
    "data": {...},            // Ответные данные
    "message_id": "123456",   // Идентификатор сообщения
    "message": "",            // Сообщение об ошибке
    "yunhu_user_raw": {...}   // Необработанные данные ответа
}

Специфические типы событий

Необходимо проверять platform == "yunhu_user", чтобы использовать функции данной платформы.

Основные отличия

  1. Специфические типы событий:
    • Супер-файлы-раздача: yunhu_user_file_send
    • Доска объявлений бота: yunhu_user_bot_board
    • Уведомление об изменении сообщения: message_edit
    • Уведомление об удалении сообщения: message_delete (отмена отправки)
  2. Специфические типы сообщений:
    • Форма сообщения: yunhu_user_form
    • Статья сообщения: yunhu_user_post
    • Наклейка сообщения: yunhu_user_sticker
    • Кнопка сообщения: yunhu_user_button
    • Сообщение A2UI: a2ui
  3. Расширенные поля:
    • Все специфические поля имеют префикс yunhu_user_
    • Исходные данные сохраняются в поле yunhu_user_raw
    • Оригинальный тип события сохраняется в поле yunhu_user_raw_type
    • В личных сообщениях self.user_id указывает на ID текущего пользователя

Поддерживаемые оригинальные типы событий

Оригинальный тип события Тип OneBot12 Описание
push_message message Отправка сообщения (личный чат, групповой чат, чат с ботом)
edit_message notice (message_edit) Событие редактирования сообщения
file_send_message notice (yunhu_user_file_send) Событие супер-файла-раздачи
bot_board_message notice (yunhu_user_bot_board) Событие доски объявлений бота

Другие типы событий (например, heartbeat_ack, draft_input, stream_message и т.д.) будут проигнорированы.

Поддерживаемые detail_type OneBot12

detail_type OneBot12 chat_type yunhu Описание
private 1 Личное сообщение
group 2 Групповое сообщение
bot 3 Чат с ботом

Примеры событий сообщений

{
    "id": "event_id",
    "time": 1234567890,
    "type": "message",
    "detail_type": "group",
    "platform": "yunhu_user",
    "self": {
        "platform": "yunhu_user",
        "user_id": "your_user_id"
    },
    "message": [
        {"type": "text", "data": {"text": "Содержание сообщения"}}
    ],
    "alt_message": "Содержание сообщения",
    "user_id": "sender_user_id",
    "user_nickname": "Имя отправителя",
    "group_id": "group_id",
    "message_id": "msg_id",
    "yunhu_user_raw": {...},
    "yunhu_user_raw_type": "push_message"
}

Пример уведомления об изменении сообщения

{
    "type": "notice",
    "detail_type": "message_edit",
    "platform": "yunhu_user",
    "self": {
        "platform": "yunhu_user",
        "user_id": "your_user_id"
    },
    "message_id": "msg_id",
    "user_id": "sender_user_id",
    "user_nickname": "Имя отправителя",
    "edit_time": 1234567890,
    "group_id": "group_id",
    "yunhu_user_raw": {...},
    "yunhu_user_raw_type": "edit_message"
}

Пример события супер-файла-раздачи

{
    "type": "notice",
    "detail_type": "yunhu_user_file_send",
    "platform": "yunhu_user",
    "self": {
        "platform": "yunhu_user",
        "user_id": "your_user_id"
    },
    "user_id": "send_user_id",
    "user_nickname": "",
    "yunhu_user_file_send": {
        "send_user_id": "ID отправителя",
        "user_id": "ID получателя",
        "send_type": "Тип отправки",
        "data": "Данные файла"
    },
    "yunhu_user_raw": {...},
    "yunhu_user_raw_type": "file_send_message"
}

Пример события доски объявлений бота

{
    "type": "notice",
    "detail_type": "yunhu_user_bot_board",
    "platform": "yunhu_user",
    "self": {
        "platform": "yunhu_user",
        "user_id": "your_user_id"
    },
    "bot_id": "bot_id",
    "bot_name": "Имя бота",
    "yunhu_user_bot_board": {
        "bot_id": "bot_id",
        "chat_id": "chat_id",
        "chat_type": 1,
        "content": "Содержание объявления",
        "content_type": 1,
        "last_update_time": 1234567890
    },
    "yunhu_user_raw": {...},
    "yunhu_user_raw_type": "bot_board_message"
}

Пример обработки событий

from ErisPulse.Core.Event import message, notice

@message.on_message()
async def handle_yunhu_user_message(event):
    """Обработка сообщений пользователя yunhu"""
    if event.get("platform") != "yunhu_user":
        return
    
    user_id = event.get("user_id", "")
    user_nickname = event.get("user_nickname", "")
    alt_message = event.get("alt_message", "")
    
    print(f"Пользователь {user_nickname}({user_id}): {alt_message}")
    
    # Проверка специфических типов сообщений
    for segment in event.get("message", []):
        seg_type = segment.get("type", "")
        
        if seg_type == "yunhu_user_form":
            form_data = segment["data"]["form"]
            print(f"Получено сообщение-форма: {form_data}")
        
        elif seg_type == "yunhu_user_post":
            post_data = segment["data"]
            print(f"Получено сообщение-статья: {post_data.get('post_title', '')}")
        
        elif seg_type == "yunhu_user_sticker":
            sticker_url = segment["data"]["file_id"]
            print(f"Получено сообщение-наклейка: {sticker_url}")
        
        elif seg_type == "yunhu_user_button":
            buttons = segment["data"]["buttons"]
            print(f"Сообщение содержит кнопки: {buttons}")
        
        elif seg_type == "a2ui":
            a2ui_data = segment["data"]["a2ui"]
            print(f"Получено сообщение A2UI: {a2ui_data}")
    
    # Автоматическая отправка ответа
    await event.reply(f"Echo: {alt_message}")

@notice.on_notice()
async def handle_yunhu_user_notice(event):
    """Обработка уведомлений пользователя yunhu"""
    if event.get("platform") != "yunhu_user":
        return
    
    detail_type = event.get("detail_type", "")
    
    if detail_type == "message_edit":
        message_id = event.get("message_id", "")
        user_nickname = event.get("user_nickname", "")
        edit_time = event.get("edit_time", 0)
        print(f"Пользователь {user_nickname} изменил сообщение {message_id}")
    
    elif detail_type == "yunhu_user_file_send":
        file_data = event.get("yunhu_user_file_send", {})
        print(f"Получено сообщение супер-файла-раздачи: {file_data}")
    
    elif detail_type == "yunhu_user_bot_board":
        board_data = event.get("yunhu_user_bot_board", {})
        bot_name = event.get("bot_name", "")
        print(f"Бот {bot_name} опубликовал объявление: {board_data.get('content', '')}")

Описание расширенных полей

Типы уникальных сегментов сообщений

Сегмент сообщения формы (yunhu_user_form)

Когда content_type равен 5, тип сегмента сообщения — yunhu_user_form:

{
    "type": "yunhu_user_form",
    "data": {
        "form": "Данные формы"
    }
}

Сегмент сообщения статьи (yunhu_user_post)

Когда content_type равен 6, тип сегмента сообщения — yunhu_user_post:

{
    "type": "yunhu_user_post",
    "data": {
        "post_id": "Идентификатор статьи",
        "post_title": "Заголовок статьи",
        "post_content": "Содержание статьи"
    }
}
Поле Тип Описание
post_id string Уникальный идентификатор статьи
post_title string Заголовок статьи
post_content string Содержание статьи

Сегмент сообщения стикера (yunhu_user_sticker)

Когда content_type равен 7, тип сегмента сообщения — yunhu_user_sticker:

{
    "type": "yunhu_user_sticker",
    "data": {
        "file_id": "URL изображения стикера"
    }
}
Поле Тип Описание
file_id string URL изображения стикера

Сегмент сообщения кнопки (yunhu_user_button)

При наличии кнопок в сообщении добавляется сегмент yunhu_user_button:

{
    "type": "yunhu_user_button",
    "data": {
        "buttons": [[{"text": "Текст кнопки", "actionType": 3, "value": "Значение"}]]
    }
}

Сегмент сообщения A2UI (a2ui)

Когда content_type равен 14, тип сегмента сообщения — a2ui:

{
    "type": "a2ui",
    "data": {
        "a2ui": "JSON-данные A2UI"
    }
}

Многоаккаунтная конфигурация

Описание конфигурации

YunhuUserAdapter поддерживает одновременную настройку и работу нескольких пользовательских аккаунтов.

# config.toml
[YunhuUserAdapter]
ws_reconnect_interval = 30  # Интервал переподключения WebSocket (секунды)
ws_timeout = 70             # Время ожидания WebSocket (секунды)

[YunhuUserAdapter.accounts.default]
email = "[email protected]"  # Электронная почта пользователя (обязательно)
password = "password1"       # Пароль пользователя (обязательно)
platform = "windows"         # Идентификатор платформы (опционально, по умолчанию windows)
device_id = ""               # Идентификатор устройства (опционально, генерируется автоматически)
enabled = true               # Включен ли аккаунт (опционально, по умолчанию true)

[YunhuUserAdapter.accounts.account2]
email = "[email protected]"
password = "password2"
platform = "android"
device_id = "fixed_device_id_2"
enabled = true

Описание параметров:

Конфигурация уровня адаптера:

Важное уведомление:

  1. Адаптер использует электронную почту для входа и получения токена, после чего получает события через WebSocket
  2. При разрыве соединения WebSocket будет автоматически переподключаться, максимум 3 попытки
  3. Рекомендуется назначать каждому аккаунту фиксированный device_id для поддержания консистентности сессии
  4. Аккаунты с неизменёнными шаблонными данными (стандартные почта и пароль) будут автоматически пропущены

Использование Send DSL для указания аккаунта

Можно использовать метод Using() для указания аккаунта, через который будут отправлены сообщения. Этот метод поддерживает два типа параметров:

from ErisPulse.Core import adapter
yunhu_user = adapter.get("yunhu_user")

# Использование имени аккаунта для отправки сообщения
await yunhu_user.Send.Using("default").To("user", "user123").Text("Hello from account1!")

# Использование user_id для отправки сообщения (автоматически подбирает соответствующий аккаунт)
await yunhu_user.Send.Using("user_id_here").To("group", "group456").Text("Hello from user!")

# Без указания аккаунта используется первый включённый аккаунт
await yunhu_user.Send.To("user", "user123").Text("Hello from default account!")

Подсказка: При использовании user_id система автоматически находит соответствующий аккаунт из конфигурации. Это особенно полезно при обработке ответов на события, где можно использовать event["self"]["user_id"] для ответа от того же аккаунта.

Идентификатор аккаунта в событиях

Получаемые события автоматически содержат информацию об идентификаторе пользователя:

from ErisPulse.Core.Event import message

@message.on_message()
async def handle_message(event):
    if event["platform"] == "yunhu_user":
        # Получение идентификатора текущего пользователя
        my_user_id = event["self"]["user_id"]
        print(f"Сообщение получено от аккаунта: {my_user_id}")
        
        # Ответ от того же аккаунта
        yunhu_user = adapter.get("yunhu_user")
        await yunhu_user.Send.Using(my_user_id).To(
            event["detail_type"],
            event["user_id"] if event["detail_type"] == "private" else event["group_id"]
        ).Text("Ответ на сообщение")

Информация в журнале

Адаптер автоматически включает информацию об аккаунте в журнал, что облегчает отладку и отслеживание:

[INFO] Аккаунт default ([email protected]) успешно вошёл, идентификатор пользователя: 12345678
[INFO] Аккаунт default WebSocket задача прослушивания запущена
[INFO] Аккаунт account2 ([email protected]) успешно вошёл, идентификатор пользователя: 87654321

Интерфейс управления

# Получение информации обо всех аккаунтах
accounts = yunhu_user.accounts
# Формат ответа: {"default": {"name": "default", "email": "...", "token": "...", "user_id": "...", ...}, ...}

# Проверка, включен ли аккаунт
for account_name, account_config in yunhu_user._account_configs.items():
    print(f"{account_name}: enabled={account_config.enabled}")

# Получение HTTP-клиента по имени аккаунта
http_client = yunhu_user._get_http_client("default")

# Поиск аккаунта по user_id
account_name = yunhu_user._get_account_by_user_id("12345678")

API вызовы

Адаптер предоставляет метод call_api, который поддерживает прямой вызов API платформы:

# Отправка сообщения
result = await yunhu_user.call_api("/send", 
    target_type="group", 
    target_id="group_id",
    account_id="default",
    message={"text": "Привет", "msg_type": 1}
)

# Редактирование сообщения
result = await yunhu_user.call_api("/edit",
    target_type="group",
    target_id="group_id",
    msg_id="msg_id",
    text="Новое содержимое",
    content_type="text"
)

# Отмена сообщения
result = await yunhu_user.call_api("/recall",
    target_type="group",
    target_id="group_id",
    msg_id="msg_id"
)

# Пакетная отмена сообщений
result = await yunhu_user.call_api("/recall_batch",
    target_type="group",
    target_id="group_id",
    msg_id_list=["msg_id_1", "msg_id_2"]
)

# Получение списка сообщений
result = await yunhu_user.call_api("/list",
    chat_id="group_id",
    chat_type=2,
    msg_count=10,
    msg_id=""
)

# Получение истории редактирования сообщений
result = await yunhu_user.call_api("/list_edit_record",
    msg_id="msg_id",
    size=10,
    page=1
)

# Отчет о событии кнопки
result = await yunhu_user.call_api("/button_report",
    chat_id="group_id",
    chat_type=2,
    msg_id="msg_id",
    user_id="user_id",
    button_value="button_value"
)

Поддерживаемые API эндпоинты:

Эндпоинт Описание
/send Отправка сообщения
/edit Редактирование сообщения
/recall Отмена сообщения
/recall_batch Пакетная отмена сообщений
/list Получение списка сообщений
/list_by_seq Получение сообщений по последовательности
/list_by_mid_seq Получение сообщений по ID сообщения и последовательности
/list_edit_record Получение истории редактирования сообщений
/button_report Отчет о событии кнопки