WP Manifestindependent plugin directory
manifest / social / wp-pinfeed

WP PinFeed

WordPress Plugin for Pinterest RSS Feeds

★ 0stars

Install

Download source zip No release zip yet

This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/geliorn/wp-pinfeed/archive/refs/heads/claude%2Ffunny-cray-vx2g6z.zip
No built-in updater. New versions won't appear under Dashboard → Updates. Install new releases yourself, or let Git Updater track the repository.

WP PinFeed (wp-pinfeed)

Версия 0.2.0 · WordPress-плагин, который отдаёт RSS-ленты для автопубликации в Pinterest. Ленты собираются по таксономиям, текст пина строится по шаблонам (и при желании пишется моделью), а картинка пина по умолчанию — вертикальная инфографика 2:3 в стиле llm-agent-articles: заголовок и 5 нумерованных тезисов списком или сеткой. Самодостаточен — без ACF/CPT UI, переносится на любой сайт сети копированием папки. Работает в связке с llm-agent-articles и llm-agent-github-repos, но не зависит от них.

Как Pinterest работает с RSS

Pinterest → Settings → Bulk create Pins → Auto-publish → Connect RSS feed: указывается URL ленты и одна доска. Pinterest забирает ленту примерно раз в сутки и создаёт пины из новых <item> (до 200 пинов в день на аккаунт). Из уже созданного пина он больше ничего не перечитывает — ни текст, ни картинку. Отсюда два правила плагина:

  • <guid> элемента стабилен (/?p=ID) и не зависит от шаблонов и UTM — правка ленты не превращает старые записи в «новые»;
  • элемент лучше отдавать уже с готовой картинкой (см. «Пока пин не собран»).

Два вида лент

Ленты из админки (Pinterest → Добавить ленту, тип записи pinfeed). У каждой — свой адрес https://site/pinfeed/<слаг-ленты>/ и полный набор настроек ниже. Одна лента может объединять несколько типов записей, например статьи и репозитории по MCP.

Автоленты терминов (Pinterest → Автоленты). Отмечаете таксономии — у каждого их термина появляется лента https://site/pinfeed/term/<таксономия>/<слаг-термина>/. Все автоленты настраиваются одним набором (та же форма); условие «запись в этом термине» добавляется само. Адрес автоленты виден на экране редактирования термина. Термины, где записей меньше заданного минимума, отдают 404.

Без ЧПУ работают и адреса-параметры: /?wppf_feed=<слаг>, /?wppf_tax=<таксономия>&wppf_term=<слаг>. Добавьте ?wppf_preview=1 к адресу ленты — редактор увидит HTML-сетку пинов с длиной текстов, источником картинки и статусом каждого элемента (посетителю без прав отдаётся обычный XML).

Настройки ленты

Что попадает

Поле Что делает
Типы записей Любые публичные: post, github_repo, …
Условия по таксономиям Строки «таксономия + условие + термины»: любой из (IN), ни один из (NOT IN), все сразу (AND), есть любой термин, нет терминов; флажок «с дочерними». Связь между строками — И / ИЛИ. Термины — слаги через запятую (переносимо между сайтами), числа считаются ID
Сортировка По дате, по обновлению, случайно, по числовому мета-полю (например _gh_stars), по комментариям
Записей в ленте По умолчанию 25
Не старше, дней / задержка, минут Окно по дате публикации. Задержка даёт время проставиться обложке, SEO-полям и фоновой генерации
Исключить ID, «только с картинкой» Плюс флажок «Не публиковать в Pinterest» у любой записи

Текст пина — шаблоны

