note の記事投稿を自動化しようとして、丸一日ハマった話。

タイトル・本文はブラウザの自動操作(ProseMirrorへのpasteイベント偽装)で問題なく投入できた。ハッシュタグや価格の設定画面でも、input要素に値をセットしてinput/changeイベントを発火させれば、画面上はチップとして表示され、成功したように見えた。

だが、しばらく経ってから同じ設定画面を開き直すと、価格もハッシュタグも初期値に戻っていた。

何が起きていたのか

ハッシュタグを5つ設定 → 価格を¥980に設定 → 画面上は正しく反映(チップも表示、値も入力済み) → ここで一旦作業を離れる → 数十分後に同じ画面を再訪 → 価格は¥300(デフォルト)、ハッシュタグは自動提案の5つに戻っていた。

ブラウザのネットワークログを見ても、pricehashtagを含むAPIリクエストは一度も送信されていなかった。

つまり、inputイベント・changeイベントを発火させて画面上の見た目を変えることと、その値がサーバーに保存されることは別だった。この設定パネルは、フィールドごとに自動保存する作りではなく、一連の画面遷移を最後まで進めて「投稿する」(または「更新する」)ボタンを押した時にまとめて送信する作りになっていた。

正しい手順

  1. ハッシュタグ・価格などを設定する
  2. 画面をリロードせず、間を空けずに、公開フローの次のステップへ進むボタン(有料記事なら「有料エリア設定」、それ以外は次の確認画面)をクリックする
  3. 最終確認画面で「投稿する」(または「更新する」)を押す

途中でタブを閉じる、リロードする、長時間放置する、といったことをすると、それまでの入力はブラウザの一時的な状態としてしか存在していないため失われる。

もう一つの罠: 「保存中」の表示が固まって見えることがある

「投稿する」を押した直後、ボタンが「保存中」の表示のまま長時間止まって見えることがあった。

これは実際には次の画面への遷移が進行中で、document.readyStateを確認するとcompleteのまま、コンソールにはトラッキング用スクリプトのfailed to fetchエラーが並んでいた(広告ブロッカーや拡張機能による分析用リクエストのブロックが原因で、実際の投稿処理とは無関係)。焦らずに数秒待つと、正しく次の画面(公開設定 → 記事ページ)に遷移していた。

まとめ

  • フォーム要素に値をセットしてinput/changeイベントを発火させても、それだけではサーバーに保存されないサービスがある
  • 保存の実体が「最後の送信ボタンを押した時の一括送信」である場合、途中経過を信用してリロードすると全部消える
  • 自動操作をするなら、値の設定から最終送信までを、リロードを挟まず一続きの手順として実行するのが安全
  • 一見固まって見える「保存中」表示は、無関係なトラッキングスクリプトのエラーで判断せず、実際のページ遷移状況を見て判断する