Go言語でSlack,Chatwork,LINEへチャットメッセージを投稿するコマンド作成 (Windows,Linux,Macに対応したコマンドを作成する)

はじめに
===

**この記事は<a href="https://qiita.com/advent-calendar/2018/lifull">LIFULL Advent Calendar 2018</a>の23日目の記事になります。**

はじめまして、<a href="https://LIFULL.com/">株式会社LIFULL</a>でSalesforceアプリケーション開発部署でエンジニアを担当しております @na0AaooQ と申します。よろしくお願い致します。

本記事では、Windows/Mac/Linux上で動作するコマンドとして、Go言語でSlack,Chatwork,LINEへメッセージを投稿するコマンド 
　**「<a href="https://github.com/na0AaooQ/c2ptcli">c2ptcli</a>」**
を作成しましたので、Goのソースコードやコマンド作成手順を共有致します。

Go初心者の為、拙い記事で恐縮ですが、どうぞよろしくお願い致します。

前置き
===

私、主にSalesforceとそれ以外の他システム(PHPで開発されたWebサイト, AWS, Google BigQuery, Chatwork等)と連携する機能の設計や開発を担当しております。

最近、プロジェクト的にSlack,Chatwork等の複数のチャットツールを扱う事が増えてきました。

各チャットのメッセージ送信APIの動作確認を行いたい事がありまして、今までは、各チャットごとにメッセージをPOSTするような入力フォームやスクリプトを用意して対応しておりましたが、少々スクリプトの数が増えてきてしまいました。

以下の理由から、Go言語でSlack,Chatwork,LINEへメッセージを投稿するコマンドを作成してみました。

| No | 理由 |
|:------------|:------------|
|　1 | 各チャットのメッセージ投稿スクリプトの数が増えてきたので、なるべくまとめたい。|
|　2 | Mac, Linuxをお持ちでない方でも、実行環境を問わず、手軽に各チャットへメッセージを投稿できるようにしたい。|
|　3 | curlコマンドや各チャットのメッセージ投稿APIを触った事がない方でも、手軽に各チャットへメッセージを投稿できるようにしたい。|
|　4 | システム監視の通知、任意のスケジュールやタイミングで、簡単に各チャットへメッセージを投稿できるようにしたい。|

その他、私自身がGo言語とクロスコンパイルを試したかったという思いがあり、今回はGoでコマンドを作ってみました。

参考資料
===

Goでのコマンド作成にあたり、以下の記事を参考にさせて頂きました。ありがとうございました。

・<a href="https://qiita.com/techys/items/44a712a76859fe0a9dea">Go言語のHello Worldを3分で試す</a>

・<a href="https://qiita.com/Jxck_/items/02185f51162e92759ebe">Go のクロスコンパイル環境構築</a>

・<a href="https://qiita.com/yyoshiki41/items/fc878494e19b9de93d56">Go言語 http POSTする際のContent-Type</a>

・<a href="http://developer.chatwork.com/ja/">Chatwork APIリファレンス</a>

・<a href="https://api.slack.com/docs/messages">Slack APIリファレンス</a>

・<a href="https://developers.line.biz/ja/reference/messaging-api/">LINE Messaging APIリファレンス</a>

注意事項
===

**本記事のコマンドによるSlack, Chatwork, LINEへのメッセージ投稿はそれぞれのAPIを利用して実現しております。**
**それぞれのAPIコール数には上限や制約がございますので、例えば、同時に何百も並列でメッセージ投稿して、各チャットツール(Slack, Chatwork, LINE)のAPIコール数上限に達しないようご注意頂ければと思います。**　　

**コマンドを実行する際には、Slack様, Chatwork様, LINE様のAPIサーバやインフラへの負荷を考慮頂きながら、実行頂きますようお願い致します。**

Goの開発環境
===

Go言語のソースコードを開発、コンパイルした環境は以下になります。

| OS | マシンの種類 | OSバージョン | カーネルバージョン |
|:------------:|:------------:|:------------:|:------------:|
| Mac | MacBook PRO (Retina) | macOS Mojave 10.14.1 | Darwin Kernel Version 18.2.0 |

Goでコンパイルしたコマンドの動作確認環境
===

Go言語でコンパイルしたコマンドについて、以下の環境で正常に動作する事を確認しました。

