Embed Discourse comments on another website via Javascript

Сотни раз я заходил на ту страницу с CSS, но так и не заметил стили для встраиваемых элементов…

1 лайк

Если у кого-то возникли трудности с поиском того, как выглядит страница встраивания, вот она:

Я попытался реализовать это сегодня, но столкнулся с несколькими проблемами:

  • В сообщении форума сгенерированный URL (из discourseEmbedUrl?) приводится к нижнему регистру (lowercased()), что нарушает работу чувствительных к регистру URL в ссылке, следующей за текстом «Это тема для обсуждения, связанная с оригинальной записью по адресу …».
  • При первой загрузке страницы встраиваемый блок отображает «Загрузка обсуждения…» и зависает. При второй загрузке всё работает корректно.
  • «Тряска» страницы: когда iframe загружается, он имеет высоту по умолчанию, но если комментариев не найдено, высота уменьшается до одной строки с надписью «Начать обсуждение». Это усугубляет проблему с зависанием «Загрузка обсуждения…», так как удерживает большую вертикальную высоту.
  • Было бы неплохо, если бы данные, извлекаемые из родительского элемента embed, отдавали предпочтение мета-тегу вместо преобразования всей страницы в текст. Предполагаю, это более общая особенность поведения Discourse.

Самым большим сюрпризом стало то, что при каждом посещении URL со встроенным обсуждением создается новая тема. Это указано в исходном посте (OP):

Единственное решение, которое я могу придумать, довольно хаковое и полагается на краткосрочный SSR/кэширование для опроса конечной точки embed:

Поэтому, думаю, логика должна быть следующей:

  1. Проверить $discourse/embed/info?embed_url=$link.

  2. Если тема существует, показать embed как обычно.

  3. Если нет, показать кнопку «Начать разговор», ведущую по ссылке $discourse/new-topic?subject=$link.

Сработает ли это, или необходимо реализовать какую-то другую связку?

Новая тема создаётся только при первом посещении страницы со встроенным контентом. При повторных посещениях отображается существующая тема, связанная с этим URL.

Если вы не хотите автоматического создания тем, вы можете создавать их через API-вызовы удобным для вас способом, а затем передавать topicID встроенному контенту, чтобы вручную управлять связью.

Понятно, для моего случая это крайне неудобно, так как у меня десятки тысяч страниц.

Так?

  1. Проверка через API, существует ли тема.
  2. Если не существует — показать кнопку.
  3. Нажатие кнопки — вызов API для создания темы.
  4. Успех — контейнер с кнопкой преобразуется во внедрённый контент.

…но и у этого подхода есть проблемы, например, нажатия на кнопку без последующего взаимодействия.

Есть ли способ создавать тему только тогда, когда пользователь действительно оставит комментарий, что-то вроде этого?:

$discourse/new-topic?subject=$link.

Или проблема в том, что мы не можем передать topicID для детерминированной связи?

Нет, в Discourse невозможно ответить на тему, которой не существует.

Чтобы решить эту задачу, мы сделали возможным создание всех тем для встраивания как скрытых тем, которые автоматически становятся видимыми в списке при первом ответе на них.

Я думаю, что создание темы потребует аутентифицированного запроса, выполняемого на сервере. Если вы не хотите разбираться с этим, альтернативный подход — добавить в интерфейс кнопку, которая запускает код, похожий на этот (код, который иначе автоматически добавлялся бы в тег head страницы): discourse/public/javascripts/embed.js at 581dbca97f2b55c9bbbe40dc3b58a9df7409d77f · discourse/discourse · GitHub. Он просто создаёт элемент iframe, используя эти данные:

<div id='discourse-comments'></div>
<meta name='discourse-username' content='DISCOURSE_USERNAME'>

<script type="text/javascript">
  DiscourseEmbed = {
    discourseUrl: 'http://127.0.0.1:4200/',
    discourseEmbedUrl: 'EMBED_URL',
    // className: 'CLASS_NAME',
  };
</script>

Редактирование: Я решил попробовать. Это лишь доказательство концепции: discourse-embed-iframe-test/app/routes/triggering-embed-code.tsx at main · scossar/discourse-embed-iframe-test · GitHub. Не думаю, что это отличное решение для вашей задачи.

