外部URL用のリダイレクトページ

こんにちは!外部リンク(それが不可能な場合はすべてのリンク)を、例えば exit.website.tld/?page={{URL}} のようにリダイレクトしたいと考えています。
これは Discourse で可能でしょうか?もし不可能なら、そのようなプラグインはありますか?すでに検索しましたが、使用した検索クエリでは該当するものが見つかりませんでした。
Steam が行っているような方法です()。

私も同じことを考えていました。すべての外部リンクにインターネットアーカイブの保存URLを追加したいと考えており、正直なところ、カテゴリごとに設定できるとかっこいいですよね。

プラグインで何らかのフィルタ処理を行う方法があるかと思いますが、テーマコンポーネントを使ってデータ操作のルールを曲げてしまうような実装も散見されます。もし現在それが不可能であれば、皆さんはこの機能をどのように実装するでしょうか?プラグインとして、それともテーマコンポーネントとして?

これは「フォーラム署名」のような、ユーザーにとって敵対的な機能だと考えているため、プラグインとして実装する必要があります。テーマコンポーネントで実現できるかどうかはわかりません。

以前、安全性の文脈でこの要望を見たことがあります。具体的には、

:scream: ああだめ!あなたはハイパーリンクを介してウェブサイトへアクセスしようとしています!すさまじい危険に備えていますか?!?!

といったものです。これは、ごく稀なコミュニティの極めて稀な状況では、もしかしたら理にかなっているかもしれませんね…うーん、たぶん?

私はウェブサイトのアーカイブ用のカテゴリを運営しています。私たちのユースケースは、非常に特殊で、少し怠け者です。:slight_smile:

また、ウェブアーカイブプロキシは、メッセージ内の画像のコピーを保存するのと似ていると考えていますが、繰り返しになりますが、私はウェブサイトのアーカイブ用のカテゴリを運営しています:nerd_face:

公平な話、有効なユースケースもあるかもしれません。でも、僕はユーザーのために戦っているんですよ、本当に…

私の意見では、これは実際にはセキュリティに関わる問題かもしれません。もちろん、Discourse のメタフォーラムやいくつかのプログラミングフォーラムでは、ユーザーが URL の違いなどを区別できるでしょう。しかし、技術に特化していないフォーラム(特に非技術職や学校向けのフォーラムなど)では、多くの人が、見た目は同じでも TLD が異なるサイト、あるいは全く異なるドメイン名のサイトにアクセスしていることに気づかない可能性があります。
もちろん、これは一部のフォーラムにとってはユーザーフレンドリーではないかもしれませんが、デフォルトで有効にする必要はありません。チェックボックスのように設定し、Discourse 自体のページを表示するか、カスタムページに直接リンクさせるようにすればよいのです。
私の考えでは、これは Discourse に直接組み込むべき本質的な機能ですが、もちろん、これはあくまで私の個人的な意見です。

Jeff は、これはプラグインとして実装する必要があることを明確にしています(テーマ内で実装できる場合を除きますが、それは可能性が高いようです)。過去の事例を踏まえると、ログイン機能を開発し、数百のサイト(その中には数十のエンタープライズ顧客も含まれます)がそれを求めるようになれば、数年以内に公式プラグインとして採用されるでしょう。

ただし、テーマ内で実装可能であれば(おそらく可能だと思います)、Discourse はすでにその機能をサポートしていると言えます。必要なのはそれを実現するテーマだけです!Discourse テーマの開発者ガイドを確認するか、Marketplace に予算を明記して投稿してみてください。私の推測では、少なくとも1000ドルかかると思いますが、間違っているかもしれません。

Discourse のテーマなどについては経験がありませんが、JS と HTML については基本的な経験があります。このような作業であれば、10〜20 分もかからないはずです。なぜ 1000 ドルもの予算が必要なのでしょうか?

20 分でできるなら、もう終わらせているはずです。私はまだ JavaScript や Ember があまり得意ではないので、思っているよりずっと簡単なのかもしれません。数時間の作業だと思っています。

テーマのリンクを貼ってください!とても楽しみです。

約5分後に動作するJavaScriptコードが完成しました(まだ改善の余地はありますが、動作します。ちなみに10行です)。今後は、ページ読み込み後にこのコードを実行する方法を調べる必要があります。

素晴らしい!こんなに簡単でよかったですね!あの作業、私には信じられないほど時間がかかるんです。だいたい「これくらいかかるはずだ」という推測は得意なんですが。

一般的には、記事ページにいるかを確認し、すべての タグをループして、その中にある実際のコンテンツのタグを見つけ、そこにあるすべての タグをループし、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 を指定します。
    { id: "external-link-decorator" }
  );
</script>

繰り返しになりますが、ユーザーをリダイレクトするのは摩擦が大きすぎて、すぐにうっとうしくなるでしょう。そのため、別のアプローチを検討することをお勧めします。例えば、外部リンクの隣に目立たないアイコンを追加し、ユーザーにその意味を教えるのはどうでしょうか?

このユースケースには、クリックの有無にかかわらずすべてのリンク先サイトが適切に保存されるようにするプラグインや外部連携(投稿作成/編集時のウェブフックを使用)の方がはるかに適していると思います。