| OS | マシンの種類 | OSバージョン | カーネルバージョン |
|:------------:|:------------:|:------------:|:------------:|
| Mac | MacBook PRO (Retina) | macOS Mojave 10.14.1 | Darwin Kernel Version 18.2.0 |
| Windows | HP ProBook | Windows 7 Professional (32bit版) | ビルド 7601 |
| Linux | AWS (EC2) | Amazon Linux 2 | 4.14.88-88.73.amzn2.x86_64 |

Goで作成したコマンドの使い方
===

Goで作成するコマンドの実行方法は以下の通りです。

```
$ ~/c2ptcli/mac/c2ptcli

Usage:
[slackへメッセージを投稿する場合]
  export SLACK_API_TOKEN="slackのAPIトークンをセットする"
  ./c2ptcli slack メッセージ投稿先のチャネル名(例:general) "slackへ投稿したいメッセージ"

[chatworkへメッセージを投稿する場合]
  export CHATWORK_API_TOKEN="chatworkのAPIトークンをセットする"
  ./c2ptcli chatwork メッセージ投稿先のルーム番号 "chatworkへ投稿したいメッセージ"

[LINEへメッセージを投稿する場合]
  export LINE_CHANNEL_ID="LINE Messaging APIのChannel ID文字列をセットする"
  export LINE_CHANNEL_SECRET="LINE Messaging APIのChannel Secret文字列列をセットする"
  ./c2ptcli line メッセージ投稿先のUID(LINE User Id) "LINEへ投稿したいプッシュメッセージ"

$ 
```

既存のコマンド名称と重ならないもので、良い名前が中々思いつかなかったので、
　**　c2ptcli　**
という名称でコマンドを作成しています。
(Chat Post CLIを略して、c2ptcliという名称にしました)

Goで作成したコマンドの実行例
===

コマンドの実行例は以下の通りです。
以下のようにコマンドを実行すると、SlackやChatworkやLINEへメッセージが投稿されます。

## (1) Slackへのメッセージ投稿例

Slackへメッセージを投稿する時は、投稿先のChannel名を指定します。

```
[ec2-user@example-linux-server ~]$ ./c2ptcli slack general "Linux テストメッセージ"
slackメッセージ投稿に成功しました。
  slackメッセージ投稿ステータスコード=[ 200 ] レスポンス内容=[ 200 OK ]
[ec2-user@example-linux-server ~]$ 
```

以下のようにSlackへメッセージが投稿されます。

<img width="1203" alt="スクリーンショット 2018-12-23 22.08.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/63647/f578a429-3e3f-d66a-5dc4-e69384c7ce41.png">

## (2) Chatworkへのメッセージ投稿例

Chatworkへメッセージを投稿する時は、投稿先のルーム番号を指定します。

```
[ec2-user@example-linux-server ~]$ ./c2ptcli chatwork 9xxxxxxx "Linux テストメッセージ"
chatworkメッセージ投稿に成功しました。
  chatworkメッセージ投稿ステータスコード=[ 200 ] レスポンス内容=[ 200 OK ]
[ec2-user@example-linux-server ~]$ 
```

以下のようにChatworkへメッセージが投稿されます。

<img width="1198" alt="スクリーンショット 2018-12-23 22.01.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/63647/32541665-0769-a791-9b4f-aee78c12cfc6.png">

## (3) LINEへのメッセージ投稿例

LINEへメッセージ(プッシュメッセージ)を投稿する時は、投稿先のLINEユーザID(LINE UID)を指定します。