Логика полностью на стороне клиента (функция-загрузчик нужна лишь для удобства). К сожалению, у клиента нет хорошего способа узнать, существует ли тема в Discourse. Поэтому невозможно адаптировать интерфейс в зависимости от того, существует ли тема уже. Есть способы решить эту проблему, но, вероятно, потребуется писать что-то в базу данных приложения.

Discourse использует Window: postMessage() для передачи данных из iframe в родительский документ. Например, когда в встроенных комментариях нажимают на ссылку «Ответить»: discourse/app/assets/javascripts/discourse/scripts/embed-application.js at 581dbca97f2b55c9bbbe40dc3b58a9df7409d77f · discourse/discourse · GitHub. Интересно, можно ли отправлять сообщение в родительский документ, чтобы указать, что тема была создана. Это позволило бы сайтам, например, настраивать собственные индикаторы загрузки или отображать разный интерфейс в зависимости от того, готова ли тема к приёму комментариев.

1 лайк

Думаю, так быть не обязательно, если бы можно было назначить основную ссылку для нового сообщения:

$discourse/new-topic-link?link=$link

Это, вероятно, перенаправляло бы на поток, если он уже существует, и использовало бы существующую логику в настройках встраивания. Возможно, с использованием шаблонов?

Другой способ решения этой проблемы — поиск любых сообщений, ссылающихся на рассматриваемую ссылку, и отображение совпадений в рамках общесайтового обсуждения, рендеринг непосредственно на странице через SSR. Это может быть эквивалентно, учитывая, что встроенные элементы всё равно доступны только для просмотра. Самая очевидная проблема здесь — выбор потока, на который отправить пользователя, когда он захочет принять участие.

edit: если я смогу разобраться, как искать сообщения по содержимому ссылки

Меня интересует, можно ли использовать эту функцию для атаки на форум Discourse. В частности, возможно ли, чтобы кто-то подделал посещение страниц по множеству URL-адресов одного хоста и создал множество тем?

Привет, сообщество Discourse!

Я рад поделиться плагином, который я разработал для тех, кто использует Docusaurus v3 и хочет внедрить комментарии Discourse на свои сайты.

docusaurus-plugin-discourse-comments

Этот плагин упрощает интеграцию комментариев Discourse в ваш сайт на Docusaurus v3. Вот его ключевые возможности:

  • Бесшовная интеграция с Docusaurus v3
  • Настраиваемые маршруты для встраивания
  • Режим отладки для удобного устранения неполадок
  • Автоматическая обработка URL-адресов для встраивания
  • Настраиваемое размещение комментариев

Если вы используете Docusaurus v3 и хотите добавить комментарии Discourse к своей документации или публикациям в блоге, этот плагин значительно упрощает этот процесс.

Вы можете найти плагин на npm: docusaurus-plugin-discourse-comments

4 лайка

Допустим, у меня есть один хост для встраивания blog.example.com и список разрешённых путей с подстановочным знаком, например /.*.

Я хочу добавить ещё один элемент для встраивания с тем же хостом, но с другим списком разрешённых путей, например /new-release.*, и с дополнительным тегом, скажем, releases.

Очевидно, что тема «new release» может соответствовать обоим комбинациям хоста и пути, но какая из них будет иметь приоритет? В каком порядке оцениваются правила?

По-прежнему ли невозможно встраивать темы из закрытого форума на отдельный хост? Мой сценарий использования таков: мы используем Kajabi для размещения продукта и Discourse в качестве платформы комментариев на отдельном веб-сайте. Для каждой платформы требуется отдельный вход, поэтому я предполагаю, что ответ всё ещё «невозможно». Однако это один из ограничивающих факторов для наших пользователей и серьёзная проблема, так как у нас более 750 модулей, каждый со своим собственным пространством для обсуждений. Если бы я мог встраивать тему Discourse для каждого модуля Kajabi на ту же страницу, даже без возможности комментирования на самой странице, это значительно упростило бы процесс и позволило бы легко ссылаться на соответствующую тему в Discourse.

