Goでslackのチャネルを開くAlfred Workflow作ってみた

2021.05.21
Alfred
Alfred WorkflowGoslack

はじめに

こちらの記事は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

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.

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

aw package - github.com/deanishe/awgo - Go Packages

Goで実装する部分では以下のことをします。

  • チャネルを開くコマンドとキャッシュを更新するコマンドを分ける
  • slack-goを使ってチャネル一覧とチームIDを取得してキャッシュを更新
  • awgoで開くチャネルのアイテムを生成

slackアプリでチャネルを開くのはAlfred側で行います。

実行するコマンドを分ける

main.goではコマンドラインオプションでチャネルを開くコマンドとキャッシュを更新するコマンドを分けて実行できるようにします。

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に環境変数があるため、そこに保存しています。

update.go
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(&params)
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メソッドで変数にして渡しています。

全てのチャネルのアイテムを生成したら、コマンドから与えられた文字列でフィルタリングしています。

open.go
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ファイルがアップされるようにしています。

release.yml
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

参考

Support

\ この記事が役に立ったと思ったら、サポートお願いします! /

buy me a coffee
Share

Profile

author

Masa

都内のIT企業で働くエンジニア
自分が学んだことをブログでわかりやすく発信していきながらスキルアップを目指していきます!

buy me a coffee