LINE UIDとは、LINEコンソール画面( https://developers.line.biz/console/channel/********/basic/ )の「チャネル基本設定」→「その他」→「Your user ID」に記載されている各LINEユーザに付与された30桁程度のユニークIDの事です。

```
[ec2-user@example-linux-server ~]$ ./c2ptcli line U2******************************* "Linux テストメッセージ"
line APIアクセストークン取得に成功しました。
lineメッセージ投稿に成功しました。
  lineメッセージ投稿ステータスコード=[ 200 ] レスポンス内容=[ 200  ]
  line APIアクセストークン取得ステータスコード=[ 200 ] レスポンス内容=[ 200 OK ]
[ec2-user@example-linux-server ~]$ 
```

以下のようにLINEへメッセージが投稿されます。

<img width="443" alt="スクリーンショット 2018-12-24 4.38.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/63647/68d5184f-d61f-fc80-f7fc-5ff79a89e051.png">

Goのソースコード作成とコンパイル手順
===

今回、Goで作成したコマンドのソースコードは以下リポジトリに保存しております。そのソースコードをコンパイルしてコマンドを生成します。

https://github.com/na0AaooQ/c2ptcli

ソースコードのコンパイル手順を以下に記します。

## (1) Goの開発環境を準備します。

Goをインストールします。

```
$ brew install go
```

Goがインストールされた事を確認します。

```
$ which go
/usr/local/bin/go
$ 
```

## (2) Goのソースコードを作成します。

```
$ mkdir ~/c2ptcli
$ 
```

```
$ cd ~/c2ptcli/
```

```
$ vi c2ptcli.go
```

ソースコードの内容は以下になります。

```golang:c2ptcli.go
package main

import (
  "fmt"
  "os"
  "net/http"       // チャットAPIコール用
  "net/url"        // チャットAPIコール用
  "strings"        // チャットAPIコール用
  "bytes"          // LINE Messaging APIコール用
  "encoding/json"  // JSONパース用
  "io/ioutil"      // JSONパース用
)

// Slack APIメッセージ投稿結果レスポンス(json)格納用構造体
// Slackは存在しないchannelにメッセージを投稿した場合でも、ステータスコード200を返す為、Slack APIレスポンスのok,errorをチェックする
type SlackResponse struct {
  Ok    bool   `json:"ok"`
  Error string `json:"error"`
}

// LINE Messaging API認証レスポンス(json)格納用構造体
type LineAuthResponse struct {
  AccessToken   string `json:"access_token"`
  ExpireIn      int32  `json:"expires_in"`
  TokenType     string `json:"token_type"`
}

///////////////////////////////////////////////////////////////////////////
// Slackへメッセージを投稿する
///////////////////////////////////////////////////////////////////////////
func SlackMessagePost(chatKind, apiUrl, apiToken, channel, message string) error {
  values := url.Values{}
  values.Set("token", apiToken)
  values.Add("channel", channel)
  values.Add("text", message)

  req, err := http.NewRequest(
    "POST",
    apiUrl,
    strings.NewReader(values.Encode()),
  )
  if err != nil {
    fmt.Println(err)
    return err
  }

  // Content-Type 設定
  req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

  // チャットへメッセージを投稿
  client := &http.Client{}
  resp, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return err
  }
  defer resp.Body.Close()

  // メッセージ投稿結果の表示
  if resp.StatusCode == http.StatusOK {
 
    // Slack APIレスポンスをパースする
    slackRespArray, _ := ioutil.ReadAll(resp.Body)
    slackRespJsonBytes := ([]byte)(slackRespArray)
    slackRespData := new(SlackResponse)

    // Slack APIレスポンスのok:がfalseの場合、メッセージ投稿エラー
    if err := json.Unmarshal(slackRespJsonBytes, slackRespData); err != nil {
      fmt.Println("JSON Unmarshal error:", err)
    }
    if slackRespData.Ok == false {
      fmt.Println(chatKind + "メッセージ投稿に失敗しました。")
      fmt.Println("  " + chatKind + "メッセージ投稿結果=[", slackRespData.Ok, "] メッセージ投稿エラーメッセージ=[", slackRespData.Error, "]")
    } else {
      fmt.Println(chatKind + "メッセージ投稿に成功しました。")
    }

  } else {
    fmt.Println(chatKind + "メッセージ投稿に失敗しました。")
  }
  fmt.Println("  " + chatKind + "メッセージ投稿ステータスコード=[", resp.StatusCode, "] レスポンス内容=[", resp.Status, "]")

  return err
}

///////////////////////////////////////////////////////////////////////////
// LINEへメッセージを投稿する
///////////////////////////////////////////////////////////////////////////
func LineMessagePost(chatKind, apiAuthUrl, apiPushMessageUrl, lineChannelId, lineChannelSecret, lineUid, message string) error {

  values := url.Values{}
  values.Set("client_id", lineChannelId)
  values.Add("client_secret", lineChannelSecret)
  values.Add("grant_type", "client_credentials")

  req, err := http.NewRequest(
    "POST",
    apiAuthUrl,
    strings.NewReader(values.Encode()),
  )
  if err != nil {
    fmt.Println(err)
    return err
  }

  // Content-Type 設定
  req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

  // LINE Messaging APIのアクセストークン取得
  client := &http.Client{}
  resp, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return err
  }
  defer resp.Body.Close()

  // メッセージ投稿結果の表示
  if resp.StatusCode == http.StatusOK {
 
    // LINE Messaging APIレスポンスをパースする
    lineRespArray, _ := ioutil.ReadAll(resp.Body)
    lineRespJsonBytes := ([]byte)(lineRespArray)
    lineRespData := new(LineAuthResponse)

    // LINE Messaging APIアクセストークン取得結果をチェック
    if err := json.Unmarshal(lineRespJsonBytes, lineRespData); err != nil {
      fmt.Println("JSON Unmarshal error:", err)
    }
    if len(lineRespData.AccessToken) < 1 {
      fmt.Println(chatKind + " APIアクセストークン取得に失敗しました。")
      fmt.Println("  " + chatKind + " APIアクセストークン取得結果=[", lineRespData.AccessToken, "] アクセストークン取得エラーメッセージ=[", lineRespData.ExpireIn, "]")
    } else {
      fmt.Println(chatKind + " APIアクセストークン取得に成功しました。")

      LinePushMessagePost(chatKind, apiPushMessageUrl, lineRespData.AccessToken, lineUid, message)

    }

  } else {
    fmt.Println(chatKind + " APIアクセストークン取得に失敗しました。")
  }
  fmt.Println("  " + chatKind + " APIアクセストークン取得ステータスコード=[", resp.StatusCode, "] レスポンス内容=[", resp.Status, "]")

  return err
}

///////////////////////////////////////////////////////////////////////////
// LINEへプッシュメッセージ(プッシュメッセージとはLINEメッセージの一種)を投稿する
///////////////////////////////////////////////////////////////////////////
func LinePushMessagePost(chatKind, apiPushMessageUrl, lineAccessToken, lineUid, message string) error {

  // LINEへ投稿するプッシュメッセージリクエストjsonをセット
  jsonStr := `{
    "to": "` + lineUid + `",
    "messages": [
      {
        "type": "text",
        "text": "` + message + `"
      }
    ]
  }`

  req, err := http.NewRequest(
    "POST",
    apiPushMessageUrl,
    bytes.NewBuffer([]byte(jsonStr)),
  )
  if err != nil {
    fmt.Println(err)
    return err
  }

  // Content-Type 設定
  req.Header.Set("Content-Type", "application/json")
  req.Header.Set("Authorization", "Bearer " + lineAccessToken)

  // チャットへメッセージ投稿
  client := &http.Client{}
  resp, err := client.Do(req)
  if err != nil {
    return err
  }

  defer resp.Body.Close()

  // メッセージ投稿結果の表示
  if resp.StatusCode == http.StatusOK {
    fmt.Println(chatKind + "メッセージ投稿に成功しました。")
  } else {
    fmt.Println(chatKind + "メッセージ投稿に失敗しました。")
  }
  fmt.Println("  " + chatKind + "メッセージ投稿ステータスコード=[", resp.StatusCode, "] レスポンス内容=[", resp.Status, "]")
  return err

}

///////////////////////////////////////////////////////////////////////////
// Chatworkへメッセージを投稿する
///////////////////////////////////////////////////////////////////////////
func ChatworkMessagePost(chatKind, apiUrl, apiToken, message string) error {
  values := url.Values{}
  values.Set("body", message)

  req, err := http.NewRequest(
    "POST",
    apiUrl,
    strings.NewReader(values.Encode()),
  )
  if err != nil {
    return err
  }

  // Content-Type 設定
  req.Header.Set("X-ChatWorkToken", apiToken)
  req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

  // チャットへメッセージ投稿
  client := &http.Client{}
  resp, err := client.Do(req)
  if err != nil {
    return err
  }

  defer resp.Body.Close()

  // メッセージ投稿結果の表示
  if resp.StatusCode == http.StatusOK {
    fmt.Println(chatKind + "メッセージ投稿に成功しました。")
  } else {
    fmt.Println(chatKind + "メッセージ投稿に失敗しました。")
  }
  fmt.Println("  " + chatKind + "メッセージ投稿ステータスコード=[", resp.StatusCode, "] レスポンス内容=[", resp.Status, "]")

  return err
}

///////////////////////////////////////////////////////////////////////////
// コマンドライン入力パラメータをチェックする
///////////////////////////////////////////////////////////////////////////
func CheckCliInputParameter() {

  if len(os.Args) != 4 {
    fmt.Println("指定された引数の数が間違っています。")
    fmt.Println("Usage:")

    fmt.Println("[slackへメッセージを投稿する場合]")
    fmt.Println("  export SLACK_API_TOKEN=\"slackのAPIトークンをセットする\"")
    fmt.Println("  ./c2ptcli slack メッセージ投稿先のチャネル名(例:general) \"slackへ投稿したいメッセージ\"\n")

    fmt.Println("[chatworkへメッセージを投稿する場合]")
    fmt.Println("  export CHATWORK_API_TOKEN=\"chatworkのAPIトークンをセットする\"")
    fmt.Println("  ./c2ptcli chatwork メッセージ投稿先のルーム番号 \"chatworkへ投稿したいメッセージ\"\n")

    fmt.Println("[LINEへメッセージを投稿する場合]")
    fmt.Println("  export LINE_CHANNEL_ID=\"LINE Messaging APIのChannel ID文字列をセットする\"")
    fmt.Println("  export LINE_CHANNEL_SECRET=\"LINE Messaging APIのChannel Secret文字列列をセットする\"")
    fmt.Println("  ./c2ptcli line メッセージ投稿先のUID(LINE User Id) \"LINEへ投稿したいプッシュメッセージ\"\n")

    os.Exit(1)
  }

}
///////////////////////////////////////////////////////////////////////////
// main
///////////////////////////////////////////////////////////////////////////
func main() {

  // 入力パラメータのチェック
  CheckCliInputParameter()

  // メッセージを投稿するチャットの種類を取得
  chatKind := os.Args[1]

  // チャットの種類により、メッセージ投稿用のパラメータを生成
  switch chatKind {

    case "slack":

      postChannel := os.Args[2]
      postMessage := os.Args[3]

      apiUrl := "https://slack.com/api/chat.postMessage"
      if len(os.Getenv("SLACK_API_TOKEN")) != 0 {

        apiToken := os.Getenv("SLACK_API_TOKEN")
        SlackMessagePost(chatKind, apiUrl, apiToken, postChannel, postMessage)

      } else {

        fmt.Println(chatKind + "メッセージ投稿用のAPIトークンを環境変数 SLACK_API_TOKEN にセットして下さい。")
        fmt.Println("Linux,Mac系の環境変数設定方法(bashの例):")
        fmt.Println("  export SLACK_API_TOKEN=\"APIトークン文字列\"")
        os.Exit(1)

      }

    case "chatwork":

      postChannel := os.Args[2]
      postMessage := os.Args[3]

      apiUrl := "https://api.chatwork.com/v2/rooms/" + postChannel + "/messages"
      if len(os.Getenv("CHATWORK_API_TOKEN")) != 0 {

        apiToken := os.Getenv("CHATWORK_API_TOKEN")
        ChatworkMessagePost(chatKind, apiUrl, apiToken, postMessage)

      } else {

        fmt.Println(chatKind + "メッセージ投稿用のAPIトークンを環境変数 CHATWORK_API_TOKEN にセットして下さい。")
        fmt.Println("Linux,Mac系の環境変数設定方法(bashの例):")
        fmt.Println("  export CHATWORK_API_TOKEN=\"APIトークン文字列\"")
        os.Exit(1)

      }

    case "line":

      postLineUid := os.Args[2]
      postMessage := os.Args[3]

      apiAuthUrl := "https://api.line.me/v2/oauth/accessToken"
      apiPushMessageUrl := "https://api.line.me/v2/bot/message/push"
      if len(os.Getenv("LINE_CHANNEL_ID")) != 0 && len(os.Getenv("LINE_CHANNEL_SECRET")) != 0 {

        lineChannelId := os.Getenv("LINE_CHANNEL_ID")
        lineChannelSecret := os.Getenv("LINE_CHANNEL_SECRET")
        LineMessagePost(chatKind, apiAuthUrl, apiPushMessageUrl, lineChannelId, lineChannelSecret, postLineUid, postMessage)

      } else {

        fmt.Println(chatKind + "メッセージ投稿用のAPIトークンを環境変数 LINE_CHANNEL_IDとLINE_CHANNEL_SECRET にセットして下さい。")
        fmt.Println("Linux,Mac系の環境変数設定方法(bashの例):")
        fmt.Println("  export LINE_CHANNEL_ID=\"LINE Messaging APIのChannel ID文字列\"")
        fmt.Println("  export LINE_CHANNEL_SECRET=\"LINE Messaging APIのChannel Secret文字列\"")
        os.Exit(1)

      }

    default:
      fmt.Printf("未対応のチャットツールが指定されました。指定されたチャットの種類 = [%s]\n", chatKind)
    
  }

}
```

## (3) Goのソースコードをコンパイルするシェルスクリプトを作成します。

以下のシェルスクリプトを作成します。

```
$ vi go_build.sh 
```

```bash:go_build.sh
#!/bin/sh -x

if [ ! -d ./mac ] ; then
  mkdir mac
fi

if [ ! -d ./linux_amd64 ] ; then
  mkdir linux_amd64
fi

if [ ! -d ./windows_386 ] ; then
  mkdir windows_386
fi

## Mac用コマンドをコンパイル
go build -o mac/c2ptcli c2ptcli.go

## Linux 64bit用コマンドをコンパイル
GOOS=linux GOARCH=amd64 go build -o linux_amd64/c2ptcli c2ptcli.go

## Windows 32bit用コマンドをコンパイル
GOOS=windows GOARCH=386 go build -o windows_386/c2ptcli.exe c2ptcli.go
```

```
$ chmod 755 go_build.sh 
```

```
$ sh -n go_build.sh 
$ 
```

## (4) Goのソースコードをコンパイルします。

```
$ ls -lrta ~/c2ptcli/
total 24
-rw-r--r--   1 **********  staff  6742 12 23 17:57 c2ptcli.go
-rwxr-xr-x   1 **********  staff   482 12 23 20:49 go_build.sh
drwxr-xr-x+ 77 **********  staff  2464 12 23 20:49 ..
drwxr-xr-x   4 **********  staff   128 12 23 20:49 .
$ 
```

```
$ ./go_build.sh 
+ '[' '!' -d ./mac ']'
+ mkdir mac
+ '[' '!' -d ./linux_amd64 ']'
+ mkdir linux_amd64
+ '[' '!' -d ./windows_386 ']'
+ mkdir windows_386
+ go build -o mac/c2ptcli c2ptcli.go
+ GOOS=linux
+ GOARCH=amd64
+ go build -o linux_amd64/c2ptcli c2ptcli.go
+ GOOS=windows
+ GOARCH=386
+ go build -o windows_386/c2ptcli.exe c2ptcli.go
$ 
```

## (5) Goのソースコードがコンパイルされた事を確認します。

```
$ ls -lrta ~/c2ptcli/
total 24
-rw-r--r--   1 **********  staff  6742 12 23 17:57 c2ptcli.go
-rwxr-xr-x   1 **********  staff   482 12 23 20:49 go_build.sh
drwxr-xr-x+ 77 **********  staff  2464 12 23 20:49 ..
drwxr-xr-x   7 **********  staff   224 12 23 20:52 .
drwxr-xr-x   3 **********  staff    96 12 23 20:52 mac
drwxr-xr-x   3 **********  staff    96 12 23 20:52 linux_amd64
drwxr-xr-x   3 **********  staff    96 12 23 20:52 windows_386
$ 
```

```
$ ls -lrta ~/c2ptcli/mac/c2ptcli 
-rwxr-xr-x  1 **********  staff  6318116 12 23 20:52 /Users/**********/c2ptcli/mac/c2ptcli
```

```
$ ls -lrta ~/c2ptcli/linux_amd64/c2ptcli 
-rwxr-xr-x  1 **********  staff  6330727 12 23 20:52 /Users/**********/c2ptcli/linux_amd64/c2ptcli
```

```
$ ls -lrta ~/c2ptcli/windows_386/c2ptcli.exe 
-rwxr-xr-x  1 **********  staff  5330944 12 23 20:52 /Users/**********/c2ptcli/windows_386/c2ptcli.exe
```

Goのソースコードからコンパイルしたコマンドの動作確認(Mac)
===

それでは、コンパイルにより生成されたコマンドをMacで実行してみます。

## (1) Slackへメッセージを投稿します。

・Slackへのメッセージ通知はSlack APIを利用します。

・環境変数にSlack APIトークン(xoxp-〜ではじまるAPIトークン文字列)をセットします。

```
$ export SLACK_API_TOKEN="xoxp-************************************"
$ 
```

・以下のようにコマンドを実行し、Slackへメッセージを投稿します。
　例として、メッセージ投稿先のChannelは「general」であるとします。

```
$ pwd
/Users/**********/c2ptcli
$

$ ~/c2ptcli/mac/c2ptcli slack general "Mac テストメッセージ"
slackメッセージ投稿に成功しました。
  slackメッセージ投稿ステータスコード=[ 200 ] レスポンス内容=[ 200 OK ]
$ 
```

## (2) Chatworkへメッセージを投稿します。

・Chatworkへのメッセージ通知はChatwork APIを利用します。

・環境変数にChatwork APIトークンをセットします。

```
$ export CHATWORK_API_TOKEN="35*******************************"
$ 
```

・以下のようにコマンドを実行し、Chatworkへメッセージを投稿します。
　例として、メッセージ投稿先のルームは「9xxxxxxx」であるとします。

```
$ ~/c2ptcli/mac/c2ptcli chatwork 9xxxxxxx "Mac テストメッセージ"
chatworkメッセージ投稿に成功しました。
  chatworkメッセージ投稿ステータスコード=[ 200 ] レスポンス内容=[ 200 OK ]
$ 
```


## (3) LINEへメッセージを投稿します。

・LINEへのメッセージ通知はLINE Messaging API( https://api.line.me/v2/bot/message/push )を利用しています。

・環境変数にLINE APIトークン(LINE Channel ID 及び LINE Channel Secret)をセットします。

```
$ export LINE_CHANNEL_ID="16********"
$ 
```

```
$ export LINE_CHANNEL_SECRET="e0******************************"
$ 
```

・以下のようにコマンドを実行し、LINEへメッセージを投稿します。
　例として、メッセージ投稿先のLINE UIDは「U2*******************************」であるとします。

```
$ ~/c2ptcli/mac/c2ptcli line U2******************************* "Mac テストメッセージ `date`"
line APIアクセストークン取得に成功しました。
lineメッセージ投稿に成功しました。
  lineメッセージ投稿ステータスコード=[ 200 ] レスポンス内容=[ 200  ]
  line APIアクセストークン取得ステータスコード=[ 200 ] レスポンス内容=[ 200 OK ]
$ 
```

Goのソースコードからコンパイルしたコマンドの動作確認(Windows)
===

コンパイルにより生成されたコマンドをWindows 7(32bit版)で実行してみます。

Windowsでは以下のexe形式のコマンドを利用します。

```
$ ls -lrta ~/c2ptcli/windows_386/c2ptcli.exe 
-rwxr-xr-x  1 **********  staff  5330944 12 23 20:52 /Users/**********/c2ptcli/windows_386/c2ptcli.exe
$ 
```

Macでコンパイルしたexe形式のコマンドをWindowsへ持っていきます。

```
D:\tools>dir c2ptcli.exe

2018/12/23  20:52         5,330,944 c2ptcli.exe
               1 個のファイル           5,330,944 バイト
               0 個のディレクトリ  36,344,451,072 バイトの空き領域

D:\tools>
```

## (1) Slackへメッセージを投稿します。

・Slackへのメッセージ通知はSlack APIを利用します。

・環境変数にSlack APIトークン(xoxp-〜ではじまるAPIトークン文字列)をセットします。

```
D:\tools>setx SLACK_API_TOKEN "xoxp-************************************"

成功: 指定した値は保存されました。
```

・setxコマンドでセットした環境変数を適用する為、Windowsコマンドプロンプトを新たに開いてコマンドを実行します。

・以下のようにコマンドを実行し、Slackへメッセージを投稿します。
　例として、メッセージ投稿先のChannelは「general」であるとします。

```
D:\tools>c2ptcli.exe slack general "Windows テストメッセージ"
slackメッセージ投稿に成功しました。
  slackメッセージ投稿ステータスコード=[ 200 ] レスポンス内容=[ 200 OK ]

D:\tools>
```

## (2) Chatworkへメッセージを投稿します。

・Chatworkへのメッセージ通知はChatwork APIを利用します。

・環境変数にChatwork APIトークンをセットします。

```
D:\tools>setx CHATWORK_API_TOKEN "35*******************************"

成功: 指定した値は保存されました。
```

・setxコマンドでセットした環境変数を適用する為、Windowsコマンドプロンプトを新たに開いてコマンドを実行します。

・以下のようにコマンドを実行し、Chatworkへメッセージを投稿します。
　例として、メッセージ投稿先のルームは「9xxxxxxx」であるとします。

```
D:\tools>c2ptcli.exe chatwork 9xxxxxxx "Windows テストメッセージ"
chatworkメッセージ投稿に成功しました。
  chatworkメッセージ投稿ステータスコード=[ 200 ] レスポンス内容=[ 200 OK ]

D:\tools>
```


## (3) LINEへメッセージを投稿します。

・LINEへのメッセージ通知はLINE Messaging APIを利用します。

・環境変数にLINE APIトークン(LINE Channel ID 及び LINE Channel Secret)をセットします。

```
D:\tools>setx LINE_CHANNEL_ID "16********"

成功: 指定した値は保存されました。

D:\tools>
```

```
D:\tools>setx LINE_CHANNEL_SECRET "e0******************************"

成功: 指定した値は保存されました。

D:\tools>
```

・setxコマンドでセットした環境変数を適用する為、Windowsコマンドプロンプトを新たに開いてコマンドを実行します。

・以下のようにコマンドを実行し、LINEへメッセージを投稿します。
　例として、メッセージ投稿先のLINE UIDは「U2*******************************」であるとします。

```
D:\tools>c2ptcli.exe line U2******************************* "Windows テストメッセージ"
line APIアクセストークン取得に成功しました。
lineメッセージ投稿に成功しました。
  lineメッセージ投稿ステータスコード=[ 200 ] レスポンス内容=[ 200  ]
  line APIアクセストークン取得ステータスコード=[ 200 ] レスポンス内容=[ 200 OK ]

D:\tools>
```

Goのソースコードからコンパイルしたコマンドの動作確認(Linux)
===

コンパイルにより生成されたコマンドをAmazon Linux 2で実行してみます。

## (1) Slackへメッセージを投稿します。

・Slackへのメッセージ通知はSlack APIを利用します。

・環境変数にSlack APIトークン(xoxp-〜ではじまるAPIトークン文字列)をセットします。

```
[ec2-user@example-linux-server ~]$ export SLACK_API_TOKEN="xoxp-************************************"
[ec2-user@example-linux-server ~]$
```

・以下のようにコマンドを実行し、Slackへメッセージを投稿します。
　例として、メッセージ投稿先のChannelは「general」であるとします。

```
[ec2-user@example-linux-server ~]$ ./c2ptcli slack general "Linux テストメッセージ"
slackメッセージ投稿に成功しました。
  slackメッセージ投稿ステータスコード=[ 200 ] レスポンス内容=[ 200 OK ]
[ec2-user@example-linux-server ~]$ 
```

## (2) Chatworkへメッセージを投稿します。

・Chatworkへのメッセージ通知はChatwork APIを利用します。

・環境変数にChatwork APIトークンをセットします。

```
[ec2-user@example-linux-server ~]$ export CHATWORK_API_TOKEN="35*******************************"
[ec2-user@example-linux-server ~]$
```

・以下のようにコマンドを実行し、Chatworkへメッセージを投稿します。
　例として、メッセージ投稿先のルームは「9xxxxxxx」であるとします。

```
[ec2-user@example-linux-server ~]$ ./c2ptcli chatwork 9xxxxxxx "Linux テストメッセージ"
chatworkメッセージ投稿に成功しました。
  chatworkメッセージ投稿ステータスコード=[ 200 ] レスポンス内容=[ 200 OK ]
[ec2-user@example-linux-server ~]$ 
```

## (3) LINEへメッセージを投稿します。

・LINEへのメッセージ通知はLINE Messaging APIを利用します。

・環境変数にLINE APIトークン(LINE Channel ID 及び LINE Channel Secret)をセットします。

```
[ec2-user@example-php-server ~]$ export LINE_CHANNEL_ID="16********"
[ec2-user@example-php-server ~]$
```

```
[ec2-user@example-php-server ~]$ export LINE_CHANNEL_SECRET="e0******************************"
[ec2-user@example-php-server ~]$
```

・以下のようにコマンドを実行し、LINEへメッセージを投稿します。
　例として、メッセージ投稿先のLINE UIDは「U2*******************************」であるとします。

```
[ec2-user@example-php-server ~]$ ./c2ptcli line U2******************************* "Linux テストメッセージ"
line APIアクセストークン取得に成功しました。
lineメッセージ投稿に成功しました。
  lineメッセージ投稿ステータスコード=[ 200 ] レスポンス内容=[ 200  ]
  line APIアクセストークン取得ステータスコード=[ 200 ] レスポンス内容=[ 200 OK ]
[ec2-user@example-php-server ~]$ 
```

最後に
===

WindowsやMacといった様々な環境で動作するコマンドを作成していく際、Go言語はとても便利ですね。

まだ作ったばかりのコマンドで、他にもやりたいこと(ソースのリファクタリング、Salesforceへのメッセージ投稿機能追加等)がございますので、コマンドは引き続きブラッシュアップしていきたいと思います。

**明日の <a href="https://qiita.com/advent-calendar/2018/lifull">LIFULL Advent Calendar 2018</a> ですが、IoTやデバイスマスターの @Sam さんにご担当頂きます。ご期待下さい！**

最後に、今回の記事がみなさまにとって、何らかの参考になれば幸いです。ありがとうございました。

以上になります。