Goでslackのチャネルを開くAlfred Workflow作ってみた
Goの勉強がしたいと思い、普段使用しているAlfredのWorkflowを作ってみました。
今回は作ったものの紹介と公開するまでにやったことをまとめたいと思います。
Alfred Workflowとは
Alfredは多機能なランチャーアプリです。
無料版でも使えるのですが、有料版を購入することでWorkflow機能が使えるようになります。
Workflow機能は、コマンドを入力することでさまざまな作業を実行してくれる機能になります。Workflow機能が使えるようになると、自作したものや公開されているWorkflowが使えるようになり、さまざまなことができるようになります。
よく使われているものはまとめられています。
作ったAlfred Workflowの紹介
今回作ったWorkflowは、slackのチャネルを指定して、slackアプリでチャネルを開くという単純なものになります。
機能
- slackアプリでチャネルを開く
- キャッシュのチャネル一覧を更新する
チャネルを開くとき毎回チャネル一覧を取得していると実行に時間がかかっていたので、キャッシュに保存しています。
Goで処理部分を作成する
ここからは実際に作成した部分を紹介します。
まずはGoで処理部分を実装していきます。
awgo
というライブラリを使うことでAlfred Workflowを作成できます。
Goで実装する部分では以下のことをします。
slackアプリでチャネルを開くのはAlfred側で行います。
実行するコマンドを分ける
main.go
ではコマンドラインオプションでチャネルを開くコマンドとキャッシュを更新するコマンドを分けて実行できるようにします。
package main
import (
"flag"
aw "github.com/deanishe/awgo"
)
var (
wf *aw.Workflow
cache_dir = "./cache"
cache_file = "cache.json"
)
type Channel struct {
Name string `json:"name"`
ID string `json:"id"`
TeamID string `json:"teamid"`
}
func init() {
wf = aw.New()
}
func run() {
update := flag.Bool("update", false, "Update Channels")
open := flag.Bool("open", false, "Open Channel")
flag.Parse()
if *update {
updateChannels()
return
}
if *open {
openChannel()
return
}
}
func main() {
wf.Run(run)
}
チャネル一覧とチームIDを取得
update.go
ではslack-go
でチャネル一覧とチームIDを取得し、awgo
のキャッシュ機能を使って保存しています。
slackのトークンはAlfredに環境変数があるため、そこに保存しています。
package main
import (
aw "github.com/deanishe/awgo"
"github.com/slack-go/slack"
)
func updateChannels() {
wf.NewItem("Update Channels").Valid(true)
c := aw.NewCache(cache_dir)
cfg := aw.NewConfig()
token := cfg.Get("SLACK_TOKEN")
api := slack.New(token)
params := slack.GetConversationsParameters{}
channels, _, err_channels := api.GetConversations(¶ms)
team, err_team := api.GetTeamInfo()
if err_channels != nil || err_team != nil {
wf.Warn("Error", "Error occurred in Slack API ")
}
all_channels := make([]Channel, 0)
for _, channel := range channels {
all_channels = append(all_channels, Channel{
Name: channel.Name,
ID: channel.ID,
TeamID: team.ID,
})
}
c.StoreJSON(cache_file, all_channels)
wf.SendFeedback()
}
開くチャネルのアイテムを生成
キャッシュの情報から開くチャネルのアイテムを生成します。
Alfred側でチャネルを開くのにチャネルIDとチームIDが必要なため、Var
メソッドで変数にして渡しています。
全てのチャネルのアイテムを生成したら、コマンドから与えられた文字列でフィルタリングしています。
package main
import (
aw "github.com/deanishe/awgo"
)
func openChannel() {
c := aw.NewCache(cache_dir)
var c_channels []Channel
if c.Exists(cache_file) {
if err := c.LoadJSON(cache_file, &c_channels); err != nil {
wf.FatalError(err)
}
for _, channel := range c_channels {
wf.NewItem(channel.Name).
Var("teamID", channel.TeamID).
Var("channelID", channel.ID).
Valid(true)
}
}
args := wf.Args()
if len(args) > 1 {
wf.Filter(args[1])
}
wf.SendFeedback()
}
Alfred Workflowを作成する
次にAlfredからWorkflowを作成します。
Workflowの全体像は以下のようになります。
キャッシュの更新
Goの実行ファイルであるslack-alfred-workflow
を-update
オプションをつけて実行します。
チャネルを開く
-open
オプションをつけて実行します。
{query}
には実行する時のコマンドから開くチャネル名が渡されます。
実際にslackアプリでチャネルを開きます。
open
コマンドを使うことでチャネル指定でslackアプリを開くことができます。
Makefileでビルドする
Goをビルドして、生成された実行ファイルとAlfred Workflowのinfo.plist
ファイルをzipでまとめてWorkflowファイルを作ります。
SHELL := /bin/bash
PLIST=info.plist
ICON=icon.png
EXEC_BIN=slack-alfred-workflow
DIST_FILE=slack.alfredworkflow
GO_SRCS=$(shell find -f . \( -name \*.go \))
all: $(DIST_FILE)
$(EXEC_BIN): $(GO_SRCS)
go build -o $(EXEC_BIN)
$(DIST_FILE): $(EXEC_BIN) $(CREDITS) $(PLIST)
zip -r $(DIST_FILE) $(PLIST) $(ICON) $(EXEC_BIN)
Github ActionsでCI/CDする
せっかくなのでGithub Actionsを使ってみました。
tagをpushすると、GithubのReleasesにWorkflowファイルがアップされるようにしています。
name: Release
on:
push:
tags:
- "v*"
jobs:
release:
runs-on: macos-latest
steps:
- name: Checkout source codes
uses: actions/checkout@v2
- name: Step Go environment
uses: actions/setup-go@v2
with:
go-version: 1.16
- name: Restore cache if available
uses: actions/cache@v2
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Download modules
if: steps.cache.outputs.cache-hit != 'true'
run: go mod download
- name: Build
run: make
- name: Create new release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
draft: false
prerelease: false
- name: Upload release asset
id: upload_release_asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./slack.alfredworkflow
asset_name: slack.alfredworkflow
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
- Goでslackのチャネルを開くAlfred Workflow作ってみた | amateur engineer's blog
Discussion