10
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

エンジニアとして働いていると度々お世話になるQiita記事。その有難さには頭が上がりませんが、私のエンジニア歴も1年に達しQiitaの投稿を少しずつ始めた中で一つだけ不満がありました。
Qiitaにはなぜ予約投稿機能がないのだろうか?
...ということで、JavaScriptの練習をかねてQiitaの予約投稿機能をChrome拡張で作ってみました。

使い方

1.上記リンクより拡張機能を追加してください。
2.拡張機能を有効にすると、Qiita記事編集ページに予約投稿ボタンが現れます。
image.png
3.投稿したい時刻をHHmm形式で入力します(投稿予約時刻はコンソールに表示されます)。
image.png
4.予約した時刻になると記事が投稿されます。
image.png

中身

・画面のロード後に、予約投稿ボタンを作成する函数を呼び出します。

var containerDiv, setting, posting, button, hour, minute;

window.onload = function() {
    createButton();
};

・画面の要素を取得して、公開設定ボタンの横に予約投稿ボタンを作成します。

containerDiv : 「下書き保存」「公開設定」を覆うdiv
setting : 「公開設定」ボタン
posting : 「記事を投稿する」ボタン

function createButton() {
    containerDiv = document.querySelector('style-ucg0tn');
    setting = document.getElementsByClassName('style-1fu20hp')[0];
    posting = document.getElementsByClassName('style-mtcazu')[0];
    button = document.createElement('button');
    button.textContent = '予約投稿';
    button.id = 'autoPost'; 

    // ボタンをDOMに追加
    if(containerDiv) {
        containerDiv.appendChild(button);  
    }
    
    // ボタンがクリックされたときの処理
    button.addEventListener('click', function() {
        autoPost();
    });
}

・予約投稿ボタンがクリックされたときの処理を記述します。予約時刻を設定する函数を呼び出し、指定時間後に投稿の動作を行う函数を呼び出します。

function autoPost() {
    if(setting && posting) {
        // スケジュールを設定
        getPostingSchedule();
        if(hour && minute) {
            // 予約時刻になったら投稿
            waitUntilHour(hour, minute, function() {
                setting.click();
                posting.click();
                window.alert("記事を投稿しました!");
            });
        }
    }
}

・指定時間後に処理を行う函数です。予約時刻と現在の時刻の時間差を取得し、Timeoutで指定時間後に呼び出し元で記述された処理を行います。

function waitUntilHour(hour, minute, callback) {
    console.log(`投稿予定時間は${hour}:${minute}です。`);
    var now = new Date();
    var targetTime = new Date(now.getFullYear(), now.getMonth(), now.getDate(), hour, minute, 0, 0);
    var timeDiff = targetTime.getTime() - now.getTime();

    // すでに今日の指定時間を過ぎていた場合
    if (timeDiff <= 0) {
        // 明日の同じ時間に設定
        targetTime.setDate(targetTime.getDate() + 1);
        timeDiff = targetTime.getTime() - now.getTime();
    }

    setTimeout(callback, timeDiff);
}

・投稿予約時刻を設定する函数です。ポップアップで入力を受け付けた後、バリデーションチェックを行い予約時刻を設定します。

function getPostingSchedule() {
    var input = prompt("投稿予定時間をHHmm形式で入力してください。例: 0830");

    // 入力値のチェック
    if (!input || input === "") {
        alert("時間を入力してください。");
        return;
    } else if (input.length !== 4 || !/^\d+$/.test(input)) {
        alert("正しい形式で時間を入力してください。");
        return;
    }
    
    // 入力をHHとMMに分割
    var hourInput = parseInt(input.substring(0, 2), 10);
    var minuteInput = parseInt(input.substring(2, 4), 10);

    // 時間範囲のチェック
    if (hourInput < 0 || hourInput > 23 || minuteInput < 0 || minuteInput > 59) {
        alert("正しい形式で時間を入力してください。");
        return;
    } else if (hourInput < 6 || hourInput > 22) {
        alert("深夜・早朝の投稿は控えましょう。");
        return;
    } else {
        hour = hourInput;
        minute = minuteInput;
    }
}

おわりに

個人の用途としてはギリギリ使える範囲ですが、現状ではブラウザを閉じると動作しない等まだまだ改善の余地が多くあります。軽微なバグ修正などはこの記事の更新、それなりの改修をした場合は新たに記事を投稿して、継続的にアップデートしていきたいです。
指摘・要望も大歓迎です!

--今後の予定
・時刻をサーバーから取得したい
・投稿をクリックでなくAPIで行えないか
・バックグラウンド実行?

10
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?