Skip to content

Instantly share code, notes, and snippets.

@na0AaooQ
Last active December 24, 2018 17:06
Show Gist options
  • Save na0AaooQ/ca3e1cd3dd6755eeb711eed1d13bb61f to your computer and use it in GitHub Desktop.
Save na0AaooQ/ca3e1cd3dd6755eeb711eed1d13bb61f to your computer and use it in GitHub Desktop.
Go言語でSlack,Chatwork,LINEへチャットメッセージを投稿するコマンド作成 (Windows,Linux,Macに対応したコマンドを作成する) ref: https://qiita.com/na0AaooQ/items/7f937ff1fd938eb89b6a
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)
}
}
$ ~/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へ投稿したいプッシュメッセージ"
$
[ec2-user@example-linux-server ~]$ ./c2ptcli slack general "Linux テストメッセージ"
slackメッセージ投稿に成功しました。
slackメッセージ投稿ステータスコード=[ 200 ] レスポンス内容=[ 200 OK ]
[ec2-user@example-linux-server ~]$
$ vi go_build.sh
$ chmod 755 go_build.sh
$ chmod 755 go_build.sh
$ sh -n go_build.sh
$
$ 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
$
$ 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
[ec2-user@example-linux-server ~]$ ./c2ptcli chatwork 9xxxxxxx "Linux テストメッセージ"
chatworkメッセージ投稿に成功しました。
chatworkメッセージ投稿ステータスコード=[ 200 ] レスポンス内容=[ 200 OK ]
[ec2-user@example-linux-server ~]$
$ export SLACK_API_TOKEN="xoxp-************************************"
$
$ pwd
/Users/**********/c2ptcli
$
$ ~/c2ptcli/mac/c2ptcli slack general "Mac テストメッセージ"
slackメッセージ投稿に成功しました。
slackメッセージ投稿ステータスコード=[ 200 ] レスポンス内容=[ 200 OK ]
$
$ export CHATWORK_API_TOKEN="35*******************************"
$
$ ~/c2ptcli/mac/c2ptcli chatwork 9xxxxxxx "Mac テストメッセージ"
chatworkメッセージ投稿に成功しました。
chatworkメッセージ投稿ステータスコード=[ 200 ] レスポンス内容=[ 200 OK ]
$
$ export LINE_CHANNEL_ID="16********"
$
$ export LINE_CHANNEL_SECRET="e0******************************"
$
$ ~/c2ptcli/mac/c2ptcli line U2******************************* "Mac テストメッセージ `date`"
line APIアクセストークン取得に成功しました。
lineメッセージ投稿に成功しました。
lineメッセージ投稿ステータスコード=[ 200 ] レスポンス内容=[ 200 ]
line APIアクセストークン取得ステータスコード=[ 200 ] レスポンス内容=[ 200 OK ]
$
$ ls -lrta ~/c2ptcli/windows_386/c2ptcli.exe
-rwxr-xr-x 1 ********** staff 5330944 12 23 20:52 /Users/**********/c2ptcli/windows_386/c2ptcli.exe
$
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>
D:\tools>setx SLACK_API_TOKEN "xoxp-************************************"
成功: 指定した値は保存されました。
[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 ~]$
D:\tools>c2ptcli.exe slack general "Windows テストメッセージ"
slackメッセージ投稿に成功しました。
slackメッセージ投稿ステータスコード=[ 200 ] レスポンス内容=[ 200 OK ]
D:\tools>
D:\tools>setx CHATWORK_API_TOKEN "35*******************************"
成功: 指定した値は保存されました。
D:\tools>c2ptcli.exe chatwork 9xxxxxxx "Windows テストメッセージ"
chatworkメッセージ投稿に成功しました。
chatworkメッセージ投稿ステータスコード=[ 200 ] レスポンス内容=[ 200 OK ]
D:\tools>
D:\tools>setx LINE_CHANNEL_ID "16********"
成功: 指定した値は保存されました。
D:\tools>
D:\tools>setx LINE_CHANNEL_SECRET "e0******************************"
成功: 指定した値は保存されました。
D:\tools>
D:\tools>c2ptcli.exe line U2******************************* "Windows テストメッセージ"
line APIアクセストークン取得に成功しました。
lineメッセージ投稿に成功しました。
lineメッセージ投稿ステータスコード=[ 200 ] レスポンス内容=[ 200 ]
line APIアクセストークン取得ステータスコード=[ 200 ] レスポンス内容=[ 200 OK ]
D:\tools>
[ec2-user@example-linux-server ~]$ export SLACK_API_TOKEN="xoxp-************************************"
[ec2-user@example-linux-server ~]$
[ec2-user@example-linux-server ~]$ ./c2ptcli slack general "Linux テストメッセージ"
slackメッセージ投稿に成功しました。
slackメッセージ投稿ステータスコード=[ 200 ] レスポンス内容=[ 200 OK ]
[ec2-user@example-linux-server ~]$
[ec2-user@example-linux-server ~]$ export CHATWORK_API_TOKEN="35*******************************"
[ec2-user@example-linux-server ~]$
[ec2-user@example-linux-server ~]$ ./c2ptcli chatwork 9xxxxxxx "Linux テストメッセージ"
chatworkメッセージ投稿に成功しました。
chatworkメッセージ投稿ステータスコード=[ 200 ] レスポンス内容=[ 200 OK ]
[ec2-user@example-linux-server ~]$
$ brew install go
[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 ~]$
[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 ~]$
$ which go
/usr/local/bin/go
$
$ mkdir ~/c2ptcli
$
$ cd ~/c2ptcli/
$ vi c2ptcli.go
$ vi 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment