Страница перенаправления для внешних URL

Привет! Я хотел бы перенаправлять все внешние ссылки (или, если фильтрация невозможна, все ссылки) на адрес вида exit.website.tld/?page={{URL}}. Возможно ли это в Discourse? Если нет, существует ли для этого плагин? Я уже искал, но не смог найти подходящий с помощью использованных поисковых запросов. Это должно работать аналогично тому, как это делает Steam. (Пример)

Я тоже об этом думал; я хотел добавлять URL сохранения из Internet Archive ко всем внешним ссылкам, и, будем честны: было бы круто настраивать это по категориям.

Думаю, для этого можно использовать какой-то фильтр через плагин, но люди часто делают вещи с компонентами темы, которые, кажется, нарушают правила манипуляции данными. Так что, если это сейчас невозможно, как, по вашему мнению, лучше реализовать это: через плагин или компонент темы?

Мы считаем эту функцию своего рода враждебной по отношению к пользователям (по аналогии с «подписями в форумах»), поэтому она должна быть реализована в виде плагина. Не уверен, что это можно сделать через компонент темы.

Я уже встречал подобные запросы в контексте безопасности, например:

:scream: о нет! вы собираетесь перейти по ГИПЕРССЫЛКЕ на САЙТ! Вы готовы к НЕВЕРОЯТНОЙ ОПАСНОСТИ?!??!

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

Я администрирую категорию для архивирования веб-сайтов. Наше использование очень специфично/лениво. :slight_smile:

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

Это справедливо, могут быть некоторые обоснованные случаи использования, я просто здесь борюсь за пользователей, брат…

На мой взгляд, это может быть связано именно с безопасностью, потому что, конечно, здесь, на форуме Discourse Meta или на некоторых форумах для программистов, люди умеют различать URL и т. д., но на форумах, не ориентированных на технологии (особенно на форумах для нетехнических профессий, учебных заведений и т. д.), многие пользователи могут не заметить, что находятся на сайте, который выглядит точно так же, но имеет другой домен верхнего уровня (TLD) или даже совершенно другое доменное имя.
И хотя это, конечно, может показаться враждебным по отношению к пользователям для некоторых форумов, никто не говорит, что эту функцию нужно включать по умолчанию. Можно просто сделать её в виде флажка, который затем будет использовать страницу самого Discourse или вести напрямую на пользовательскую страницу.
На мой взгляд, это скорее важная функция, которая должна быть встроена непосредственно в Discourse, но, конечно, это лишь моё личное мнение.

Джефф четко дал понять, что это должно быть реализовано в виде плагина (если только это нельзя сделать в теме, что, вероятно, возможно). История подсказывает, что если вы разработаете функционал входа в систему, и его захотят сотни сайтов, включая десятки корпоративных клиентов, то он станет официальным плагином всего за несколько лет.

Однако, если это возможно реализовать в теме, что, по моему мнению, вероятно, то можно сказать, что Discourse уже поддерживает эту функцию — вам просто нужна тема для её включения! Вы можете ознакомиться с руководством разработчика по темам Discourse или разместить запрос в канале Marketplace с указанием бюджета. Я предполагаю, что это стоит не менее 1000 долларов, но могу ошибаться.

Хотя у меня нет опыта работы с темами Discourse и подобным, у меня есть базовые знания в области JS и HTML. Что-то вроде этого не должно занимать больше 10–20 минут работы. Почему для этого нужен бюджет в 1000 долларов?

Если вы можете сделать это за двадцать минут, значит, вы уже должны были это сделать. Я всё ещё довольно плохо разбираюсь в JavaScript и Ember, возможно, это гораздо проще, чем я думаю. Мне кажется, что это займёт несколько часов работы.

Пожалуйста, опубликуйте ссылку на вашу тему! Я не могу дождаться, чтобы её увидеть.

Примерно через 5 минут я получил работающий JS-код (который всё ещё требует доработки, но работает; кстати, всего 10 строк). Единственное, что мне теперь нужно выяснить, — как запускать этот код после загрузки страницы…

Отлично! Рад, что всё прошло так легко! Обычно у меня на это уходит безумное количество времени. Я, как правило, лучше угадываю, сколько времени это должно занять.

В целом, это просто проверка того, что вы находитесь на странице статьи, перебор всех тегов <article>, поиск тега с фактическим содержимым внутри них, перебор всех тегов <a> внутри этого содержимого и, если их атрибут href не ведет на официальный сайт (используя для этого простое регулярное выражение), добавление URL страницы выхода перед ним.

Однако я все еще не могу разобраться, как запускать JS-код после того, как страница полностью загрузится и будет загружено все динамическое содержимое (например, посты). Временным решением было бы просто запускать код через 1–2 секунды, но это не очень надежно, и для некоторых пользователей загрузка может занять больше времени…

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

То, что вы ищете, называется декоратором поста. Это хук, который позволяет запускать скрипты перед отрисовкой каждого поста. Он является частью API плагинов.

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

Это размещается в секции header вашей темы или компонента темы:

<script type="text/discourse-plugin" version="0.8">
  // Сохраняем имя хоста, чтобы можно было использовать его повторно.
  const siteHostname = location.hostname;
  
  // Создадим декоратор для выполнения этого в каждом посте
  api.decorateCooked(
    post => {
      // Есть ли в посте ссылки?
      const links = [...post[0].querySelectorAll("a")];
      
      // Ссылок нет, выходим.
      if (!links.length) return;
      
      // Ссылки есть, отфильтруем их и возьмём только внешние
      const externalLinks = links.filter(
        link => link.hostname !== siteHostname
      );
      
      // Если есть внешние ссылки, выполним некоторые действия. Например, можно
      // добавить класс к каждой внешней ссылке следующим образом.
      externalLinks.forEach(link => {
        link.classList.add('external-link');
        // Здесь можно выполнить дополнительные действия.
      });
    },
    // Присваиваем декоратору идентификатор, чтобы избежать утечек памяти.
    { id: "external-link-decorator" }
  );
</script>

Ещё раз: перенаправление пользователей создаёт слишком много трения и быстро станет раздражающим. Поэтому я бы рассмотрел другой подход, например, добавление небольшой иконки рядом с внешними ссылками и обучение пользователей тому, что она означает?

Думаю, этот случай использования гораздо лучше обслуживается плагином или внешней интеграцией (с использованием вебхука создания/редактирования поста), который гарантирует, что все связанные сайты будут правильно сохранены, независимо от того, кликнул ли кто-то на них или нет.