Подстановка Значение
{title} Заголовок записи
{excerpt} Отрывок или первые 55 слов текста
{content:300} Текст записи до N символов
{short_description} Краткое описание репозитория (llm-agent-github-repos)
{seo_title} {seo_description} Из Yoast / Rank Math (определяется автоматически)
{pin_title} {pin_description} Ручной текст из метабокса «Pinterest» у записи
{llm_title} {llm_description} Текст от модели (см. ниже)
{terms:category:3} {term:repo_topic} Термины через запятую / первый термин
{hashtags:post_tag:5} Хэштеги из терминов: «AI агенты» → #AIАгенты. * вместо таксономии — все
{meta:ключ} Любое мета-поле
{date} {author} {post_type_label} {permalink}
{feed_title} {feed_slug} {term_name} {term_slug} Лента / термин автоленты
{site_name} {site_domain} {site_url}
{gh_stars} {gh_forks} {gh_language} {gh_license} {gh_full_name} {gh_url} Если стоит llm-agent-github-repos. {gh_stars} → «★ 15,2k»
{primary_keyword} Главный ключ статьи llm-agent-articles

{a|b|c} — первое непустое значение, {excerpt|"Читать на сайте"} — текст в кавычках как последний вариант. Неизвестная подстановка даёт пустую строку (и проваливается дальше по цепочке) — опечатка не утечёт в публичный пин.

По умолчанию заголовок — {pin_title|llm_title|seo_title|title}, описание — {pin_description|llm_description|seo_description|short_description|excerpt|content:400} плюс строка хэштегов. Пределы Pinterest (100 / 500 символов) соблюдаются обрезкой по границе слова; хвостовая строка хэштегов при обрезке сохраняется целиком.

Текст от модели (LLM)

Включается в ленте. Модель получает заголовок, описание, термины, начало текста и тему доски и возвращает JSON {title, description} — подставляется в {llm_title} и {llm_description}. Дополнительно: язык, ключевые слова доски (можно шаблоном, например {primary_keyword}), свободные требования.

  • Никогда не вызывается, пока Pinterest ждёт ленту. Тексты пишет фоновая задача; до готовности цепочка шаблона берёт следующий вариант ({seo_description}, …).
  • Ответ кэшируется в мете записи _wppf_llm с ключом по настройкам промпта и временем правки записи — правка записи или промпта сама делает его устаревшим.
  • Запись, на которой модель ошиблась, откладывается на 6 часов, чтобы не съедать бюджет.
  • Провайдеры те же, что в соседних плагинах: Yandex Foundation Models, DeepSeek, Qwen, Timeweb TWC AI, OpenRouter. Ключи свои, но в Настройки есть кнопка «Скопировать провайдера и ключи» из llm-agent-articles или llm-agent-github-repos.

Картинка пина — три уровня

Цепочка источников, порядок перетаскивается в форме ленты, берётся первый найденный:

  1. Картинка Pinterest у записи — метабокс «Pinterest». Всегда отдаётся как есть.
  2. Миниатюра записи (featured image).
  3. Картинка термина — поле «Изображение для Pinterest» у термина (список таксономий с этим полем — в настройках). Берётся самый глубокий термин записи, затем его предки; в автоленте первым проверяется сам термин ленты.
  4. Первая картинка в тексте записи.
  5. Мета-поле — ID вложения или URL (например _gh_owner_avatar у репозиториев).
  6. Картинка по умолчанию ленты.

Дальше — генерация вертикального пина через GD: никогда, если найденная картинка не вертикальная (по умолчанию; «вертикальная» = высота ≥ 1,25 ширины) или всегда. Формат собранного пина выбирается в ленте:

Инфографика (по умолчанию)

Как инфографика статей в llm-agent-articles, только вертикальная 1000×1500: акцентная полоса, заголовок ({pin_title|llm_title|title}), 3–8 тезисов (по умолчанию 5) — нумерованным списком или сеткой блоков, у тезиса короткая метка и одно предложение, внизу подпись ({site_domain}) и логотип. Фон — цвет/градиент или затемнённая картинка записи. Все тезисы набираются одним кеглем (жирным — метки, обычным начертанием — текст, если рядом со шрифтом лежит его regular-версия).

