Files
claude-plugins/wordpress/skills/mcp-bit-social/references/data-model.md
T
ealmeida 70b2866edf feat(wordpress): nova skill mcp-bit-social - MCP dedicado BitSocial/BitSocial Pro
Cobre: contas sociais ligadas (+ activar/desactivar), schedules de
auto-post e Share Now, logs de publicacao, resumo de falhas por
plataforma, analytics, estado da licenca Pro. 12 tools, testado
ponta-a-ponta em producao 19-08-2026. references/data-model.md com o
schema completo wpah_bit_social_* e references/diagnostics.md com o
playbook de investigacao de falhas (inclui o caso real recorrente do
Pinterest sem imagem).
2026-08-19 05:11:24 +01:00

127 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# BitSocial — modelo de dados (confirmado em produção, 2026-08-19)
Prefixo real de tabela em descomplicar.pt: `wpah_` (WP table prefix) + `bit_social_` (`Config::VAR_PREFIX`).
Todas as tabelas usam `Schema::withPrefix(...)`, `timestamps()` standard (`created_at`/`updated_at`).
## Tabelas
### `wpah_bit_social_accounts` (4 linhas)
| Coluna | Tipo | Notas |
|---|---|---|
| `id` | bigint PK | |
| `custom_app_id` | bigint, nullable, FK → `custom_apps.id` | null quando usa a app proxy da BitApps |
| `profile_id` | string | ID do perfil/utilizador na plataforma |
| `account_id` | string | ID da conta/página na plataforma (ex.: Facebook page id) |
| `account_name` | string | |
| `details` | longtext (JSON) | **NUNCA seleccionar** — contém `access_token` OAuth em claro, `icon`, `category`, etc. |
| `platform` | string | `facebook`, `linkedin`, `pinterest`, `tumblr`, `instagram`, `twitter`, `discord`, `threads`, `tiktok`, `bluesky`, `telegram`, `googleBusinessProfile`, … |
| `account_type` | int | `Account::accountType`: `DEFAULT=1` (app proxy BitApps), `CUSTOM=2` (app própria), `AI_PLATFORM=3` |
| `status` | int (bool) | `1` activo, `0` inactivo |
### `wpah_bit_social_custom_apps` (1 linha)
| Coluna | Tipo | Notas |
|---|---|---|
| `id` | bigint PK | |
| `name` | string | |
| `platform` | string | |
| `credential` | longtext | **NUNCA seleccionar** — segredo de app cifrado (base64 de payload AES) |
| `status` | int (bool) | |
### `wpah_bit_social_schedules` (175 linhas)
Cobre **dois fluxos diferentes na mesma tabela**, distinguidos por `schedule_type`:
| Coluna | Tipo | Notas |
|---|---|---|
| `id` | bigint PK | |
| `name` | string | Ex.: `"Auto Post - Post ID: 60261"` (auto-post) |
| `config` | longtext (JSON) | Ver forma abaixo. Coluna aninhada — precisa de segundo `JSON.parse` no lado do cliente. |
| `published_post_ids` | longtext (JSON, array de ints) | Posts já publicados por este schedule |
| `repeat_schedule` | bool | |
| `schedule_type` | int | `Schedule::scheduleType`: `SCHEDULE_SHARE=1` (auto-post recorrente/agendado), `DIRECT_SHARE=2` ("Share Now") |
| `status` | int | `Schedule::status`: `INACTIVE=0`, `ACTIVE=1`, `COMPLETED=2`, `DRAFT=3`, `MISSED=4` |
| `cron_status` | int | `INACTIVE=0`, `ACTIVE=1` |
| `started_at`, `ended_at`, `last_published_at`, `next_published_at` | timestamp, nullable | |
Forma real de `config` (exemplo de um schedule de auto-post):
```json
{
"settings": { "started_at": "2026-08-11 11:50:34" },
"post_filters": { "post_type": "post", "specific_postIds": [60261] },
"accounts": { "accountIds": [1, 4, 5, 6], "groupIds": [] },
"templates": {
"facebook": { "postingType": "isFeaturedImage", "content": "{post_title}", "trimMessage": false },
"pinterest": { "postingType": "isLinkCard", "content": "{post_title}", "trimMessage": true, "isLinkCard": false },
"...": "uma entrada por plataforma, mesma forma que bit_social_templates_settings"
}
}
```
### `wpah_bit_social_logs` (1825 linhas)
Uma linha por tentativa de publicação (schedule × plataforma).
| Coluna | Tipo | Notas |
|---|---|---|
| `id` | bigint PK | |
| `schedule_id` | bigint, nullable, FK → `schedules.id` | |
| `details` | longtext (JSON) | Ver forma abaixo |
| `platform` | string | |
| `status` | int (bool) | `1` sucesso, `0` falha — confirmado em `AnalyticsController::index` (`Log::where('status', true)`) |
Forma de `details` em sucesso:
```json
{
"account_id": "164743196715367",
"account_name": "Descomplicar - Agência de Aceleração Digital",
"response": { "id": "164743196715367_122245726064096762", "post_supports_client_mutation_id": true },
"post_id": 60261,
"post_url": "https://fb.com/164743196715367_122245726064096762"
}
```
Forma de `details` em falha (o caso real mais comum, Pinterest):
```json
{
"account_id": "1051238806710440771",
"account_name": "Blog Descomplicar",
"post_id": 60261,
"response": { "status": "error", "error_msg": "Must have image for create pin in Pinterest." },
"post_url": null
}
```
O erro está sempre em `details.response.error_msg` nos casos observados; `extractErrorMessage()`
no MCP também tenta `response.message`, `error`, `message` como fallback para plataformas com
forma diferente.
### `wpah_bit_social_groups` / `wpah_bit_social_groups_accounts` (Pro, 0 linhas em produção)
`groups`: `id`, `name`, `status`. `groups_accounts`: pivot `group_id` × `account_id`, cascade on
delete. Um grupo pode substituir uma lista explícita de `accountIds` num `config.accounts.groupIds`.
## `wp_options` relevantes
| Chave | Conteúdo |
|---|---|
| `bit_social_version` / `bit_social_pro_version` | string, ex. `"1.16.0"` |
| `bit_social_db_version` / `bit_social_pro_db_version` | string |
| `bit_social_installed` / `bit_social_pro_installed` | bool |
| `bit_social_auto_post_settings` | `{isEnabled, keepLogs, taxonomies[], accounts:{accountIds[],groupIds[]}, postType[], postDelay:{every,unit}}` |
| `bit_social_templates_settings` | um objecto por plataforma, mesma forma que `config.templates` num schedule |
| `bit_social_pro_settings` | `{cron:{isExternalCronEnabled}}` |
| `bit_social_pro_license_data` | `{key, status, expireIn}` — `key` **nunca** deve ser devolvida sem máscara |
| `bit_social_secret_key` | segredo interno do plugin — nunca ler/expor |
## Análogo AnalyticsController (referência, não reimplementação 1:1)
`AnalyticsController::index` só calcula `active_account_count`, `published_post_count` (logs com
`status=true`) e `active_schedule_count`. `bs_get_analytics` estende com `failed_post_count`
(logs com `status=0`) porque o controller original omite essa contagem apesar de ser a métrica
mais accionável.