ブログ記事を書くのはめんどくさい

ブログの記事を書くというのはマジでめんどくさく、しかししばらく経ってから読み返すと案外面白いという唯一の利点のために10年くらい投稿している。めんどくささをできるだけ排除し、少しでも楽をするためにこまごまとした工夫はたくさんある。コマンドひとつでfrontmatter付きの新しいMarkdownファイルを作れるようにMakefileを書いたり、git pushしたら勝手にビルドして公開するようにしたり、404を検知できるようにしたりと、記事投稿やサイト運用のハードルを定期的に取り除きつづけないとわたしはめんどくささに負けてブログを放置してしまうのだ。

旅行系の記事に貼り付ける画像を用意するというのもまたとんでもなくめんどくさい。たくさんある写真から載せたい画像を選び、記事中に貼れるサイズに縮小し、固定URLを発行し、Markdown形式で記事に貼り付ける、という手順を画像の枚数だけ繰り替えす。これがあまりにも面倒なので、いまは全ての画像の埋め込み用URLを発行して記事中に一括して貼り付け、記事を書きながら不要な写真をごりごり削るというスタイルに落ち着いた。この手法は旅行記事みたいな写真が何枚も貼られた記事を書くときに非常に効率がいい。産みの苦しみを解決するのはむずかしくても、ただそこにあるものから品質の低いもの、流れにそぐわないものを取り除くというのはとても簡単なのだ。それっぽく画像が並ぶ記事ができあがれば、あとは写真の隙間にテキストをおいていけば記事は完成する。未来の自分が読むためだけに書いているという前提に立てば、こういう省力化はたぶん正しい。

SmugMugをつかっていたときは縮小された画像への直リンURLが管理者にとって予測可能な形をとっていたため、エディタの置換機能を使えばまとめてリンクを作ることができた。しかしOneDriveに移行してからはそうもいかない。OneDriveではサイトに埋め込める形式のURL発行はサーバーへのリクエストによってランダムなURLとして生成されるからだ。しかたないのでAPIを使って縮小画像URLを生成する短いスクリプトを書いた。OneDriveにかぎらずMicrosoft社のWebサービスはMicrosoft Graph APIとよばれる統合された単一のエンドポイントから操作できる。Azure Active Directoryでアプリケーションとして登録すればサービスプリンシパル経由でも使えるため、頻用するならブラウザを経由しなくてすむように設定しておくとよい。

import { Client } from 'https://esm.sh/@microsoft/[email protected]'

const ACCESS_TOKEN = 'xxxxxxxx'
const DRIVE_ID = 'aaaaaaaa'
const DIRECTORY = 'bbbbbbbb'
const IMAGE_WIDTH = 1200

const client = Client.init({ authProvider: done => done(null, ACCESS_TOKEN) })
const base_url = `/drives/${DRIVE_ID}/items`

const imageIds = await client.api(`${base_url}/${DIRECTORY}/children`)
  .orderby('photo/takenDateTime').get()

const thumbnails = await Promise.all(imageIds.value.map(({ id, file }, idx) => {
  if (file.mimeType.startsWith('image/')) {
    return client.api(`${base_url}/${id}/thumbnails?select=c999999x${IMAGE_WIDTH}`).get()
      .then(({ value }) =>  `![${idx}](${Object.values(value[0])[0].url})`)
  } else {
    return client.api(`${base_url}/${id}/createLink`).post({ type: 'embed' })
      .then(({ link }) => `{{​< video src="${link.webUrl.replace('embed', 'download')}" >​}}`)
  }
}))

console.log(thumbnails.join('\n'))

最初に特定のディレクトリ中にあるファイルを全てとりだし、次のリクエストでディメンションを指定したサムネ画像を生成している。ファイルが画像であれば横1200pxのサイズのサムネイル画像を、動画であれば埋め込み用のリンクを取得してhugoで展開できるようにshortcode記法で出力する。

OneDrive APIはわかりにくいが思いのほか強力で、案外なんでもできる。サムネイルの生成も縦横比を変えないまま任意の大きさに縮小できたりトリミングできたりするし、WordファイルをPDFにするみたいな変換処理やファイルのバージョン管理まで実装されているので、うまく使えばリッチなWebサービス制作にも活用できそうだ。

denoを使うとこういう雑なスクリプトを書くときはファイル一つに収まってくれてうれしい。外部モジュールに依存しているとnode.jsであればpackage.jsonとかnode_modulesとかの邪魔なものをごちゃごちゃと配置しなくてはならないのがうっとおしい。最初からhttpsからのimportが書けたりトップレベルawaitが使えたりするのも便利だ。

参考: