[Go]Go言語入門~Twitter Botを作ってみよう~

この記事は約11分で読めます。

今回はDay7でGo言語入門~twitter Botを作ってみよう~です。

前回は

Go言語 :簡単な AI を作ってみよう~
今回はGo言語入門~簡単なAI( ニューラルネットワーク )~を作ってみようです。 最初の AI は煽りすぎました...

でした。この応用は次回に持ち越して、今回は、Twitter Botを作ってみます。

 

制作物

  • HelloWorldを呟く
  • 動画を添付する
  • ConoHaVPSを使って定期実行する

事前登録

Twitter Bot作るためにTwitter API利用申請する必要があります。

TwitterのDeveloper登録します。

Twitter API 登録 (アカウント申請方法) から承認されるまでの手順まとめ

 

を参考に登録して、

  • コンシューマキー
  • コンシューマーシークレットキー
  • アクセストークン
  • アクセスシークレットトークン

をもらいます。

これで準備完了です。

HelloWorldを呟く

package main

import (
	"github.com/ChimeraCoder/anaconda"

)

func main() {
	anaconda.SetConsumerKey("CONSUMER_KEY")
	anaconda.SetConsumerSecret("CONSUMER_SECRET")
	api := anaconda.NewTwitterApi("ACCESS_TOKEN", "ACCESS_TOKEN_SECRET")
        api.PostTweet("hello world", nil)
}

はい、かなり簡単に記述できますね。

もし仮に、ツイートされていなければ、キーが間違っていないかどうか、また権限を見直してください。Read-onlyとかなっていないか確認してみてください。

パッケージ

“github.com/ChimeraCoder/anaconda”…twiiterAPIを用いてtwiiterを扱う外部パッケージ

動画を投稿する

短い動画を投稿

最初は140秒動画には対応せず,30秒以内かつ5MB以内の動画のみになります。

Twitter developを見ながら作成して行きます。

動画投稿の操作は3つあります。

  1. INIT
  2. APPEND
  3. FINALIZE そしてツイートします。

1.INIT
これをするには、画像のファイルサイズとメディアタイプを引数としています。
なので、画像のファイルサイズとメディアタイプ(ex video/mp4)を設定します。

2.APPEND
base64エンコードした動画ファイルと、INITで返ってきたMEDIAIDを引数としています。

ファイルサイズは5MB以上の際はここを複数回行うことで実現できます。

3.FINALIZE
MediaIDを引数としています。
最後に画像をツイートします。

 package main

import (
	"encoding/base64"
	"io/ioutil"
	"net/url"
	"os"

	"github.com/ChimeraCoder/anaconda"
)

func main() {
	anaconda.SetConsumerKey("CONSUMER_KEY")
	anaconda.SetConsumerSecret("CONSUMER_SECRET")
	api := anaconda.NewTwitterApi("ACCESS_TOKEN","ACCESS_TOKEN_SECRET")
	//*************INIT***************//
        fi, err := os.Open("動画ファイル")
	if err != nil {
		panic(err)
	}
	defer fi.Close()

	//ファイルサイズを計算
	status, _ := fi.Stat()
	size := status.Size()
	if err != nil {
		panic(err)
	}

	//動画ファイルをbyte配列に変換する
	byteMedia, err := ioutil.ReadAll(fi)
	if err != nil {
		panic(err)
	}

	//base64エンコードする
	base64Media := base64.StdEncoding.EncodeToString(byteMedia)

	chunkedMedia, err := api.UploadVideoInit(int(size), "video/mp4")
	if err != nil {
		panic(err)
	}
	//*************APPEND***************//
	err = api.UploadVideoAppend(chunkedMedia.MediaIDString, 0, base64Media)
	if err != nil {
		panic(err)
	}
	//*************FINALIZE***************//
	video, err := api.UploadVideoFinalize(chunkedMedia.MediaIDString)
	if err != nil {
		panic(err)
	}
	//*************ツイート作業***************//
	params := url.Values{}
	params.Add("media_ids", video.MediaIDString)
	if _, err = api.PostTweet("hello world", params); err != nil {
		panic(err)
	}
}

実行結果


スポンサーリンク

5MB以上の動画を投稿

これに関しては、プルリクがまだマージされていないので個別に設定する必要があります。

vendorを使っている人は、直接anaconda/media.goを開き

type StatusMedia struct {
	MediaID          int64  `json:"media_id"`
	MediaIDString    string `json:"media_id_string"`
	MediaKey         string `json:"media_key"`
	ExpiresAfterSecs int    `json:"expires_after_secs"`
	ProcessingInfo   struct {
		State           string `json:"state"`
		CheckAfterSecs  int    `json:"check_after_secs"`
		ProgressPercent int    `json:"progress_percent"`
	} `json:"processing_info"`
}
 func (a TwitterApi) UploadVideoStatus(mediaIdString string) (videoMedia StatusMedia, err error) {
	v := url.Values{}
	v.Set("command", "STATUS")
	v.Set("media_id", mediaIdString)

	var mediaResponse StatusMedia

	response_ch := make(chan response)
	a.queryQueue <- query{UploadBaseUrl + "/media/upload.json", v, &mediaResponse, _GET, response_ch}
	return mediaResponse, (<-response_ch).err
}

これを追記します。

そして、mainのコードには

package main

import (
	"encoding/base64"
	"io/ioutil"
	"net/url"
	"os"
	"time"

	"github.com/ChimeraCoder/anaconda"
)

func main() {
	anaconda.SetConsumerKey("CONSUMER_KEY")
	anaconda.SetConsumerSecret("CONSUMER_SECRET")
        api := anaconda.NewTwitterApi("ACCESS_TOKEN", "ACCESS_TOKEN_SECRET")
	fi, err := os.Open("動画ファイル名")
	if err != nil {
		panic(err)
	}
	defer fi.Close()

	//ファイルサイズを計算
	status, _ := fi.Stat()
	size := int(status.Size())
	if err != nil {
		panic(err)
	}

	//動画ファイルをbyte配列に変換する
	byteMedia, err := ioutil.ReadAll(fi)
	if err != nil {
		panic(err)
	}

	chunkedMedia, err := api.UploadVideoInit(int(size), "video/mp4")
	if err != nil {
		panic(err)
	}
	//The base64-encoded chunk of media file. It must be <= 5 MB
	chunkSize := 5 * 1024 * 1024
	index := 0
	for i := 0; i < size; i += chunkSize {
		var data string
		if (size-i)/chunkSize > 0 {
			data = base64.StdEncoding.EncodeToString(byteMedia[i : i+chunkSize])
		} else {
			data = base64.StdEncoding.EncodeToString(byteMedia[i:])
		}
		if err = api.UploadVideoAppend(chunkedMedia.MediaIDString, index, data); err != nil {
			panic(err)
		}
		index++
	}

	video, err := api.UploadVideoFinalize(chunkedMedia.MediaIDString)
	if err != nil {
		panic(err)
	}

	for {
		videos, err := api.UploadVideoStatus(chunkedMedia.MediaIDString)
		if err != nil {
			panic(err)
		}
		if videos.ProcessingInfo.State == "succeeded" {
			break
		}
		time.Sleep(time.Duration(videos.ProcessingInfo.CheckAfterSecs))
	}

	params := url.Values{}
	params.Add("media_ids", video.MediaIDString)
	if _, err := api.PostTweet("text", params); err != nil {
		panic(err)
	}
}

このようにAPPEND部分と、最後に動画アップロードする処理が必要になります。

肝は5MB以下でしか送信できないため、チャンクに分けて送信しなければいけないところです。
そして送信毎にCheckAfterSecsがレスポンスで返ってくるので、その時間だけsleepしProcessingInfo.Statesucceededになるまで待つ処理が必要です。

 

ConoHaVPSで定期実行する

定期的に自動ツイートをします。

ConoHaVPS上で定期実行には2通りあります。

  1. Goプログラム内で定期実行する
  2. Cronタスクを用いる(osのコマンドでGoのプログラムを定期実行)

Goプログラム内で定期実行する

package main

import (
	"github.com/ChimeraCoder/anaconda"
	"github.com/carlescere/scheduler"
)

func main() {
   anaconda.SetConsumerKey("CONSUMER_KEY")
   anaconda.SetConsumerSecret("CONSUMER_SECRET")
   api := anaconda.NewTwitterApi("ACCESS_TOKEN", "ACCESS_TOKEN_SECRET")
   api.PostTweet("init",nil)
   job := func() {
       api.PostTweet("おはよう by Go", nil)
   }
   scheduler.Every(5).Seconds().Run(job)
   for{}
}

パッケージ

“github.com/carlescere/scheduler”…スケジュールでメインのgoroutineが起動している間、定期実行してくれる

注意

twitterAPIでは同じ投稿を拒否されるので、違う文章にしましょう

Cronタスクで実行する

VPSサーバ(CentOS)上で

$ yum install cronie

インストール後

$ crontab -e

で開いて下記を書き込み

*/5 * * * *  run.sh

保存します。

run.shにはgoのプログラムを起動するコマンドを書いておきます。

cronについて詳しく知りたい場合は、この記事を参考にしてください。

まとめ

今回はtwitter botを作成してみました。

botは様々な使い方(タイムラインやstreamAPI…)があるので、是非色々試してください!

タイトルとURLをコピーしました