とにかくやれ！なChrome拡張

:::note info
この記事は、[クソアプリ Advent Calendar 2024](https://qiita.com/advent-calendar/2024/kuso-app)の20日目の記事です。
昨日は@toffyさんの記事でした。
:::

## はじめに

こんにちは、[@rs_tukki](https://twitter.com/rs_tukki)です。

突然ですが、私は今月とても〆切に追われていました。
この記事を含めて執筆するアドベントカレンダーが3本と、年末の某コミックなマーケットの原稿の〆切も控えてました。
でもなかなかやる気が出ない。ついついTwitterを眺めてしまう。

今日はそんな人たちに向けたChrome拡張を紹介しようと思います。

## 今まで作ったクソ拡張

https://qiita.com/rs_tukki/items/9de350e6276c40f54fc4

https://qiita.com/rs_tukki/items/29656329fd0823dc9ed8

https://qiita.com/rs_tukki/items/168bd071cd7f3bf59699

## 今回のテーマ

まずはこちらの動画をご覧ください。

<iframe width="560" height="315" src="https://www.youtube.com/embed/JV3KOJ_Z4Vs?si=zD_UZN-h74Y1_dhh" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

『星のカービィ』シリーズ等のディレクターでおなじみ、桜井政博さんの金言ですね。
やる気がない時はとにかくやれ。
身も蓋もないような気もしますが、結構的を射ている言葉ではないかと思います。  

でも、そんな言葉を知っていても、結局やらないときはやらないものです。

**であれば、強制的にやらざるを得ない状況にすればよいのでは？**

## 成果物

という訳で、作りました。こんなChrome拡張。

https://github.com/rs-tukki/DoAnyway

![twitter-Google-検索-Google-Chrome-2024-12-19-01-27-08.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308803/c98a1afe-35c4-42f1-8515-d97c9b9407f4.gif)


とにかく**Chromeで何かサイトを見ようとすると問答無用で「とにかくやれ」の動画に飛ばしてくれます。**
ここまで無限に「とにかくやれ」の圧を浴び続ければ、流石にやらずにはいられないでしょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308803/e465f42c-f289-1098-5eb1-bb74b2781b32.png)

あなたを焦らせるために、「とにかくやれ」を開いた回数と秒数のカウンターも完備しています。
飛ばす先を自由に決めることもできます。

## 仕組み

仕組みはとにかく単純です。
何かしらのサイトをロードした時に自身のURLでなかったらリダイレクトさせるだけ。

実装については大半をChatGPTの力をお借りしながら作成しました。

```javascript
let redirectUrl = "";
let redirectCount = 0;
let totalTimeSpent = 0;
let startTime = null;
const defaultRedirectUrl = "https://www.youtube.com/watch?v=JV3KOJ_Z4Vs";

  // 設定値の初期化
  chrome.runtime.onInstalled.addListener(() => {
    chrome.storage.local.set({
      redirectUrl: defaultRedirectUrl,
      redirectCount: 0,
      totalTimeSpent: 0
    }, () => {
      redirectUrl = defaultRedirectUrl;
    });
  });

  // タブを開いた際の処理
  chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
    if (changeInfo.status === "complete" && tab.url.startsWith("http")) {
      chrome.storage.local.get("redirectUrl", (data) => {
        const currentRedirectUrl = data.redirectUrl || defaultRedirectUrl;
        if (tab.url !== currentRedirectUrl) {
          chrome.tabs.update(tabId, { url: currentRedirectUrl });
          redirectCount++;
          chrome.storage.local.set({ redirectCount });
          startTime = Date.now();
          startInterval();
        }
      });
    }
  });

  // タブを移動した時の処理
  chrome.tabs.onActivated.addListener(() => {
    if (startTime) {
      recordElapsedTime();
      stopInterval();
    }
  });

  // タブを閉じたときの処理
  chrome.tabs.onRemoved.addListener(() => {
    if (startTime) {
      recordElapsedTime();
      stopInterval();
    }
  });

  // サイトを開いていた時間をDBに保存する
  function recordElapsedTime() {
    if (startTime) {
      const elapsedTime = (Date.now() - startTime) / 1000;
      totalTimeSpent += elapsedTime;
      chrome.storage.local.set({ totalTimeSpent });
      startTime = null;
    }
  }

  // 1秒ごとに時間を計測する
  function startInterval() {
    if (!intervalId) {
      intervalId = setInterval(() => {
        recordElapsedTime();
        startTime = Date.now();
      }, 1000);
    }
  }

  // 計測を終了する
  function stopInterval() {
    if (intervalId) {
      clearInterval(intervalId);
      intervalId = null;
    }
  }
```

[chrome.tabs](https://developer.chrome.com/docs/extensions/reference/api/tabs?hl=ja)APIを使うことで、裏側から各タブの挙動を検知しています。
タブを開いている間だけその時間を計測しておき、タブを移動するか閉じるかしてとにかくやる態勢になったときに計測を終了するような仕組みです。
~~あまりにも作りが単純なところもクソアプリ~~

## まとめ

というわけで、今回はとにかくやるためのChrome拡張を作成しました。
みなさんもやる気がないときはこれを使ってとにかくやらせるようにしましょう。

...え？
それで結局とにかくやれたのかって？

...PC作業をする私の手元にはスマートフォンがありました。
**あとは察してください。** 一応原稿は間に合いました。なんとか。

明日は@RyoKatsuseさんです！