Откуда тезисы (первое, что нашлось):

  1. вручную — поле «Тезисы для инфографики» в метабоксе «Pinterest» записи (по строке, Метка: текст или просто текст);
  2. из структуры записи (если в ленте не выбрано «всегда модель»): блок «Коротко», который пишет llm-agent-articles (а также списки под заголовками «Главное», «Ключевые выводы», «Key takeaways», «Возможности»…), иначе заголовки H2 (без служебных: «Оглавление», «Частые вопросы», «Заключение»…), иначе самый длинный маркированный список; метка берётся из <strong> в начале пункта;
  3. от модели (если в ленте не выбрано «только структура») — по заголовку, описанию, пунктам из структуры и началу текста; предел длины тезиса считается из пресета. Как и всё LLM — только в фоновой задаче, с кэшем в мете _wppf_theses; для записи, где текста меньше 300 символов, модель не вызывается (ей пришлось бы выдумывать).

Текст не обрезается никогда. Тезис, который не влезает в свой блок, фоновая задача просит модель переписать короче под измеренный бюджет символов; что всё равно не влезло — убирается при сборке целым пунктом (самый длинный первым), но не меньше трёх. Если тезисов меньше трёх — вместо инфографики собирается обложка.

Пока модель не ответила, элемент ведёт себя как несобранный пин (см. «Пока пин не собран»).

Обложка

Найденная картинка становится фоном, сверху — текст ({pin_title|title} по умолчанию) и подпись внизу. Если не нашлось ничего, можно собрать текстовую обложку на фоне пресета. Используется, когда в ленте выбран формат «Обложка», и как запасной вариант инфографики.

Пресеты (Pinterest → Пресеты картинок, две вкладки) — с живым предпросмотром на реальной записи (её тезисы или пример):

  • Инфографика: размер, поля, фон (цвет / затемнённая картинка записи), градиент, акцентная полоса, заголовок (кегль с автоподбором, строки, выравнивание), раскладка список/сетка и число колонок, плашки пунктов (цвет, прозрачность, скругление, обводка), маркер (номер в круге / квадрате / без подложки / точка / без маркера), метка, кегль текста и его минимум, подпись, логотип. Стартовые: «Тёмный список», «Сетка 2 колонки», «Светлый список».
  • Обложка: компоновка картинка сверху / текст на плашке снизу или текст поверх картинки, обрезка по фокусу, фильтры, тонирование, градиент, акцентная полоса, текст с автоподбором кегля, тень, подложка, подпись, логотип, рамка.

Экспорт/импорт JSON для переноса между сайтами — на каждой вкладке.

Собранные пины — обычные файлы в uploads/wppf-pins/<ID записи>/, не вложения медиатеки. Имя файла содержит хэш всего, что влияет на картинку (формат, пресет, заголовок, тезисы, подпись, исходник), поэтому изменения подхватываются сами, а неизменённый пин сохраняет стабильный URL. Старые версии удаляются при сборке новой и при удалении записи.

Пока пин не собран. При запросе ленты синхронно собирается не больше N пинов (настройка, по умолчанию 3) и ничего не скачивается из сети; остальное доделывает фоновая задача. До этого элемент либо отдаётся с исходной картинкой, либо (надёжнее) не включается в ленту, пока пин не готов — выбирается в ленте.

Шрифт. GD нужен TTF/OTF: шрифт пресета → путь из настроек → загруженные (uploads/wppf-fonts/, а также uploads/laa-fonts/ от llm-agent-articles) → системные (DejaVu, Noto, Liberation).

Ссылка

UTM-метки (utm_source=pinterest, utm_medium=social, utm_campaign={feed_slug}) — с подстановками, отключаются флажком.

Готовые профили

