Goでslackのチャネルを開くAlfred Workflow作ってみた
はじめに
こちらの記事はZennで投稿した「Goでslackのチャネルを開くAlfred Workflow作ってみた」の再投稿になります。
Goの勉強がしたいと思い、普段使用しているAlfredのWorkflowを作ってみました。 今回は作ったものの紹介と公開するまでにやったことをまとめたいと思います。
Alfred Workflowとは
Alfredは多機能なランチャーアプリです。 無料版でも使えるのですが、有料版を購入することでWorkflow機能が使えるようになります。
Workflow機能は、コマンドを入力することでさまざまな作業を実行してくれる機能になります。Workflow機能が使えるようになると、自作したものや公開されているWorkflowが使えるようになり、さまざまなことができるようになります。
よく使われているものはまとめられています。
GitHub - zenorocha/alfred-workflows: :metal: A collection of Alfred 3 and 4 workflows that will rock your world
:metal: A collection of Alfred 3 and 4 workflows that will rock your world - zenorocha/alfred-workflows
作ったAlfred Workflowの紹介
今回作ったWorkflowは、slackのチャネルを指定して、slackアプリでチャネルを開くという単純なものになります。
GitHub - monda00/alfred-slack-workflow: Alfred workflow to open slack channel.
Alfred workflow to open slack channel. Contribute to monda00/alfred-slack-workflow development by creating an account on GitHub.
機能
- slackアプリでチャネルを開く
- キャッシュのチャネル一覧を更新する
チャネルを開くとき毎回チャネル一覧を取得していると実行に時間がかかっていたので、キャッシュに保存しています。
Goで処理部分を作成する
ここからは実際に作成した部分を紹介します。
まずはGoで処理部分を実装していきます。
awgo
というライブラリを使うことでAlfred Workflowを作成できます。
aw package - github.com/deanishe/awgo - Go Packages
Goで実装する部分では以下のことをします。
slackアプリでチャネルを開くのはAlfred側で行います。
実行するコマンドを分ける
main.go
ではコマンドラインオプションでチャネルを開くコマンドとキャッシュを更新するコマンドを分けて実行できるようにします。
1package main
2
3import (
4 "flag"
5
6 aw "github.com/deanishe/awgo"
7)
8
9var (
10 wf *aw.Workflow
11 cache_dir = "./cache"
12 cache_file = "cache.json"
13)
14
15type Channel struct {
16 Name string `json:"name"`
17 ID string `json:"id"`
18 TeamID string `json:"teamid"`
19}
20
21func init() {
22 wf = aw.New()
23}
24
25func run() {
26 update := flag.Bool("update", false, "Update Channels")
27 open := flag.Bool("open", false, "Open Channel")
28 flag.Parse()
29
30 if *update {
31 updateChannels()
32 return
33 }
34
35 if *open {
36 openChannel()
37 return
38 }
39
40}
41
42func main() {
43 wf.Run(run)
44}
チャネル一覧とチームIDを取得
update.go
ではslack-go
でチャネル一覧とチームIDを取得し、awgo
のキャッシュ機能を使って保存しています。
slackのトークンはAlfredに環境変数があるため、そこに保存しています。
1package main
2
3import (
4 aw "github.com/deanishe/awgo"
5 "github.com/slack-go/slack"
6)
7
8func updateChannels() {
9 wf.NewItem("Update Channels").Valid(true)
10
11 c := aw.NewCache(cache_dir)
12 cfg := aw.NewConfig()
13 token := cfg.Get("SLACK_TOKEN")
14 api := slack.New(token)
15 params := slack.GetConversationsParameters{}
16 channels, _, err_channels := api.GetConversations(¶ms)
17 team, err_team := api.GetTeamInfo()
18
19 if err_channels != nil || err_team != nil {
20 wf.Warn("Error", "Error occurred in Slack API ")
21 }
22
23 all_channels := make([]Channel, 0)
24 for _, channel := range channels {
25 all_channels = append(all_channels, Channel{
26 Name: channel.Name,
27 ID: channel.ID,
28 TeamID: team.ID,
29 })
30 }
31
32 c.StoreJSON(cache_file, all_channels)
33 wf.SendFeedback()
34}
開くチャネルのアイテムを生成
キャッシュの情報から開くチャネルのアイテムを生成します。
Alfred側でチャネルを開くのにチャネルIDとチームIDが必要なため、Var
メソッドで変数にして渡しています。
全てのチャネルのアイテムを生成したら、コマンドから与えられた文字列でフィルタリングしています。
1package main
2
3import (
4 aw "github.com/deanishe/awgo"
5)
6
7func openChannel() {
8 c := aw.NewCache(cache_dir)
9
10 var c_channels []Channel
11 if c.Exists(cache_file) {
12 if err := c.LoadJSON(cache_file, &c_channels); err != nil {
13 wf.FatalError(err)
14 }
15
16 for _, channel := range c_channels {
17 wf.NewItem(channel.Name).
18 Var("teamID", channel.TeamID).
19 Var("channelID", channel.ID).
20 Valid(true)
21 }
22 }
23
24 args := wf.Args()
25 if len(args) > 1 {
26 wf.Filter(args[1])
27 }
28
29 wf.SendFeedback()
30}
Alfred Workflowを作成する
次にAlfredからWorkflowを作成します。
Workflowの全体像は以下のようになります。
キャッシュの更新
Goの実行ファイルであるslack-alfred-workflow
を-update
オプションをつけて実行します。
チャネルを開く
-open
オプションをつけて実行します。
{query}
には実行する時のコマンドから開くチャネル名が渡されます。
実際にslackアプリでチャネルを開きます。
open
コマンドを使うことでチャネル指定でslackアプリを開くことができます。
Makefileでビルドする
Goをビルドして、生成された実行ファイルとAlfred Workflowのinfo.plist
ファイルをzipでまとめてWorkflowファイルを作ります。
1SHELL := /bin/bash
2
3PLIST=info.plist
4ICON=icon.png
5EXEC_BIN=slack-alfred-workflow
6DIST_FILE=slack.alfredworkflow
7GO_SRCS=$(shell find -f . \( -name \*.go \))
8
9all: $(DIST_FILE)
10
11$(EXEC_BIN): $(GO_SRCS)
12 go build -o $(EXEC_BIN)
13
14$(DIST_FILE): $(EXEC_BIN) $(CREDITS) $(PLIST)
15 zip -r $(DIST_FILE) $(PLIST) $(ICON) $(EXEC_BIN)
Github ActionsでCI/CDする
せっかくなのでGithub Actionsを使ってみました。 tagをpushすると、GithubのReleasesにWorkflowファイルがアップされるようにしています。
1name: Release
2on:
3 push:
4 tags:
5 - "v*"
6jobs:
7 release:
8 runs-on: macos-latest
9 steps:
10 - name: Checkout source codes
11 uses: actions/checkout@v2
12
13 - name: Step Go environment
14 uses: actions/setup-go@v2
15 with:
16 go-version: 1.16
17
18 - name: Restore cache if available
19 uses: actions/cache@v2
20 with:
21 path: ~/go/pkg/mod
22 key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
23 restore-keys: |
24 ${{ runner.os }}-go-
25 - name: Download modules
26 if: steps.cache.outputs.cache-hit != 'true'
27 run: go mod download
28
29 - name: Build
30 run: make
31
32 - name: Create new release
33 id: create_release
34 uses: actions/create-release@v1
35 env:
36 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
37 with:
38 tag_name: ${{ github.ref }}
39 release_name: Release ${{ github.ref }}
40 draft: false
41 prerelease: false
42
43 - name: Upload release asset
44 id: upload_release_asset
45 uses: actions/upload-release-asset@v1
46 env:
47 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
48 with:
49 upload_url: ${{ steps.create_release.outputs.upload_url }}
50 asset_path: ./slack.alfredworkflow
51 asset_name: slack.alfredworkflow
52 asset_content_type: application/zip
参考
- Alfred Workflows - Extend Alfred and Boost Your Productivity
- deanishe/awgo: Go library for Alfred 3 + 4 workflows
- aw · pkg.go.dev
- slack-go/slack: Slack API in Go - community-maintained fork created by the original author, @nlopes
- deanishe/awgoを使って簡単にAlfred Workflowを作る - ぽよメモ
- GitHub Actions のクイックスタート - GitHub Docs
- mvdan/github-actions-golang: GitHub Actions as CI for Go