Так есть ли какие-либо прогресс в этом вопросе, или это навсегда останется ограничением для закрытых форумов?

Я вижу, что невозможно встроить комментарии с частного форума (на сайте, использующем отдельный домен):

Однако коллега использует для комментариев на сайте Ghost публичный форум (на совершенно другом домене), где публикуются в основном бесплатные посты. Недавно он опубликовал свой первый пост только для участников. Когда я перевел соответствующую тему на Discourse в категорию, которая доступна не «Всем», а только определенной Группе (связанной с платными участниками сайта Ghost), встроенный блок теперь отображает сообщение «Ошибка встраивания».

Хотя автор оригинального сообщения (OP) заявил, что частные форумы (на отдельных доменах) не позволяют встроенному блоку работать, здесь речь идет о публичном форуме с частной категорией. Проблема, с которой я столкнулся, связана с тем, что частная категория на публичном форуме функционально эквивалентна частному форуму? Ведь я прочитал следующий комментарий, который, похоже, подтверждает это утверждение:

Если действительно темы из частных категорий на публичных форумах нельзя встроить «из коробки», существует ли способ реализовать это путем настройки встроенного блока (и/или платформы)? Я не тороплюсь (надеюсь) «исправить» эту проблему, так как меня в какой-то мере устраивает временный перевод частной категории в публичную (поскольку Discourse не может скрапить частный пост Ghost и, следовательно, непреднамеренно показывать его содержимое неплатящим пользователям в Discourse). Однако, если сделать это рабочим возможно, я не против нанять кого-нибудь в будущем, чтобы доработать встроенный блок и/или отправить запрос на включение изменений (PR) для платформы.

Привет! Я использую функцию встраивания (embed) на своём блоге Ghost, но столкнулся с проблемами при публикации постов на моём форуме. У меня настроены следующие хосты:

Из-за сложностей с настройкой поддомена (мой домен размещён у другого провайдера, чем мой форум Discourse) я решил использовать тег.

Проблема в том, что все мои посты из блога попадают в категорию «Блог» на моём форуме Discourse. Я использую учётную запись администратора как автора постов в Discourse; все три категории позволяют администраторам создавать новые темы.

Не могли бы вы подсказать, что может быть причиной этого?

Может быть, указать пути для каждого? Например, если посты, предназначенные для категории «Блог», находятся в /blog/, то, насколько я помню, можно использовать /blog/*.

1 лайк

Это не работает с Ghost-блогом (по крайней мере, в стандартной установке). Я использую свой основной домен (alphagamer.net), а Ghost-блог автоматически добавляет путь после домена на основе заголовка поста. Я пробовал добавить путь, но он просто удаляется.

1 лайк

Мне интересно, можно ли встроить комментарии Discourse (тему) в тему Discourse? Возможно, с помощью iframe, который включает кнопку ответа, но не остальную часть сайта. То есть без заголовка и подвала.

Аналогично статье с разделом комментариев. Если это объединить с голосованием за посты в теме комментариев, которая встроена в последнюю страницу блога со статьями.

Я использовал его с Ghost без проблем, кроме отсутствия интеграции SSO, что расстраивает пользователей.

Помню, мне пришлось немного доработать пример кода.

Я думаю, что это работает нормально, если у вас есть 1 встраивание. Если же вы пытаетесь встраивать разные типы записей блога в разные категории Discourse, потребуется немного больше настроек.

Я думал, что смогу заставить это работать с помощью тегов, но одних тегов, похоже, недостаточно (для моей настройки). Я полагаю, что в Ghost мне понадобятся Коллекции контента, которые по сути позволяют добавить структуру папок (например, alphagamer.net/blog/ и другие, которые мне нужны). Я попробую это сделать в эти выходные, обновлю свой «белый список путей» и напишу здесь, если мне удастся заставить это работать.

Можно ли указывать список разрешённых путей через запятую, как в этом примере?

/blog/.*,/articles/.*

Редактирование: Похоже, что это не работает. Также не работает и следующее:

/(blog|articles)/.* 

Возможно, для этого нужно использовать два разных хоста?