Metadata-Version: 2.5
Name: s-socialkit
Version: 0.0.1
Summary: Общий слой соцсетей: контракт видов (кто умеет publish/content/media/comments/feed/metrics/search/profile/session/export), сущности домена (материал, комментарий, показатели, цель публикации) и живость входа. То, что одинаково у Telegram, VK, Instagram, TikTok, YouTube, Rutube, Дзена и остальных, — в одном месте, а разговор с сервисом остаётся за навыком.
Author: Dmitry
License: MIT
Keywords: capabilities,comments,content,metrics,publishing,social
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.11
Requires-Dist: pydantic>=2.7
Requires-Dist: s-corekit>=0.0.4
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.8; extra == 'dev'
Description-Content-Type: text/markdown

# socialkit (`s-socialkit`)

> Общий слой домена соцсетей — то, что одинаково у Telegram, VK, Instagram,
> TikTok, Threads, YouTube, Rutube, Дзена, vc.ru, ok.ru, Boosty, Reddit,
> Pinterest и MAX. Аналог `aichatkit` для ИИ-чатов.

## Зачем

Соцсети работают так же, как ИИ-чаты: **навык объявляет способности видами, а
оркестратор зовёт вид, а не сервис**. Тогда веер («найти конкурентов во всех
соцсетях») получается сам собой — спросили всех, кто объявил вид, — а новая
соцсеть подключается установкой пакета, без правки ядра.

До этого единицей подключения была ВСЯ СЕТЬ: маршрут веера лежал таблицей
`CROSSPOST_ROUTES`, перечень сетей — закрытым `NetworkId` на шестнадцать
значений, а способность выяснялась двумя десятками булевых флагов уже ПОСЛЕ
загрузки адаптера.

## Состав 0.0.1

| Модуль | Что даёт |
|---|---|
| `capabilities` | контракт видов: перечень, таблица вид→метод, правило имени точки входа `<сервис>_<вид>`, поля ответа, машинная проверка однородности вызова |
| `entities` | сущности домена: материал, комментарий, показатели, цель публикации, автор, файл, страницы выборок. Приехали из ядра `bublictr` |
| `liveness` | живость входа — ТОНКИЙ реэкспорт `corekit.diagnosis.access` (три исхода, правило живёт в основании) |

### Виды

**Ядро (веерится):** `publish` · `content` · `media` · `comments` · `feed` ·
`metrics` · `search` · `profile` · `session` · `export`.

**Второй эшелон (объявлен, волну не блокирует):** `engagement` · `schedule` ·
`members` · `messages` · `collection` · `events`.

Порог объявления — повторяемость намерения (умеют трое и больше), а не похожесть
кода. Уникальное (`market` ВКонтакте, `star revenue` Телеграма, протокол MAX)
остаётся своей командой навыка: вид с одним носителем — это переименованный
сервис.

### Правила контракта

- вид и метод зовутся ОДНИМ словом — помнить соответствие не приходится;
- имя сервиса живёт ТОЛЬКО в координате точки входа `<сервис>_<вид>`;
- **вызов однороден: `ctx` есть у любого вида и везде со значением по
  умолчанию.** У чатов это разъехалось, и наивный вызов падал `TypeError` на
  первом же сервисе. Проверяется машиной: `socialkit.uniformity_problems(навык)`;
- сырой ответ сервиса всегда лежит в `raw`;
- «не знаю» говорится прямо: `None`, а не ноль и не выдуманный вердикт.

## Чего в ките нет и не будет

Транспорта (`netkit`), браузера, минта и хранилища сессий (`librarykit`), пула
аккаунтов (`accountpoolkit`), троттлинга и реестра адресов (`adapterkit`), веера
(это оркестратор). Кит про ЗНАНИЕ домена, а не второй фреймворк.

## Установка

```sh
pip install s-socialkit
```

## Использование

```python
from socialkit import CAPABILITY_METHOD, CORE_KINDS, capability_id, uniformity_problems
from socialkit import ContentItem, ContentType, Visibility

# навык объявляет точку входа
capability_id("vk", "publish")            # → "vk_publish"

# оркестратор зовёт вид, не зная имени сервиса
метод = getattr(навык, CAPABILITY_METHOD["publish"])
метод(ContentItem(service="vk", type=ContentType.POST, visibility=Visibility.PUBLIC))

# навык проверяет себя сам: объявленное обязано быть позываемым
assert uniformity_problems(навык) == []
```

## Разработка

```sh
python -m pytest -q     # 41 тест
python -m ruff check .
```
