Node.jsでAlfred Workflowsを作る

Blog

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

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

動作を確認した環境

  • Alfred 4(Powerpack)
  • Node.js 10

ワークフローのしくみ

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

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

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

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

ここで、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」ブロック

      項目説明
      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. ブロックを結合します。

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. エディタ内で、環境変数名を検索します。

xml <key>variables</key> <dict> <key>QIITA_ACCESS_TOKEN</key> <string>This_is_a_Qiita_token</string> </dict>

  1. 環境変数の値がセットされていた場合は、値を削除しておきます。

xml <key>variables</key> <dict> <key>QIITA_ACCESS_TOKEN</key> <string></string> </dict>