В форме ленты (и автолент) — «Быстрый старт», появляется, если на сайте есть соответствующий плагин:

  • Статьи блога (llm-agent-articles) — post, SEO-описание → отрывок, хэштеги из меток; инфографика «Тёмный список» с тезисами из блока «Коротко» (модель — только если его нет), задержка 30 минут (статья публикуется раньше, чем к ней прикрепляется обложка).
  • GitHub-репозитории (llm-agent-github-repos) — github_repo, short_description, строка «★ звёзды · язык», хэштеги из repo_topic и меток; инфографика «Сетка 2 колонки», тезисы всегда от модели по README (заголовки README вроде «Installation» тезисами не годятся), в подписи — звёзды и домен; без ключей LLM — обложка из картинки термина repo_topic или аватара владельца.

Профили расширяются фильтром wppf_profiles.

Фоновая задача

Как в соседних плагинах — три равноправных триггера одного тика:

  1. WP-Cron раз в 10 минут (по умолчанию);
  2. HTTP-эндпоинт за секретом: curl "https://site/?pinfeed_cron=СЕКРЕТ" (троттлинг раз в минуту);
  3. прямой PHP CLI: php wp-content/plugins/wp-pinfeed/cron.php.

Готовые строки для crontab — в настройках. Тик проходит по всем включённым лентам и по автолентам, которые Pinterest забирал за последние 14 дней (терминов на сайте могут быть тысячи — греются только реально подключённые), просит у модели тезисы и тексты и собирает пины в пределах бюджетов «запросов к модели за тик» и «пинов за тик».

Кэш

XML ленты кэшируется (по умолчанию 30 минут). Сохранение любой записи или смена терминов сбрасывает кэш всех лент; лента, в которой ещё есть несобранные пины, не кэшируется вовсе — следующий запрос получит готовые.

WP-CLI

wp pinfeed list
wp pinfeed warm                         # тик сейчас
wp pinfeed preview <ID> [--render]      # что отдаст лента
wp pinfeed preview post_tag:mcp         # автолента термина
wp pinfeed xml <ID> > feed.xml
wp pinfeed import-llm --from=articles   # или github_repos
wp pinfeed flush-cache

Хуки

Хук Назначение
wppf_query_args (filter) Последнее слово о WP_Query ленты
wppf_placeholder (filter) Свои подстановки: вернуть строку для своего имени
wppf_image_sources / wppf_image_source (filter) Свой источник картинки: зарегистрировать / вернуть
wppf_pin (filter) Последнее слово об одном пине (текст, ссылка, картинка, статус)
wppf_profiles (filter) Свои профили быстрого старта
wppf_metabox_post_types (filter) Типы записей с метабоксом «Pinterest»

Данные плагина

  • CPT pinfeed — ленты (непубличный), мета _wppf_*.
  • Опции wppf_settings, wppf_auto_feed, wppf_image_presets, wppf_infographic_presets, wppf_log, wppf_cache_ver, wppf_last_tick, wppf_rewrite_ver.
  • Мета записей: _wppf_image_id, _wppf_pin_title, _wppf_pin_description, _wppf_theses_manual, _wppf_exclude, _wppf_llm, _wppf_theses. Мета терминов: wppf_image_id, wppf_last_fetch_at.
  • Файлы: uploads/wppf-pins/, uploads/wppf-fonts/, журнал uploads/wppf-pinfeed.log.

Удаление плагина стирает всё перечисленное. Пины, уже созданные в Pinterest, не затрагиваются — Pinterest хранит свою копию картинки.

Требования

  • WordPress 6.0+, PHP 7.4+ (проверено на 8.3).
  • GD с FreeType — для генерации пинов (без него ленты отдают исходные картинки).
  • Ключи одной из моделей — только если нужен текст или тезисы от LLM (для статей llm-agent-articles тезисы берутся из блока «Коротко» и без модели).

Безопасность

Нонсы на всех формах и AJAX, manage_options на настройках, пресетах и автолентах, edit_post на ленте и метабоксах. HTML-предпросмотр ленты — только для edit_posts. HTTP-триггер — по секрету (hash_equals) с троттлингом. Загружаемый шрифт проверяется по сигнатуре файла. Ответ модели и все тексты проходят очистку от HTML; в XML запрещённые управляющие символы вырезаются, чтобы случайный символ из README не ломал всю ленту.