Концепции, ценность и типичные сценарии клонирования — меньше кода.
Концепции, ценность и типичные сценарии клонирования — меньше кода.
Preparing Ring content
Preparing Ring content
Preparing Ring content
Используйте вкладки Основатель / Разработчик на боковой панели документации, чтобы отфильтровать эту страницу. Основатели видят бизнес-процесс и настройки для оператора. Разработчики видят сервисы, маршруты, переменные окружения и локальный тестовый прогон.
News Kingdom является слоем продвижения поверх модуля новостей Ring. Участники с ролью member или выше пишут статьи, которые размещаются в их личном пространстве по адресу /{username}/{slug}. После этого автор может попросить место в главной ленте /news. Ring оценивает статью, предлагает автору оплатить цену, которая зависит от оценки, и отправляет статью администраторам платформы в Telegram для окончательного решения «да» или «нет».
Каждая заявка на продвижение проходит через одно поле статьи, mainPageStatus:
| Этап | Что происходит | mainPageStatus |
|---|---|---|
| Подача | Автор просит разместить статью на главной странице | submitted |
| Оценка | AI или эвристика оценивает этичность, спам, дубликаты и ценность | ai_scored |
| Жёсткая блокировка | Этичность слишком низкая, риск спама или дубликата слишком высокий | published_blog_only |
| Оплата | Цена назначена, открывается checkout PaymentConductor | payment_pending |
| Оплачено | Webhook подтверждает оплату, администраторы получают карточку в Telegram | awaiting_admin_approval |
| Одобрено | Статья появляется в главной ленте для всего сайта | published_main |
| Отклонено | Администратор отказывает. Статья остаётся в блоге автора | rejected |
Тот же процесс: где статья живёт до и после запроса на продвижение.
Предпосылка: модуль новостей, редактор и главная лента, куда News Kingdom продвигает статьи.
Зависимость: как маршрутизируются checkout news_promotion и его webhooks.
См. также: бот администратора с кнопками Approve, Reject и Counter.
Используйте вкладки Основатель / Разработчик на боковой панели документации, чтобы отфильтровать эту страницу. Основатели видят бизнес-процесс и настройки для оператора. Разработчики видят сервисы, маршруты, переменные окружения и локальный тестовый прогон.
News Kingdom является слоем продвижения поверх модуля новостей Ring. Участники с ролью member или выше пишут статьи, которые размещаются в их личном пространстве по адресу /{username}/{slug}. После этого автор может попросить место в главной ленте /news. Ring оценивает статью, предлагает автору оплатить цену, которая зависит от оценки, и отправляет статью администраторам платформы в Telegram для окончательного решения «да» или «нет».
Каждая заявка на продвижение проходит через одно поле статьи, mainPageStatus:
| Этап | Что происходит | mainPageStatus |
|---|---|---|
| Подача | Автор просит разместить статью на главной странице | submitted |
| Оценка | AI или эвристика оценивает этичность, спам, дубликаты и ценность | ai_scored |
| Жёсткая блокировка | Этичность слишком низкая, риск спама или дубликата слишком высокий | published_blog_only |
| Оплата | Цена назначена, открывается checkout PaymentConductor | payment_pending |
| Оплачено | Webhook подтверждает оплату, администраторы получают карточку в Telegram | awaiting_admin_approval |
| Одобрено | Статья появляется в главной ленте для всего сайта | published_main |
| Отклонено | Администратор отказывает. Статья остаётся в блоге автора | rejected |
Тот же процесс: где статья живёт до и после запроса на продвижение.
Предпосылка: модуль новостей, редактор и главная лента, куда News Kingdom продвигает статьи.
Зависимость: как маршрутизируются checkout news_promotion и его webhooks.
См. также: бот администратора с кнопками Approve, Reject и Counter.
Используйте вкладки Основатель / Разработчик на боковой панели документации, чтобы отфильтровать эту страницу. Основатели видят бизнес-процесс и настройки для оператора. Разработчики видят сервисы, маршруты, переменные окружения и локальный тестовый прогон.
News Kingdom является слоем продвижения поверх модуля новостей Ring. Участники с ролью member или выше пишут статьи, которые размещаются в их личном пространстве по адресу /{username}/{slug}. После этого автор может попросить место в главной ленте /news. Ring оценивает статью, предлагает автору оплатить цену, которая зависит от оценки, и отправляет статью администраторам платформы в Telegram для окончательного решения «да» или «нет».
Каждая заявка на продвижение проходит через одно поле статьи, mainPageStatus:
| Этап | Что происходит | mainPageStatus |
|---|---|---|
| Подача | Автор просит разместить статью на главной странице | submitted |
| Оценка | AI или эвристика оценивает этичность, спам, дубликаты и ценность | ai_scored |
| Жёсткая блокировка | Этичность слишком низкая, риск спама или дубликата слишком высокий | published_blog_only |
| Оплата | Цена назначена, открывается checkout PaymentConductor | payment_pending |
| Оплачено | Webhook подтверждает оплату, администраторы получают карточку в Telegram | awaiting_admin_approval |
| Одобрено | Статья появляется в главной ленте для всего сайта | published_main |
| Отклонено | Администратор отказывает. Статья остаётся в блоге автора | rejected |
Тот же процесс: где статья живёт до и после запроса на продвижение.
Предпосылка: модуль новостей, редактор и главная лента, куда News Kingdom продвигает статьи.
Зависимость: как маршрутизируются checkout news_promotion и его webhooks.
См. также: бот администратора с кнопками Approve, Reject и Counter.
Checkout, который взимает плату за продвижение через настроенный вами платёжный процессор.
Вы задаёте цены в гривнах через переменные окружения сервера. Если они не заданы, действуют такие значения по умолчанию:
| Параметр | По умолчанию | Эффект |
|---|---|---|
| Базовая цена | 50 UAH | Минимальная цена для статьи с высокой ценностью |
| Масштаб | 2000 UAH | Насколько растёт цена при снижении ценности |
| Максимум | 5000 UAH | Верхний предел цены |
| Порог низкой ценности | ценность ниже 0.25 | Цена поднимается минимум до 4999 UAH |
| Встречное предложение администратора | +25% | Кнопка Counter в Telegram задаёт новую сумму, которую должен оплатить автор |
lib/telegram/admin-bot/news-callback-handler.tsapp/api/telegram/admin-bot/webhook/route.ts| Интерфейс продвижения для участника | features/news/components/news-promotion-panel.tsx на /my-news |
| Типы статусов и полей | features/news/types/index.ts (MainPageStatus, NewsContentType, NewsVisibility) |
| Маппер строк JSONB | lib/news/map-news-document.ts |
| Бренд и абсолютные URL | lib/site-branding.ts (localeBlogArticleUrl, absoluteSiteUrl) |
| Метод и путь | Аутентификация | Назначение |
|---|---|---|
POST /api/news/promotion/submit | Сессия, только автор статьи | Отмечает promoteToMainPage, оценивает, открывает checkout |
PATCH /api/news/promotion/submit | Заголовок x-news-promotion-secret | Dev или тест: отметить как оплаченное и уведомить администраторов |
POST /api/payments/{wayforpay,stripe,paypal}/webhook | Подпись процессора | Каноническое подтверждение оплаты |
POST /api/news/promotion/wayforpay-webhook | Payload процессора | Устаревший делегат к каноническому webhook WayForPay |
POST /api/mcp/v1/news/[id]/{score,approve,reject,publish} | Сервисный токен (withMcpGuard) | Операции агентов и MCP над тем же процессом |
scoreNewsForMainPage() вызывает OpenRouter, когда задан OPENROUTER_API_KEY. Без ключа сохраняются эвристические значения по умолчанию (ethics 0.7, spam 0.2, merit 0.5) и записывается model: 'heuristic'.
slug или siteWideSlug. 0.9, если у опубликованной статьи (среди первых 200) такой же заголовок.ethics < NEWS_ETHICS_MIN или spamRisk > NEWS_SPAM_MAX или duplicateRisk > NEWS_DUPLICATE_MAX. Результат: published_blog_only и никакого checkout.clamp(base, max, base + (1 - merit) * scale). Ценность ниже NEWS_MERIT_SOFT_REJECT поднимает цену минимум до 4999. Низкая ценность не меняет статус.Ни одного из ключей NEWS_* нет в env.local.template. Код читает их с такими значениями по умолчанию.
| Переменная | По умолчанию | Где читается |
|---|---|---|
NEWS_PROMO_BASE_UAH / NEWS_PROMO_SCALE_UAH / NEWS_PROMO_MAX_UAH | 50 / 2000 / 5000 | news-scoring-service.ts |
NEWS_ETHICS_MIN / NEWS_SPAM_MAX / NEWS_DUPLICATE_MAX | 0.35 / 0.85 / 0.9 | news-scoring-service.ts |
NEWS_MERIT_SOFT_REJECT | 0.25 | оценка и процесс продвижения |
OPENROUTER_API_KEY, OPENROUTER_MODEL_PRIMARY, OPENROUTER_MODEL_FALLBACK | не задано | news-scoring-service.ts |
PAYMENT_NEWS_PROCESSOR | запасной вариант PAYMENT_DEFAULT_PROCESSOR, затем wayforpay | lib/payments/payment.config.ts |
NEWS_PROMOTION_WEBHOOK_SECRET | не задано | PATCH /api/news/promotion/submit |
ADMIN_BOT_TOKEN | не задано | Ответы на callback в Telegram |
Все четыре таблицы используют документную модель JSONB (id, data jsonb, временные метки) в data/schema.sql (сплющенная v4.1.0): news, news_categories, news_likes, news_submission_audit. Каждый переход дописывает запись в data.mainPageStatusHistory и создаёт одну строку news_submission_audit. Файлы data/migrations/002_news_content_schema.sql и 003_news_kingdom_upgrade.sql носят исторический характер. Новые установки применяют только schema.sql.
approveMainPagePublication() устанавливает status: 'published' и visibility: 'site-wide'. Для материалов, написанных пользователями, затем в очередь ставится enqueueRewardCreditAddEvent({ trigger: 'newsStoryApproved' }) и запускается generateArticleTranslations(). Получатели в Telegram: пользователи с ролью администратора платформы и заполненным communication.telegramId.
Примените схему и создайте статью участника
Примените data/schema.sql и войдите как пользователь с ролью member или выше. Создайте статью на /news/create. Она получает blogUsername и после публикации появляется по адресу /{username}/{slug}.
Подайте статью на продвижение
Ответ содержит status, aiScore и либо перенаправление, либо платёжные поля для checkout.
Сымитируйте оплату в dev
Одобрите
Нажмите Approve на карточке в Telegram или вызовите POST /api/mcp/v1/news/<id>/approve с сервисным токеном. Проверьте, что mainPageStatus имеет значение published_main и что существует строка news_submission_audit.
Checkout, который взимает плату за продвижение через настроенный вами платёжный процессор.
Вы задаёте цены в гривнах через переменные окружения сервера. Если они не заданы, действуют такие значения по умолчанию:
| Параметр | По умолчанию | Эффект |
|---|---|---|
| Базовая цена | 50 UAH | Минимальная цена для статьи с высокой ценностью |
| Масштаб | 2000 UAH | Насколько растёт цена при снижении ценности |
| Максимум | 5000 UAH | Верхний предел цены |
| Порог низкой ценности | ценность ниже 0.25 | Цена поднимается минимум до 4999 UAH |
| Встречное предложение администратора | +25% | Кнопка Counter в Telegram задаёт новую сумму, которую должен оплатить автор |
lib/telegram/admin-bot/news-callback-handler.tsapp/api/telegram/admin-bot/webhook/route.ts| Интерфейс продвижения для участника | features/news/components/news-promotion-panel.tsx на /my-news |
| Типы статусов и полей | features/news/types/index.ts (MainPageStatus, NewsContentType, NewsVisibility) |
| Маппер строк JSONB | lib/news/map-news-document.ts |
| Бренд и абсолютные URL | lib/site-branding.ts (localeBlogArticleUrl, absoluteSiteUrl) |
| Метод и путь | Аутентификация | Назначение |
|---|---|---|
POST /api/news/promotion/submit | Сессия, только автор статьи | Отмечает promoteToMainPage, оценивает, открывает checkout |
PATCH /api/news/promotion/submit | Заголовок x-news-promotion-secret | Dev или тест: отметить как оплаченное и уведомить администраторов |
POST /api/payments/{wayforpay,stripe,paypal}/webhook | Подпись процессора | Каноническое подтверждение оплаты |
POST /api/news/promotion/wayforpay-webhook | Payload процессора | Устаревший делегат к каноническому webhook WayForPay |
POST /api/mcp/v1/news/[id]/{score,approve,reject,publish} | Сервисный токен (withMcpGuard) | Операции агентов и MCP над тем же процессом |
scoreNewsForMainPage() вызывает OpenRouter, когда задан OPENROUTER_API_KEY. Без ключа сохраняются эвристические значения по умолчанию (ethics 0.7, spam 0.2, merit 0.5) и записывается model: 'heuristic'.
slug или siteWideSlug. 0.9, если у опубликованной статьи (среди первых 200) такой же заголовок.ethics < NEWS_ETHICS_MIN или spamRisk > NEWS_SPAM_MAX или duplicateRisk > NEWS_DUPLICATE_MAX. Результат: published_blog_only и никакого checkout.clamp(base, max, base + (1 - merit) * scale). Ценность ниже NEWS_MERIT_SOFT_REJECT поднимает цену минимум до 4999. Низкая ценность не меняет статус.Ни одного из ключей NEWS_* нет в env.local.template. Код читает их с такими значениями по умолчанию.
| Переменная | По умолчанию | Где читается |
|---|---|---|
NEWS_PROMO_BASE_UAH / NEWS_PROMO_SCALE_UAH / NEWS_PROMO_MAX_UAH | 50 / 2000 / 5000 | news-scoring-service.ts |
NEWS_ETHICS_MIN / NEWS_SPAM_MAX / NEWS_DUPLICATE_MAX | 0.35 / 0.85 / 0.9 | news-scoring-service.ts |
NEWS_MERIT_SOFT_REJECT | 0.25 | оценка и процесс продвижения |
OPENROUTER_API_KEY, OPENROUTER_MODEL_PRIMARY, OPENROUTER_MODEL_FALLBACK | не задано | news-scoring-service.ts |
PAYMENT_NEWS_PROCESSOR | запасной вариант PAYMENT_DEFAULT_PROCESSOR, затем wayforpay | lib/payments/payment.config.ts |
NEWS_PROMOTION_WEBHOOK_SECRET | не задано | PATCH /api/news/promotion/submit |
ADMIN_BOT_TOKEN | не задано | Ответы на callback в Telegram |
Все четыре таблицы используют документную модель JSONB (id, data jsonb, временные метки) в data/schema.sql (сплющенная v4.1.0): news, news_categories, news_likes, news_submission_audit. Каждый переход дописывает запись в data.mainPageStatusHistory и создаёт одну строку news_submission_audit. Файлы data/migrations/002_news_content_schema.sql и 003_news_kingdom_upgrade.sql носят исторический характер. Новые установки применяют только schema.sql.
approveMainPagePublication() устанавливает status: 'published' и visibility: 'site-wide'. Для материалов, написанных пользователями, затем в очередь ставится enqueueRewardCreditAddEvent({ trigger: 'newsStoryApproved' }) и запускается generateArticleTranslations(). Получатели в Telegram: пользователи с ролью администратора платформы и заполненным communication.telegramId.
Примените схему и создайте статью участника
Примените data/schema.sql и войдите как пользователь с ролью member или выше. Создайте статью на /news/create. Она получает blogUsername и после публикации появляется по адресу /{username}/{slug}.
Подайте статью на продвижение
Ответ содержит status, aiScore и либо перенаправление, либо платёжные поля для checkout.
Сымитируйте оплату в dev
Одобрите
Нажмите Approve на карточке в Telegram или вызовите POST /api/mcp/v1/news/<id>/approve с сервисным токеном. Проверьте, что mainPageStatus имеет значение published_main и что существует строка news_submission_audit.
Checkout, который взимает плату за продвижение через настроенный вами платёжный процессор.
Вы задаёте цены в гривнах через переменные окружения сервера. Если они не заданы, действуют такие значения по умолчанию:
| Параметр | По умолчанию | Эффект |
|---|---|---|
| Базовая цена | 50 UAH | Минимальная цена для статьи с высокой ценностью |
| Масштаб | 2000 UAH | Насколько растёт цена при снижении ценности |
| Максимум | 5000 UAH | Верхний предел цены |
| Порог низкой ценности | ценность ниже 0.25 | Цена поднимается минимум до 4999 UAH |
| Встречное предложение администратора | +25% | Кнопка Counter в Telegram задаёт новую сумму, которую должен оплатить автор |
lib/telegram/admin-bot/news-callback-handler.tsapp/api/telegram/admin-bot/webhook/route.ts| Интерфейс продвижения для участника | features/news/components/news-promotion-panel.tsx на /my-news |
| Типы статусов и полей | features/news/types/index.ts (MainPageStatus, NewsContentType, NewsVisibility) |
| Маппер строк JSONB | lib/news/map-news-document.ts |
| Бренд и абсолютные URL | lib/site-branding.ts (localeBlogArticleUrl, absoluteSiteUrl) |
| Метод и путь | Аутентификация | Назначение |
|---|---|---|
POST /api/news/promotion/submit | Сессия, только автор статьи | Отмечает promoteToMainPage, оценивает, открывает checkout |
PATCH /api/news/promotion/submit | Заголовок x-news-promotion-secret | Dev или тест: отметить как оплаченное и уведомить администраторов |
POST /api/payments/{wayforpay,stripe,paypal}/webhook | Подпись процессора | Каноническое подтверждение оплаты |
POST /api/news/promotion/wayforpay-webhook | Payload процессора | Устаревший делегат к каноническому webhook WayForPay |
POST /api/mcp/v1/news/[id]/{score,approve,reject,publish} | Сервисный токен (withMcpGuard) | Операции агентов и MCP над тем же процессом |
scoreNewsForMainPage() вызывает OpenRouter, когда задан OPENROUTER_API_KEY. Без ключа сохраняются эвристические значения по умолчанию (ethics 0.7, spam 0.2, merit 0.5) и записывается model: 'heuristic'.
slug или siteWideSlug. 0.9, если у опубликованной статьи (среди первых 200) такой же заголовок.ethics < NEWS_ETHICS_MIN или spamRisk > NEWS_SPAM_MAX или duplicateRisk > NEWS_DUPLICATE_MAX. Результат: published_blog_only и никакого checkout.clamp(base, max, base + (1 - merit) * scale). Ценность ниже NEWS_MERIT_SOFT_REJECT поднимает цену минимум до 4999. Низкая ценность не меняет статус.Ни одного из ключей NEWS_* нет в env.local.template. Код читает их с такими значениями по умолчанию.
| Переменная | По умолчанию | Где читается |
|---|---|---|
NEWS_PROMO_BASE_UAH / NEWS_PROMO_SCALE_UAH / NEWS_PROMO_MAX_UAH | 50 / 2000 / 5000 | news-scoring-service.ts |
NEWS_ETHICS_MIN / NEWS_SPAM_MAX / NEWS_DUPLICATE_MAX | 0.35 / 0.85 / 0.9 | news-scoring-service.ts |
NEWS_MERIT_SOFT_REJECT | 0.25 | оценка и процесс продвижения |
OPENROUTER_API_KEY, OPENROUTER_MODEL_PRIMARY, OPENROUTER_MODEL_FALLBACK | не задано | news-scoring-service.ts |
PAYMENT_NEWS_PROCESSOR | запасной вариант PAYMENT_DEFAULT_PROCESSOR, затем wayforpay | lib/payments/payment.config.ts |
NEWS_PROMOTION_WEBHOOK_SECRET | не задано | PATCH /api/news/promotion/submit |
ADMIN_BOT_TOKEN | не задано | Ответы на callback в Telegram |
Все четыре таблицы используют документную модель JSONB (id, data jsonb, временные метки) в data/schema.sql (сплющенная v4.1.0): news, news_categories, news_likes, news_submission_audit. Каждый переход дописывает запись в data.mainPageStatusHistory и создаёт одну строку news_submission_audit. Файлы data/migrations/002_news_content_schema.sql и 003_news_kingdom_upgrade.sql носят исторический характер. Новые установки применяют только schema.sql.
approveMainPagePublication() устанавливает status: 'published' и visibility: 'site-wide'. Для материалов, написанных пользователями, затем в очередь ставится enqueueRewardCreditAddEvent({ trigger: 'newsStoryApproved' }) и запускается generateArticleTranslations(). Получатели в Telegram: пользователи с ролью администратора платформы и заполненным communication.telegramId.
Примените схему и создайте статью участника
Примените data/schema.sql и войдите как пользователь с ролью member или выше. Создайте статью на /news/create. Она получает blogUsername и после публикации появляется по адресу /{username}/{slug}.
Подайте статью на продвижение
Ответ содержит status, aiScore и либо перенаправление, либо платёжные поля для checkout.
Сымитируйте оплату в dev
Одобрите
Нажмите Approve на карточке в Telegram или вызовите POST /api/mcp/v1/news/<id>/approve с сервисным токеном. Проверьте, что mainPageStatus имеет значение published_main и что существует строка news_submission_audit.