Содержание
Плагин для Playerok работает с аккаунтом продавца через API Lovsel: читает сделки, чаты и товары, пишет покупателям, выдаёт товар и реагирует на события площадки. Плагин не получает cookies, токен и прокси продавца — запросы к Playerok выполняет Lovsel. Возвраты денег, публикация и платное продвижение из плагина недоступны: эти действия выполняет продавец в кабинете.
Общие правила создания плагина — структура файла, страницы, формы, операции, публикация — в руководстве «Как создать плагин». Здесь — только то, что относится к Playerok.
Манифест
MANIFEST = {
"id": "studio.playerok-helper",
"name": "Помощник Playerok",
"version": "1.0.0",
"author": "Studio",
"description": "Пишет покупателям Playerok после оплаты и подтверждения.",
"permissions": ["orders.read", "chats.read", "chats.write", "storage"],
"marketplaces": ["playerok"], # ["funpay", "playerok"] — плагин для нескольких площадок
}- Плагин с
["playerok"]не запускается, пока у пользователя не подключён Playerok, и включается сам после подключения. - Старые плагины GGsel и FunPay совместимыми с Playerok не становятся: площадку нужно объявить явно.
- Плагин получает события только объявленных площадок и не может обратиться к
ctx.ggselилиctx.funpay, если они не объявлены.
Разрешения
| Разрешение | Методы ctx.playerok |
|---|---|
orders.read | orders(), order(), delivery() |
chats.read | chats(), messages() |
chats.write | send_message(), deliver() |
products.read | items() |
products.write | set_item_price() |
reviews.read | reviews() |
balance.read | balance() |
Каждый метод проверяет разрешение, объявленную площадку, принадлежность объекта подключённому аккаунту и активную подписку пользователя. Без них — PermissionDenied или KeyError с понятным текстом.
API ctx.playerok
| Метод или свойство | Что возвращает | Обращается к Playerok |
|---|---|---|
ctx.playerok.connected | Подключён ли Playerok и объявлена ли площадка. | нет |
ctx.playerok.username | Ник продавца. | нет |
ctx.playerok.orders(limit=500, status="") | Продажи текущего аккаунта, новые первыми. | нет |
ctx.playerok.order(order_id, refresh=False) | Сделка; refresh=True — перечитать с Playerok. | при refresh |
ctx.playerok.chats(limit=100) | Чаты: kind — buyer, support или system. | нет |
ctx.playerok.messages(chat_id, limit=50) | Свежая переписка чата. | да |
ctx.playerok.send_message(chat_id, text) | Сообщение в чат (до 2000 символов). | да |
ctx.playerok.deliver(order_id, text, mark_sent=True) | Выдача товара сообщением в чат сделки. | да |
ctx.playerok.delivery(order_id) | Состояние выдачи по сделке или None. | нет |
ctx.playerok.items(status="") | Свои товары со статусами. | нет |
ctx.playerok.set_item_price(item_id, price) | Новая цена в рублях (целое). Остальные поля не меняются. | да |
ctx.playerok.reviews(limit=100) | Отзывы к сделкам. | нет |
ctx.playerok.balance() | Баланс аккаунта на Playerok (не Lovsel). | нет |
Поля сделки: id (строка), title, amount, currency, status (paid, sent, success, refunded, waiting), raw_status (как на Playerok: PAID, SENT, CONFIRMED…), has_problem, is_automated, item_id, buyer, buyer_id, chat_id, obtaining_fields (данные покупателя), buyer_comment, created_at, marketplace. ID сделок, чатов и товаров Playerok — строки, а не числа.
Выдача товара плагином
deliver() использует ту же операцию выдачи, что и встроенная автовыдача: одна сделка — одна выдача.
@app.on("playerok.new_order")
def on_order(ctx, event):
order = event["order"]
if order["raw_status"] != "PAID":
return
result = ctx.playerok.deliver(order["id"], "Ваш код: " + take_code(ctx))
if result["status"] == "busy":
return # сделку выдаёт встроенная автовыдача или другой плагин
if result["status"] == "unknown":
ctx.log("Playerok не ответил — Lovsel сверит чат сам, повторять не нужно", "warning")busy— сделку уже обслуживает другая выдача. Если продавец выбрал схему «Автовыдача Lovsel», плагин может выдать только сделку, к которой не подходит ни одно правило; при схеме «Плагины» встроенные правила не срабатывают.bad_state— сделка не ждёт выдачи (уже отправлена, возврат, Playerok выдал товар сам).unknown— Playerok не ответил на отправку: сообщение могло дойти. Не отправляйте товар повторно — выдача ждёт сверки и решения продавца.
События
| Событие | Когда | Данные |
|---|---|---|
playerok.new_order | Новая продажа после подключения | order |
playerok.order_status | Статус сделки изменился | order, old_status, old_raw_status |
playerok.deal_problem | Проблема открыта или решена | order, opened |
playerok.new_chat | Первое сообщение в новом чате | chat_id, buyer, buyer_id, chat_type, message, order |
playerok.new_message | Сообщение покупателя или поддержки | то же, плюс from (buyer или support) |
playerok.new_review | Новый отзыв | order, chat_id, review (id, stars, text) |
playerok.delivery | Товар по сделке отправлен | order, mechanism, status |
Во всех событиях event["marketplace"] == "playerok". Свои сообщения продавца, служебные уведомления площадки и старые события до подключения плагинам не приходят. Одно и то же событие не доставляется дважды при сверке и перезапуске, но обработчик всё равно должен быть идемпотентным: храните в ctx.storage, что уже сделано.
Единый баланс
ctx.wallet работает и для сделок Playerok: ctx.wallet.reserve(order_id, amount, marketplace="playerok"). Сделка должна существовать в Lovsel, площадка — быть объявленной в манифесте. Идемпотентность и изоляция операций — по пользователю, плагину, площадке, сделке и ключу, как для других площадок. Баланс Playerok и баланс Lovsel — разные деньги: закупки плагина оплачиваются только с баланса Lovsel. Подробнее — «Единый баланс в плагинах».
Проверка без сервера
from lovsel_sdk.testing import load_plugin
plugin = load_plugin("my_plugin.py", playerok={
"orders": [{"id": "deal-1", "title": "Ключ", "amount": 199, "status": "PAID", "buyer": "anna",
"chat_id": "chat-1", "item_id": "item-1"}],
"chats": [{"id": "chat-1", "buyer": "anna"}],
})
plugin.emit("playerok.new_order", {"order": plugin.ctx.playerok.order("deal-1")})
assert plugin.playerok_sent[0]["chat_id"] == "chat-1"Полный пример — docs/examples/playerok_greetings.py: приветствие после оплаты, благодарность после подтверждения и уведомление о плохом отзыве. Он ничего не создаёт на Playerok и не тратит деньги.