ここしばらく、foursquare APIの勉強がてら、Google Maps APIと組み合わせごにょごにょやってました。やはり、foursquareは地図と組み合わせると楽しいですね。
とりあえず、今後もう少しデザイン的な部分を見直したり、機能を増やしていってちょっとしたサービスに出来たらなと思っています。
サイト名は仮ですが。
4sq map : http://labs.s-koichi.info/mashup/4sq/checkinmap.html
こんな感じで、フレンドのチェックイン情報がGoogleマップの地図上に表示されます。
まず、foursquare APIの参考にしたのがこちらの日本語訳です。
まだまだ使ってないAPIがあるので、いろいろ試してみたいですね。あと、登録系のAPIは今回つかってないです。
ちなみに、foursquareのOAuthアプリ申請はこちらから出来ます。ちょっと、最初探すのに手間取ってしまいました。
あと、Google Maps APIはこちらの日本語訳と本家のドキュメントを参照しました。
foursquqreのAPIを使っている部分は、phpでOAuth認証をさせています。先日のiTunes2Twitterで使ったクラスをfoursqueare用のサブクラスを作っています。スーパークラスは、先日のエントリーと同じです。
<?php
require_once 'OAuthProxy.class.php';
/**
* fourSquare用のクラス
*
*/
class FourSquareOAuthProxy extends OAuthProxy
{
protected $request_token_url = 'http://foursquare.com/oauth/request_token';
protected $access_token_url = 'http://foursquare.com/oauth/access_token';
protected $oauth_url = 'http://foursquare.com/oauth/authorize';
public function requestMethod($action, $param, $callback)
{
try {
$this->init();
if($action == "friends") {
$response = $this->consumer->sendRequest("http://api.foursquare.com/v1/friends.json",
array(), "GET");
if($response->getStatus() != 200) {
$this->error(new Exception($response->getBody(), $response->getStatus()), $callback);
}
else {
$this->printResult($response->getBody(), $callback);
}
}
else if($action == "user") {
$response = $this->consumer->sendRequest("http://api.foursquare.com/v1/user.json",
array('uid' => $param["id"]), "GET");
$this->printResult($response->getBody(), $callback);
}
else if($action == "checkins") {
$response = $this->consumer->sendRequest("http://api.foursquare.com/v1/checkins.json",
$param, "GET");
$this->printResult($response->getBody(), $callback);
}
else if($action == "venues") {
$response = $this->consumer->sendRequest("http://api.foursquare.com/v1/venues.json",
$param, "GET");
$this->printResult($response->getBody(), $callback);
}
else if($action == "tips") {
$response = $this->consumer->sendRequest("http://api.foursquare.com/v1/tips.json",
$param, "GET");
$this->printResult($response->getBody(), $callback);
}
else if($action == "findfriends_bytwitter") {
$response = $this->consumer->sendRequest("http://api.foursquare.com/v1/findfriends/bytwitter.json",
$param, "GET");
$this->printResult($response->getBody(), $callback);
}
}
catch (Exception $e) {
$this->error($e, $callback);
}
}
private function init()
{
//アクセストークンを設定する。
$this->consumer->setToken($_SESSION['access_token']);
$this->consumer->setTokenSecret($_SESSION['access_token_secret']);
}
protected function checkAuth($e)
{
$msg = $e->getMessage();
return ($msg == "unauthorized");
}
}
?>
このクラスをつかったproxyのソースです。
4sqproxy.php
<?php
require_once 'FourSquareOAuthProxy.php';
$consumer_key = 'あなたのCONSUMER_KEY';
$consumer_secret = 'あなたのCONSUMER_SECRET';
session_name('4sq_proxy');
session_start();
if(isset($_REQUEST['pushback'])) {
$_SESSION['pushback'] = $_REQUEST['pushback'];
}
$callback = NULL;
if(isset($_GET['callback'])) {
$callback = $_GET['callback'];
}
$oauthproxy = new FourSquareOAuthProxy($consumer_key, $consumer_secret,
'http://labs.s-koichi.info/oauthproxy/4sqproxy.php');
if(isset($_GET['oauth_verifier'])) { // 認証後に、callback urlできたとき
$oauthproxy->receiveCallback($_GET['oauth_verifier'], $callback);
}
else if(isset($_SESSION['access_token']) &&
isset($_SESSION['access_token_secret'])) { // access_tokenがもうあるとき。
$action = NULL;
if(isset($_REQUEST['action'])) {
$action = $_REQUEST['action'];
}
$param;
foreach ($_REQUEST as $key => $value) {
$param[$key] = $value;
}
$oauthproxy->requestMethod($action, $param, $callback);
}
else { // これから認証。
unset($_SESSION['access_token']);
unset($_SESSION['access_token_secret']);
$oauthproxy->requestAuth($callback);
}
?>
このproxyを使ってjavascript経由で、いろいろな情報を取得してます。主なところだけ載せると、こんな感じです。
// proxyのURL
var baseurl = "http://labs.s-koichi.info/oauthproxy/4sqproxy.php";
// google mapの地図オブジェクト
var map;
// 地図のオプション情報
var mapOptions;
// マーカーの情報
var markers = {};
// ログインユーザーの情報
var owner;
/**
* チェックイン情報を取得します。
*/
function refresh()
{
// 表示中のマーカーの数を残しておく
var len = getLength(markers);
// マーカーをクリアします。
clearMarkers();
// 画面表示クリア
$("#result").empty();
// まず自分のユーザー情報を取得します。
var myurl = baseurl;
myurl += "?action=user&pushback=refresh&callback={callback}";
$.getJSONP(myurl,
function (result) {
if(result.js == undefined) { // 認証済みの場合
// 情報が取得出来てる場合
if(result.user && result.user.checkin) {
owner = result.user;
var venue = result.user.checkin.venue;
// 最初だけ地図の中心を変更します。
if(len == 0) {
var latlng = new google.maps.LatLng(venue.geolat, venue.geolong);
mapOptions.center = latlng;
map.setOptions(mapOptions);
}
// マーカーを作成します。
createMarker(result.user, venue, result.user.checkin,
"http://chart.apis.google.com/chart?cht=mm&chs=32x32&chco=FFFFFF,0000FF,000000&ext=.png");
}
// フレンドのチェックイン情報を取得します。
getCheckins();
}
else {
// OAuth認証します。
eval(result.js);
}
});
}
/**
* 連想配列の要素数を取得します。
*/
function getLength(hash)
{
var len = 0;
for (var key in hash) {
len++;
}
return len;
}
/**
* フレンドのチェックイン情報を取得します。
*/
function getCheckins()
{
var url = baseurl;
// url作成
var ownervenue = owner.checkin.venue;
url += "?pushback=refresh&action=checkins&geolat=" + ownervenue.geolat + "&geolong=" + ownervenue.geolong + "&callback={callback}";
$.getJSONP(url, function(result) {
if(result.js == undefined) {
if(result.checkins) {
// チェックイン情報があったら
$( result.checkins ).each(
function() {
var user;
var venue;
if(this.user) {
user = this.user;
}
if(this.venue) { // 公開チェックインの場合
venue = this.venue;
// 日時情報の整形
var createat = getDateString(this.created);
var markerurl;
var now = new Date();
// 時間の比較用
var diffdate = compareDate(now , createat);
// 経過時間によってマーカーの色を変えます。
if(diffdate >= 1) { // 1日以上経過している
markerurl = "http://chart.apis.google.com/chart?cht=mm&chs=32x32&chco=FFFFFF,FFCCCC,000000&ext=.png";
}
else if(diffdate <= (3600000/86400000)) { // 1時間以内にチェックインしている
markerurl = "http://chart.apis.google.com/chart?cht=mm&chs=32x32&chco=FFFFFF,FF0000,000000&ext=.png";
}
else {
markerurl = "http://chart.apis.google.com/chart?cht=mm&chs=32x32&chco=FFFFFF,FF6666,000000&ext=.png";
}
// マーカー作成
createMarker(user, venue, this, markerurl);
}
// 詳細情報表示
writeCheckinDetail(user, venue, this);
});
}
}
else {
// OAuth認証 or エラー時用
eval(result.js);
}
});
}
/**
* マーカーを作成します
*/
function createMarker(user, venue, checkin, iconurl)
{
// マーカー情報の生成。
var latlng = new google.maps.LatLng(venue.geolat, venue.geolong);
var icon = new google.maps.MarkerImage(iconurl,
new google.maps.Size( 32, 32 ),
new google.maps.Point(0,0),
new google.maps.Point(14,18));
var markerOptions = {
position : latlng,
map : map,
title : venue.name + " (" + user.firstname + ")",
icon: icon
};
// マーカー生成
var marker = new google.maps.Marker(markerOptions);
var createat = getDateString(checkin.created);
// 日時の整形
var createdate = getDisplayDate(createat);
// 情報ウインドウ用のhtml作成
var contentString = '<div id="user_' + user.id + '">' +
'<div class="user>' +
'<div class="phote"><img src="' + user.photo + '" /></div>';
contentString += '<div class="userinfo">name: ';
if(user.twitter != undefined) {
contentString += '<a href="http://foursquare.com/user/' + user.twitter + '" target="4sq">' + user.firstname + '</a>';
}
else {
contentString += user.firstname;
}
contentString += '</div>';
contentString += '<div >last checkin: ' + createdate + '</div>';
contentString += '</div>';
contentString += '<div class="venue">';
contentString += '<div class="venuename"><a href="http://foursquare.com/venue/' + venue.id + '" target="4sq">';
contentString += venue.name + '</a></div>';
contentString += '<div class="address">' + venue.address + ' ' + venue.city + '</div>';
contentString += '</div></div>';
// 情報ウインドウ作成
var infowindow = new google.maps.InfoWindow({
content: contentString
});
// マーカーがクリックしたら表示されるようにする。
google.maps.event.addListener(marker, 'click', function(event) {
infowindow.open(map,marker);
});
// マーカーを連想配列に収納
markers[checkin.id] = marker;
}
/**
* 全てのマーカーをクリアする。
*/
function clearMarkers()
{
for (var key in markers) {
var marker = markers[key];
if(marker) {
marker.setMap(null);
}
delete markers[key];
}
}
/**
* 情報ウインドウを表示する。
*/
function showInfo(checkinId)
{
var marker = markers[checkinId];
if(marker) {
marker.setZIndex = 99999;
google.maps.event.trigger(marker, 'click');
}
}
/**
* 詳細情報を表示する。
*/
function writeCheckinDetail(user, venue, checkin)
{
// htmlの整形
var detail = '<div id="checkin_' + checkin.id + '" class="checkin">';
detail += '<div class="checkininfo">';
if(venue) {
detail += '<a href="#" id="checkin_link_' + checkin.id + '" ';
if(checkin.shout) {
detail += 'title="' + checkin.shout + '" ';
}
detail += '>';
}
else {
detail += '<span ';
if(checkin.shout) {
detail += 'title="' + checkin.shout + '" ';
}
detail += '>';
}
detail += checkin.display;
if(venue) {
detail+= '</a>';
}
else {
detail+= '</span>';
}
var createat = getDateString(checkin.created);
var createdate = getDisplayDate(createat);
detail += ' (' + createdate + ')</div>';
// 整形したhtmlを表示する。
$("#result").append(detail);
// クリックしたら、情報ウインドウが表示されるようにする。
$("#checkin_link_" + checkin.id).click(
function(event) {
showInfo(checkin.id);
});
}
この他に、右クリックメニューからべニューを検索するようにもしています。べニュー(venue)検索すると、かなり位置がずれているのがあって面白いですね。
この後は、Tips情報の表示とか、地図上からべニューを登録したりとか出来る用にしたいなと思ってます。




#1 by Hattori - 2010年8月28日 at 15:11
上記コードをまねしてやってみましたが、うまく行きませんでした。
thrown in /usr/share/php5-pear/HTTP/OAuth/Consumer.php on line 168
OAUTHがうまく行かないようです。
そもそもhttp://foursquare.com/apps/でアプリケーション登録したのですが、
KEYやSECRETも得られませんでした。
なにかヒントをいただければと思います。
#2 by Koichi - 2010年8月28日 at 15:34
エラー自体については、わかりませんが、自分でOAuthアプリケーション登録したものは、
http://foursquare.com/oauth/
より確認できます。
KEYとSECRETもここで参照できます。
#3 by Hattori - 2010年8月28日 at 15:55
「自分でOAuthアプリケーション登録したものは、
http://foursquare.com/oauth/
より確認できます。
KEYとSECRETもここで参照できます。」
ありがとうございます。
確認するには、Click here to register a new consumer
を実施する必要があるのでしょうか?
#4 by Koichi - 2010年8月28日 at 23:15
それは、新しいアプリを登録するリンクです。
何も登録されていないんじゃないですかね?
登録されていれば、
Registered Consumers
の下に登録されているアプリの一覧が出ますから。
#5 by Hattori - 2010年8月29日 at 17:13
http://foursquare.com/apps/add
上記のページからアプリを登録しました。(カテゴリーはWebsitesを選択)
それでもやはり、http://foursquare.com/oauth/ こちらには表示されませんでした。
#6 by Koichi - 2010年8月29日 at 18:08
どうやら、Consumer Keyの申請は、
http://foursquare.com/oauth/register
でいいようです。
http://foursquare.com/apps/add
はアプリの申請用なので、とりあえず使う分には大丈夫そうです。
あとで、本文のリンクも変えておきます。
#7 by Hattori - 2010年8月30日 at 12:23
ありがとうございます。
http://foursquare.com/oauth/register
こちらから登録しましたが#1のエラーのままでした。
OAuthProxy.class.php の
$this->consumer->getRequestToken($this->request_token_url, $this->callback_url);
ここでエラーとなるようです。
#8 by Hattori - 2010年8月31日 at 12:25
上記のエラーについて報告です。
独自に構築したサーバの問題かもしれません。
さくらサーバでサンプロを動かしたところ、動作しました。
とても参考になるサンプルですので、
続編も期待しています。
#9 by Koichi - 2010年9月3日 at 10:45
遅くなりましたが。
無事に動いてよかったです。