Create a gist now

Instantly share code, notes, and snippets.

Play2.0でATNDのイベントサーチAPIを使うクラス (mutableな変数を極力使わないver. case classのcopyを使ってちょっとスッキリ)
package com.github.daiksy.play2.ATND
import play.api.libs.ws.WS
import collection.mutable.ListBuffer
import play.api.libs.json.JsValue
/**
* ATNDのイベントを検索し、取得する。
*
* https://gist.github.com/2585850 を
* case classのcopyメソッドを使ってちょびっとスッキリ.
*
* ・使い方
* メソッドチェーンで検索条件を指定し、executeを実行する。
*
* ex) TwitterIDに"daiksy"を指定して結果を15件取得する場合
* import com.github.daiksy.play2.ATND.EventSearch.searcher
* val ret = searcher.twitterId("daiksy").count(15).execute
*
* 取得結果は、取得件数、対象イベントの総件数、イベント詳細[List]で取得されます。
*
* ret.resultReturned //イベント件数
* ret.resultAvailable // 対象の総イベント件数
* ret.events //イベントの詳細
*
* ex) 取得してきたイベントのタイトルを抽出する場合。
* ret.events.map(_.title)
*
* 取得されるイベントデータの項目はATND APIのリファレンスに準じています。
* http://api.atnd.org/#events-response
*
*/
object EventSearch {
private case class Searcher(
_eventId: Option[String],
_keywordAnd: Option[String],
_keywordOr: Option[String],
_ym: Option[String],
_ymd: Option[String],
_userId: Option[String],
_nickname: Option[String],
_twitterId: Option[String],
_ownerId: Option[String],
_ownerNickname: Option[String],
_ownerTwitterId: Option[String],
_start: Option[Int],
_count: Option[Int]
) {
/** 検索結果を返却するためのcase class */
case class EventSearchResult(
/** 実際に取得したイベントデータの件数 */
resultReturned: Int,
/** 指定した条件で存在するイベントデータの総件数 */
resultAvailable: Int,
/** 取得したイベントデータ */
events: List[Events]
)
/** イベントの詳細データ */
case class Events(
/** イベントID */
eventId: Int,
/** タイトル */
title: String,
/** キャッチ */
catchCopy: Option[String],
/** 概要 */
description: Option[String],
/** ATNDのURL */
eventUrl: Option[String],
/** イベント開始日時 */
startedAt: Option[String],
/** イベント終了日時 */
endedAt: Option[String],
/** 参考URL */
url: Option[String],
/** 定員 */
limit: Option[Int],
/** 開催場所 */
address: Option[String],
/** 開催会場 */
place: Option[String],
/** 開催会場の緯度 */
lat: Option[String],
/** 開催会場の軽度 */
lon: Option[String],
/** 主催者のID */
ownerId: Option[Int],
/** 主催者のニックネーム */
ownerNickname: Option[String],
/** 主催者のTwitterId */
ownerTwitterId: Option[String],
/** 参加者 */
accepted: Option[Int],
/** 補欠者 */
waiting: Option[Int],
/** 更新日時 */
updatedAt: Option[String]
)
/**
* イベント毎に割り当てられた番号で検索します。複数指定可能です(カンマ区切り)
*/
def eventId(value: String) = this.copy(_eventId = Some(value))
/**
* イベントのタイトル、キャッチ、概要、住所をAND条件部分一致で検索します。複数指定可能です(カンマ区切り)
*/
def keywordAnd(value: String) = this.copy(_keywordAnd = Some(value))
/**
* イベントのタイトル、キャッチ、概要、住所をOR条件部分一致で検索します。複数指定可能です(カンマ区切り)
*/
def keywordOr(value: String) = this.copy(_keywordOr = Some(value))
/**
* 指定した年月に開催されているイベントを検索します。複数指定可能です(カンマ区切り)
* ex) 201204
*/
def ym(value: String) = this.copy(_ym = Some(value))
/**
* 指定した年月日に開催されているイベントを検索します。複数指定可能です(カンマ区切り)
* ex) 20120501
*/
def ymd(value: String) = this.copy(_ymd = Some(value))
/**
* 指定したユーザIDのユーザが参加しているイベントを検索します。複数指定可能です(カンマ区切り)
*/
def userId(value: String) = this.copy(_userId = Some(value))
/**
* 指定したニックネームのユーザが参加しているイベントを検索します。複数指定可能です(カンマ区切り)
*/
def nickname(value: String) = this.copy(_nickname = Some(value))
/**
* 指定したTwitter IDのユーザが参加しているイベントを検索します。複数指定可能です(カンマ区切り)
*/
def twitterId(value: String) = this.copy(_twitterId = Some(value))
/**
* 指定したユーザIDのユーザが主催しているイベントを検索します。複数指定可能です(カンマ区切り)
*/
def ownerId(value: String) = this.copy(_ownerId = Some(value))
/**
* 指定したニックネームのユーザが主催しているイベントを検索します。複数指定可能です(カンマ区切り)
*/
def ownerNickname(value: String) = this.copy(_ownerNickname = Some(value))
/**
* 指定したtwitter IDのユーザが主催しているイベントを検索します。複数指定可能です(カンマ区切り)
*/
def ownerTwitterId(value: String) = this.copy(_ownerTwitterId = Some(value))
/**
* 検索結果の何件目から出力するかを指定します
* ※初期値:1
*/
def start(value: Int) = this.copy(_start = Some(value))
/**
* 検索結果の最大出力データ数を指定します
* ※初期値:10, 最小値:1, 最大値:100
*/
def count(value: Int) = this.copy(_count = Some(value))
/** 検索実行 */
def execute = {
requestEventSearchApi
}
/** URLパラメータを組み立てて検索APIをコールし、結果をcase classにセットして返却するよ。 */
private def requestEventSearchApi = {
val apiUrl = "http://api.atnd.org/events/"
val paramBuilder = new ListBuffer[String]
_eventId.foreach(_.split(",").foreach(paramBuilder += "event_id=" + _))
_keywordAnd.foreach(_.split(",").foreach(paramBuilder += "keyword=" + _))
_keywordOr.foreach(_.split(",").foreach(paramBuilder += "keyword_or=" + _))
_ym.foreach(_.split(",").foreach(paramBuilder += "ym=" + _))
_ymd.foreach(_.split(",").foreach(paramBuilder += "ymd=" + _))
_userId.foreach(_.split(",").foreach(paramBuilder += "user_id=" + _))
_nickname.foreach(_.split(",").foreach(paramBuilder += "nickname=" + _))
_twitterId.foreach(_.split(",").foreach(paramBuilder += "twitter_id=" + _))
_ownerId.foreach(_.split(",").foreach(paramBuilder += "owner_id=" + _))
_ownerNickname.foreach(_.split(",").foreach(paramBuilder += "owner_nickname=" + _))
_ownerTwitterId.foreach(_.split(",").foreach(paramBuilder += "owner_twitter_id=" + _))
_start.foreach(paramBuilder += "start=" + _.toString)
_count.foreach(paramBuilder += "count=" + _.toString)
paramBuilder += "format=json"
val urlParam = paramBuilder.result.mkString("&")
val url = if (urlParam != "") {
apiUrl + "?" + urlParam
} else {
apiUrl
}
val ret = WS.url(url).get().value.get.json
EventSearchResult(
(ret \ "results_returned").as[Int],
(ret \ "results_available").as[Int],
(ret \ "events").asOpt[List[JsValue]].getOrElse(Nil).map { e =>
Events(
(e \ "event_id").as[Int],
(e \ "title").as[String],
(e \ "catch").asOpt[String],
(e \ "description").asOpt[String],
(e \ "event_url").asOpt[String],
(e \ "started_at").asOpt[String],
(e \ "ended_at").asOpt[String],
(e \ "url").asOpt[String],
(e \ "limit").asOpt[Int],
(e \ "address").asOpt[String],
(e \ "place").asOpt[String],
(e \ "lat").asOpt[String],
(e \ "lon").asOpt[String],
(e \ "owner_id").asOpt[Int],
(e \ "owner_nickname").asOpt[String],
(e \ "owner_twitter_id").asOpt[String],
(e \ "accepted").asOpt[Int],
(e \ "waiting").asOpt[Int],
(e \ "updated_at").asOpt[String]
)
}
)
}
}
val searcher = Searcher(None, None, None, None, None, None, None, None, None, None, None, None, None)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment