Node.js で Alfred Workflows を作る

August 23, 2020

概要

Alfred は、Mac の多機能ランチャーアプリケーションです。 この記事では、Alfred の機能のひとつ、Alfred Workflows(以下、ワークフロー)を Node.js で作成する方法を説明します。

「alfy」というライブラリを利用すると、Node.js でワークフローをカンタンに作成できます。

環境

  • Alfred 4(Powerpack)
  • Node.js 10

ワークフローのしくみ

ワークフロー(要 Powerpack)は、Alfred に割り当てたトリガーや検索ボックスのインプットをもとに、情報を加工し出力します。

01

たとえば筆者が作成した alfred-kibela-workflow では、次のことを行っています。

  1. ユーザーより、「ワークフローのトリガーワード」+「キーワード」が入力される
  2. 入力されたキーワードで、Kibela というサービスのノートを検索するため、API を実行する
  3. 検索結果のノート一覧を Alfred 上に表示する
  4. ユーザーからノートが選択される、ブラウザでそのノートを表示する

ワークフローは、Alfred の画面から「Trigers」や「Input」「Actions」などのブロックを組み合わせて作ります。

02

ここで、API を実行したり API から取得したデータを Alfred で表示できるデータに加工するため、簡単なスクリプトを書く必要があります。

作成手順

今回は、Qiita の記事をキーワード検索して記事一覧を表示し、ユーザーが一覧から記事を選ぶとその記事をブラウザで開くというワークフローを作成します。

1. ダミーワークフローの作成

ダミーワークフローを作って、info.plist を作成します。 info.plist は、Alfred ワークフローのマニフェストファイルです。

2. 新規作成

  1. Alfred の設定画面を開き、[Workflows] タブを選択します。
  2. 画面下の[+]マークをクリックし、[Blank Workflow]を選択します。ワークフローの作成ダイアログが表示されます。
  3. ワークフローを設定します。
    • あとで値は変更できますが、「Name」と「Bundle Id」は必ず入力してください。
  4. [Create]ボタンをクリックして作成します。Workflow のリストに作成したワークフローが表示されます。

3. ブロックの作成

  1. 作成したワークフローを選択します。

  2. 右側のブロックエディタ部分で右クリックします。

  3. 次のブロックを追加します。

    • [Input] > [Script Filter] を選択し、「Script Filter」ブロック
    • [Actions] > [Open URL]を選択し、「Open URL」ブロック
  4. 追加したブロックで、それぞれ次のように設定します。

    • 「Script Filter」ブロック 03

      項目説明
      Keywordワークフローのトリガーキーワードを設定します。
      -「with space」にチェック
      -「Argument Required」を選択
      Language「/bin/bash」を選択し、「with input as {query}」を選択します。
      Script./node_modules/.bin/run-node src/index.js "{query}" と入力します。
      あとで作成する Node.js プログラムを実行するコマンドです。
    • 「Open URL」

      項目説明
      Encode input as UTF-8チェックを入れる
      Browser「Default Browser」を選択
  5. ブロックを結合します。 04

4. info.plist のエクスポート

  1. 作成したワークフローを右クリックし、[Open in Finder]を選択します。
  2. info.plistがあるので、別の場所にコピーしておきます。
  3. 作成したダミーワークフローを削除します。

5. Node.js プログラムの作成

Node.js でスクリプトを作成します。 ここでは、Qiita API を実行して記事を検索し、取得結果を Alfred の一覧に渡すことを考えます。

  1. プロジェクトを作成します。

    mkdir alfred-workflow-example && cd $_
    npm init -y
  2. 先ほどコピーした info.plist をプロジェクトディレクトリの直下に配置します。

  3. alfy をインストールします。

    npm i --save alfy
  4. package.json を開き、npm スクリプトを定義します。

    "scripts": {
      "postinstall": "alfy-init",
      "preuninstall": "alfy-cleanup"
    },
  5. js ファイルを作成します。

    mkdir src
    touch src/index.js
  6. src/index.js を開き、以下を記述します。

    const alfy = require("alfy");
    
    const token = process.env.QIITA_ACCESS_TOKEN || "";
    
    const keyword = alfy.input;
    const resp = await alfy.fetch(
      `https://qiita.com/api/v2/items?query=body:${keyword}`,
      {
        method: "get",
        headers: {
          Authorization: `Bearer ${token}`,
          "Content-Type": "application/json",
        },
      }
    );
    const items = resp.map((el) => {
      return {
        title: el.title,
        subtitle: el.user.name,
        arg: el.url,
      };
    });
    
    alfy.output(items);

コードのポイント

  • アクセストークン

    • アクセストークンなどのユーザー固有の値は、設定する環境変数をワークフローごとに定義します。この値は、process.env.KEY で受け取ることができます。
  • ワークフローに渡される変数

    • ワークフローでトリガーと一緒に引数を渡したい場合、「Filter Script」ブロックを使ってスクリプトに渡します。渡された値は alfy.input を使って受け取ります。
  • alfy.fetch() を使うと、HTTP リクエストを送信できます。

    • http.request をベースに作られているため、ヘッダーやデータなど渡すオプションは http.request のドキュメントを参照してください。
    • 戻り値は Promise です。
  • alfy では top-level-await を利用するには、package.json に以下を追記します。

    "esm": {
      "await": true
    },
  • Alfred がサポートしている JSON オブジェクトになるよう、リクエスト結果を加工します。

    • Actions や Outputs のブロックに渡したい値を arg に設定します。

ワークフローのインストール

  1. 作成したワークフローをインストールします。プロジェクトディレクトリ直下で、次のコマンドを実行します。

    npx alfy-init
  2. Alfred ワークフローの設定画面を開きます。

  3. 一覧より、インストールしたワークフローを選択します。

  4. 環境変数を設定します。[x] ボタンをクリックします。

  5. 次の環境変数を設定します。

    NameValue
    QIITA_ACCESS_TOKENQiita のアクセストークン
    Qiita のアプリケーション設定画面から作成できます。

動作確認

  1. Alfred を起動します。
  2. 「qiita 検索クエリ」を入力します。
  3. しばらくすると、検索結果の一覧が表示されます。
  4. 一覧からエンターキーで選択します。ブラウザで該当の記事が表示されます。

ワークフローの公開

作成したワークフローは、npm intall コマンドでインストールできるような形にすると、他の人に配布できます。 たとえば、GitHub リポジトリに公開したり、さらに npm registory に公開したりするなどです。

公開するときは、info.plist の中に環境変数の値がセットされていないことを次の手順で確認してください。含まれていた場合は削除してください。

  1. info.plist をテキストエディタで開きます。
  2. エディタ内で、環境変数名を検索します。
      <key>variables</key>
      <dict>
        <key>QIITA_ACCESS_TOKEN</key>
        <string>This_is_a_Qiita_token</string>
      </dict>
  3. 環境変数の値がセットされていた場合は、値を削除しておきます。
      <key>variables</key>
      <dict>
        <key>QIITA_ACCESS_TOKEN</key>
        <string></string>
      </dict>