かまたま日記3

プログラミングメイン、たまに日常

GrailsでTwitterBotを作る(アプリケーション実装編)

TwitterBotを作ってみました。(@SuperFamicomBot)

開発の動機

  • Grailsを使って何かアプリケーションをリリースまで作ってみたかった
  • スーファミ世代の懐古厨である私の自己満足(笑)

必要な仕様

  • つぶやく対象ソフトの一覧管理
  • 定期的に処理を行うcron的な処理
  • Twitterにツイートする処理

つぶやく対象タイトル管理

CSVファイルを用意して毎回起動時にBootStrapで組み込みH2Databaseに突っ込むようにしました。
元データはスーパーファミコンのゲームタイトル一覧 - Wikipediaから拝借。
発売日と値段が無かったものに関しては個別にググって補完。
【完成したファイル】: software.csv

BootStrap.groovyでCSVファイルを読み込むためにクラスパスを取得する必要があったのでgrailsApplication経由で取得しました。

import com.kamatama41.sfc.Software

class BootStrap {
	def grailsApplication

	def init = { servletContext ->
		if (Software.count == 0) {
			def text = grailsApplication.parentContext.getResource("classpath:data/software.csv").inputStream.text
			text.eachLine { csv ->
				- 略 -
			}
		}
	}
}

必須ではなかったですが、練習がてら普通のページも作っておくかということで作ったつぶやくタイトル一覧のページTwitter Bootstrap Pluginを利用しました。おしゃれで今風なUIが簡単にできていいですねー。

定期的に処理を行うcron的な処理

Quartz pluginを使いました。
プラグインインストール後に以下のコマンドで新規のJobを作ります。

grails create-job com.kamatama41.sfc.TwitterBotJob

grails-app/jobsディレクトリ配下に指定したクラスが作られます。
スケジュール設定はtriggersブロック内で指定するようです。今回は2時間おきの実行なので以下のように指定しました。

package com.kamatama41.sfc

class TwitterBotJob {

	static triggers = {
		simple repeatInterval: 7200000L // execute job once in 2 hours
	}

	def execute() {
		- 略 -
	}
}

Twitterにツイートする処理

Twitter4Jを使いました、updateStatusメソッドを使っています。
consumerKeyとかconsumerSecretをコードに埋め込まないため、リソースプロパティと環境変数を利用することにしました。
ローカル環境は環境変数(env),本番環境はリソースプロパティを使っています。

TwitterService.groovy
package com.kamatama41.sfc

import org.slf4j.LoggerFactory
import twitter4j.Twitter
import twitter4j.TwitterFactory
import twitter4j.auth.AccessToken

class TwitterService {
	private static def logger = LoggerFactory.getLogger(TwitterService)
	private final Twitter twitter

	TwitterService(config) {
		def singleton = TwitterFactory.singleton
		singleton.setOAuthConsumer(config.consumerKey, config.consumerSecret)
		singleton.setOAuthAccessToken(new AccessToken(config.token, config.tokenSecret))
		twitter = singleton
	}

	def post(String message) {
		twitter.updateStatus(message)
		logger.info("message posted. (${message})")
	}

}
Config.groovy(一部)
environments {
	development {
		createTwitterConfig(System.getenv())
	}
	production {
		createTwitterConfig(System.getProperties())
	}
}
private def createTwitterConfig(configSource) {
	twitter.consumerKey = configSource['TWITTER_CONSUMER_KEY']
	twitter.consumerSecret = configSource['TWITTER_CONSUMER_SECRET']
	twitter.token = configSource['TWITTER_TOKEN']
	twitter.tokenSecret = configSource['TWITTER_TOKEN_SECRET']
}

resources.groovy

import com.kamatama41.sfc.TwitterService

// Place your Spring DSL code here
beans = {
	twitterService(TwitterService, grailsApplication.config.twitter)
}

リリース編に続く。。。