├── vba
├── Sheet1
└── README.md
├── c
├── utils.h
├── Makefile
├── README.md
├── http.h
├── mixi.h
├── utils.c
├── test.c
├── mixi.c
└── http.c
├── Clojure
├── .gitignore
├── project.clj
├── README.markdown
├── test
│ └── clj_mixi_graph_api
│ │ └── test
│ │ └── core.clj
└── src
│ └── clj_mixi_graph_api
│ └── core.clj
├── golang
├── Makefile
├── config.json
├── README.md
└── mixi.go
├── .gitmodules
├── Python
├── app.yaml
├── README.md
├── mixi.html
└── mixi.py
├── scala
├── build.sbt
├── README.md
└── src
│ └── main
│ └── scala
│ ├── example02
│ └── Main.scala
│ └── example01
│ └── Main.scala
├── cpp
├── Makefile
├── README.md
└── sample.cpp
├── chrome
├── README.md
├── manifest.json
├── mixi.html
└── mixi.js
├── Java
├── README.md
└── Mixi.java
├── Perl
├── README.md
└── sample.pl
├── objc
├── README.md
└── main.m
├── PHP
├── README.md
└── sample.php
├── Ruby
├── README.md
└── sample.rb
├── haskell
├── README.md
└── show_friend.hs
├── android
└── README.md
├── erlang
├── README.md
├── test.erl
└── mixi.erl
├── R
├── README.md
├── sample.R
└── lib
│ └── mixiGraphAPI.R
├── README.md
├── bash
├── README.md
└── mixi.sh
└── cs
├── README.md
└── Main.cs
/vba/Sheet1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mixi-inc/mixi_graph_api_examples/HEAD/vba/Sheet1
--------------------------------------------------------------------------------
/c/utils.h:
--------------------------------------------------------------------------------
1 | int get_integer_digit(int len);
2 |
3 | char* new_concat_strings(int len, ...);
4 |
--------------------------------------------------------------------------------
/Clojure/.gitignore:
--------------------------------------------------------------------------------
1 | pom.xml
2 | *jar
3 | /lib/
4 | /classes/
5 | .lein-failures
6 | .lein-deps-sum
7 |
--------------------------------------------------------------------------------
/golang/Makefile:
--------------------------------------------------------------------------------
1 | include $(GOROOT)/src/Make.inc
2 |
3 | TARG=mixi
4 | GOFILES=\
5 | mixi.go\
6 |
7 | include $(GOROOT)/src/Make.cmd
8 |
--------------------------------------------------------------------------------
/golang/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "client_id":"YOUR CLIENT ID",
3 | "client_secret":"YOUR SECRET",
4 | "redirect_port":"8080"
5 | }
6 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "android/oauth_people"]
2 | path = android/oauth_people
3 | url = git://github.com/tnj/AndroidOAuthExample.git
4 |
--------------------------------------------------------------------------------
/Python/app.yaml:
--------------------------------------------------------------------------------
1 | application: ***********
2 | version: 1
3 | runtime: python
4 | api_version: 1
5 |
6 | handlers:
7 | - url: /.*
8 | script: mixi.py
--------------------------------------------------------------------------------
/scala/build.sbt:
--------------------------------------------------------------------------------
1 | name := "mixi Graph API Example"
2 |
3 | version := "1.0"
4 |
5 | libraryDependencies ++= Seq(
6 | "commons-httpclient" % "commons-httpclient" % "3.1",
7 | "net.debasishg" %% "sjson" % "0.15"
8 | )
9 |
--------------------------------------------------------------------------------
/cpp/Makefile:
--------------------------------------------------------------------------------
1 | #Makefile
2 | LIBS=-lssl \
3 | -lutilspp \
4 |
5 | LIB_DIR=
6 |
7 | INCLUDES=
8 |
9 | default:
10 | gcc $(LIB_DIR) $(LIBS) $(INCLUDES) -o mixi_sample sample.cpp
11 |
12 | clean:
13 | rm mixi_sample
14 |
--------------------------------------------------------------------------------
/chrome/README.md:
--------------------------------------------------------------------------------
1 | # Chrome Extension版
2 |
3 | ## 実行手順
4 |
5 | 1. Chromeで chrome://extensions にアクセス
6 | 2. 「パッケージ化されていない拡張機能を読み込む...」をクリックして manifest.json を含むディレクトリを選択
7 | 3. 新規タブを開き、「Mixi Chrome Extension Example」をクリック
8 | 4. 画面の指示に従う
9 |
--------------------------------------------------------------------------------
/Python/README.md:
--------------------------------------------------------------------------------
1 | # 実行手順
2 |
3 | 1. mixi Partner DashboardでリダイレクトURLを [http://localhost:8080] にしたアプリを登録(ポート番号は任意)
4 | 2. app.yamlのプロジェクトを適切な内容に修正する
5 | 3. mixi.pyのCONSUMER_KEYとCONSUMER_SECRETを適切な内容に修正する
6 | 4. localhost:8080でGoogle App Engineを起動
7 | 5. ブラウザで[http://localhost8080/login]を開く
8 |
--------------------------------------------------------------------------------
/Clojure/project.clj:
--------------------------------------------------------------------------------
1 | (defproject clj-mixi-graph-api "1.0.0-SNAPSHOT"
2 | :description "Clojure sample for using mixi Graph API."
3 | :dependencies [[org.clojure/clojure "1.3.0"]
4 | [clj-apache-http "2.3.2"]
5 | [clj-json "0.4.3"]]
6 | :main clj-mixi-graph-api.core)
7 |
--------------------------------------------------------------------------------
/chrome/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Mixi Chrome Extension Example",
3 | "version": "1.0",
4 | "description": "Use mixi Graph API",
5 | "app": {
6 | "launch": {
7 | "local_path": "mixi.html"
8 | }
9 | },
10 | "permissions": [
11 | "*://*.mixi-platform.com/"
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/Java/README.md:
--------------------------------------------------------------------------------
1 | # 実行方法
2 |
3 | ## Authorization codeの入手
4 |
5 | 以下のURLにWebブラウザにてアクセスし、リダイレクト先に含まれるcodeパラメータ値を入手する。
6 |
7 | https://mixi.jp/connect_authorize.pl?client_id=Consumer key&scope=r_profile
8 |
9 | ## 実行
10 |
11 | $> cd Mixi.javaを保存したディレクトリパス
12 | $> javac Mixi.java
13 | $> java Mixi codeパラメータ値
14 |
--------------------------------------------------------------------------------
/Perl/README.md:
--------------------------------------------------------------------------------
1 | # 実行手順
2 | ## コードの書き換え
3 | コード内のCONSUMER_KEY, CONSUMER_SECRET, REDIRECT_URIを適切に書き換えてください。
4 | ## Authorization codeの入手
5 | 以下のURLにWebブラウザにてアクセスし、リダイレクト先に含まれるcodeパラメータ値を入手する。
6 |
7 | https://mixi.jp/connect_authorize.pl?client_id=[YOUR CONSUMER KEY]&scope=r_profile
8 |
9 | ## 実行
10 |
11 | $ sample.pl [codeパラメータ値]
12 |
13 |
--------------------------------------------------------------------------------
/objc/README.md:
--------------------------------------------------------------------------------
1 | # 実行方法
2 |
3 | ## Authorization codeの入手
4 |
5 | 以下のURLにWebブラウザにてアクセスし、リダイレクト先に含まれるcodeパラメータ値を入手する。
6 |
7 | https://mixi.jp/connect_authorize.pl?client_id=Consumer key&scope=r_profile
8 |
9 | ## 実行
10 |
11 | $> cd main.mを保存したディレクトリパス
12 | $> gcc -fobjc-gc -framework Foundation main.m
13 | $> ./a.out codeパラメータ値
14 |
--------------------------------------------------------------------------------
/Python/mixi.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | python sample code for mixi graph api
4 |
5 |
6 | 友人一覧
7 | {% for row in results %}
8 | {{row.displayName}}
9 | {% endfor %}
10 |
11 |
--------------------------------------------------------------------------------
/PHP/README.md:
--------------------------------------------------------------------------------
1 | # Requirement
2 |
3 | PHP >= 5.3.0
4 |
5 | # 実行手順
6 | ## コードの書き換え
7 | コード内のCONSUMER_KEY, CONSUMER_SECRET, REDIRECT_URIを適切に書き換えてください。
8 | ## Authorization codeの入手
9 | 以下のURLにWebブラウザにてアクセスし、リダイレクト先に含まれるcodeパラメータ値を入手する。
10 |
11 | https://mixi.jp/connect_authorize.pl?client_id=[YOUR CONSUMER KEY]&scope=r_profile
12 |
13 | ## 実行
14 |
15 | $ sample.php [codeパラメータ値]
16 |
17 |
--------------------------------------------------------------------------------
/Ruby/README.md:
--------------------------------------------------------------------------------
1 | # 実行手順
2 | ## gemのインストール
3 | JSONをインストールする。
4 |
5 | $gem install json
6 |
7 | ## コードの書き換え
8 | コード内のconsumer_key, consumer_secret, redirect_uriを適切に書き換えてください。
9 | ## Authorization codeの入手
10 | 以下のURLにWebブラウザにてアクセスし、リダイレクト先に含まれるcodeパラメータ値を入手する。
11 |
12 | https://mixi.jp/connect_authorize.pl?client_id=[YOUR CONSUMER KEY]&scope=r_profile
13 |
14 | ## 実行
15 |
16 | $ ruby sample.rb
17 | input Authorization code > [codeパラメータ値]
18 |
--------------------------------------------------------------------------------
/c/Makefile:
--------------------------------------------------------------------------------
1 | CC = gcc
2 | OBJ = utils.o http.o mixi.o test.o
3 |
4 | all: test
5 |
6 | test: $(OBJ)
7 | $(CC) $(OBJ) -o test -lssl -lcrypto
8 |
9 | utils.o: utils.c
10 | gcc -c utils.c
11 |
12 | utils.o: utils.h
13 |
14 | http.o: http.c
15 | gcc -c http.c
16 |
17 | http.o: http.h
18 |
19 | mixi.o: mixi.c
20 | gcc -c mixi.c
21 |
22 | mixi.o: mixi.h
23 |
24 | test.o: test.c
25 | gcc -c test.c
26 |
27 | clean:
28 | rm -f test utils.o http.o mixi.o test.o
29 |
--------------------------------------------------------------------------------
/cpp/README.md:
--------------------------------------------------------------------------------
1 | # 実行方法
2 | ## Authorization codeの入手
3 |
4 | 以下のURLにWebブラウザにてアクセスし、リダイレクト先に含まれるcodeパラメータ値を入手する。
5 |
6 | https://mixi.jp/connect_authorize.pl?client_id=Consumer key&scope=r_profile
7 |
8 | ## コンパイル時に必要なもの
9 | GCC(gcc (GCC) 4.1.2 20080704 で動作確認をしています)
10 | OpenSSL(http://www.openssl.org/)
11 | CLX(http://clx.cielquis.net/)
12 |
13 | ## 実行
14 | 1. Makefileを必要に応じて変更する
15 | 2. makeを実行する
16 | 3. mixi_sample 取得したAuthorization Code を実行
17 |
--------------------------------------------------------------------------------
/golang/README.md:
--------------------------------------------------------------------------------
1 | # 実行手順
2 |
3 | 1. mixi Developer DashboardでリダイレクトURLを [http://localhost:8080] にしたアプリを登録(ポート番号は任意)
4 | 2. config.jsonを作成
5 |
6 | {
7 | "client_id":"YOUR CLIENT ID",
8 | "client_secret":"YOUR SECRET",
9 | "redirect_port":"8080"
10 | }
11 |
12 | 3. コンパイルしてサーバー起動
13 |
14 | $ 6g mixi.go
15 | $ 6l mixi.6
16 | $ 6.out
17 | Please open http://localhost:8080 on a web browser.
18 |
19 | 4. ブラウザで [http://localhost:8080] を開く
20 |
--------------------------------------------------------------------------------
/haskell/README.md:
--------------------------------------------------------------------------------
1 | # 実行手順
2 |
3 | ## 依存モジュールのインストール
4 |
5 | > $ cabal install json
6 |
7 | > $ cabal install http-enumerator
8 |
9 | ## Authorization codeの入手
10 |
11 | 以下のURLにWebブラウザにてアクセスし、リダイレクト先に含まれるcodeパラメータ値を入手する。
12 |
13 | https://mixi.jp/connect_authorize.pl?client_id=Consumer key&scope=r_profile
14 |
15 | ## Consumer Key, Consumer Secret を書きかえ
16 |
17 | > $ vim show_friend.hs # clientId, clientSecret をそれぞれ適切な値に編集
18 |
19 | ## 実行
20 |
21 | > $ runghc show_friend.hs ${取得したcode値}
22 |
--------------------------------------------------------------------------------
/c/README.md:
--------------------------------------------------------------------------------
1 | # 実行手順
2 |
3 | ## 必要なもの
4 |
5 | > OpenSSL
6 |
7 | > GNU開発環境
8 |
9 | ## Authorization codeの入手
10 |
11 | 以下のURLにWebブラウザにてアクセスし、リダイレクト先に含まれるcodeパラメータ値を入手する。
12 |
13 | https://mixi.jp/connect_authorize.pl?client_id=Consumer key&scope=r_profile
14 |
15 | ## コードの修正
16 |
17 | test.c ファイルにある以下の文字列を適切なものに変更する。
18 |
19 | > YOUR CLIENT ID
20 |
21 | > YOUR CLIENT SECRET
22 |
23 | > YOUR REDIRECT URI
24 |
25 | ※ REDIRECT URIは、URLエンコード済みの文字列を記載してください。
26 |
27 | ## 実行
28 |
29 | $> make
30 | $> ./test codeパラメータ値
31 |
--------------------------------------------------------------------------------
/android/README.md:
--------------------------------------------------------------------------------
1 | mixi Graph API Sample Codes for Android
2 | ===============
3 |
4 | Android で mixi Graph API を使用するためのサンプルコードです。
5 | mixi API SDK for Android を *使用しない* で、 mixi Graph API を使用する例となります。
6 |
7 | oauth_people
8 | ---------------
9 | このサンプルでは、 Android 上で mixi Graph API を利用するために必要な
10 | OAuth 2.0 の認証認可の手続きと、アクセストークンのリフレッシュ機構、
11 | および People API を用いた、友人一覧の取得処理を実装しています。
12 |
13 | コードについての解説は、以下の記事をご参照ください。
14 |
15 | "ネイティブアプリで実践! mixi Graph API活用法 OAuth 2.0を使うソーシャルなAndroidアプリの作り方"
16 | http://www.atmarkit.co.jp/fsmart/articles/androidmixi/01.html
17 |
18 |
--------------------------------------------------------------------------------
/erlang/README.md:
--------------------------------------------------------------------------------
1 | # 実行手順
2 |
3 | ## mochiwebのインストール
4 |
5 | $> cd
6 | $> git clone git://github.com/mochi/mochiweb.git
7 | $> vi .bashrc
8 | $> source .bashrc
9 |
10 | .bashrcには以下を記述する。
11 |
12 | export ERL_LIBS=githubから入手したmochiwebのディレクトリパス
13 |
14 | ## Authorization codeの入手
15 |
16 | 以下のURLにWebブラウザにてアクセスし、リダイレクト先に含まれるcodeパラメータ値を入手する。
17 |
18 | https://mixi.jp/connect_authorize.pl?client_id=Consumer key&scope=r_profile
19 |
20 | ## 実行
21 |
22 | $> cd mixi.erlとtest.erlを保存したディレクトリパス
23 | $> erl
24 | 1> c(mixi).
25 | 2> c(test).
26 | 3> test:main("codeパラメータ値").
27 |
--------------------------------------------------------------------------------
/R/README.md:
--------------------------------------------------------------------------------
1 | # 実行手順
2 | ## R packageのインストール
3 | rjson,RCurlをインストールします。
4 |
5 | In your R console:
6 | > install.packages("rjson")
7 | > install.packages("RCurl")
8 |
9 | RCurlの依存ライブラリとしてlibcurl([http://curl.haxx.se.]())が必要です。
10 |
11 |
12 | ## コードの書き換え
13 | コード内のconsumer\_key, consumer\_secret, redirect\_uriを適切に書き換えてください。
14 | ## Authorization codeの入手
15 | 以下のURLにWebブラウザにてアクセスし、リダイレクト先に含まれるcodeパラメータ値を入手する。
16 |
17 | https://mixi.jp/connect_authorize.pl?client_id=[YOUR CONSUMER KEY]&scope=r_profile
18 |
19 | ## 実行
20 |
21 | $ Rscript sample.R
22 | Input Authorization Code : [codeパラメータ値]
23 |
--------------------------------------------------------------------------------
/R/sample.R:
--------------------------------------------------------------------------------
1 | #demonstration
2 |
3 | #load library
4 | source("./lib/mixiGraphAPI.R")
5 | library(rjson)
6 | library(RCurl)
7 |
8 | grant_type ="authorization_code"
9 | client_id ="YOUR CONSUMER KEY"
10 | client_secret ="YOUR CONSUMER SECRET"
11 | redirect_uri ="YOUR REDIRECT URI"
12 |
13 | cat("Input Authorization Code : ")
14 | code <-readLines(file("stdin"),1)
15 |
16 | token<-get_token(client_id,client_secret,code,redirect_uri)
17 | print(token)
18 |
19 | people<-get_people("@friends",token$access_token)
20 | print(people)
21 |
22 | refreshed_token<-refresh_token(token$refresh_token,client_id,client_secret)
23 | print(refreshed_token)
24 |
25 |
--------------------------------------------------------------------------------
/scala/README.md:
--------------------------------------------------------------------------------
1 | # 実行方法
2 |
3 | ## sbt 0.11 のセットアップ
4 |
5 | https://github.com/harrah/xsbt/wiki/Setup を参考に sbt をセットアップする。
6 |
7 | ## Authorization codeの入手
8 |
9 | 以下のURLにWebブラウザにてアクセスし、リダイレクト先に含まれるcodeパラメータ値を入手する。
10 |
11 | https://mixi.jp/connect_authorize.pl?client_id=Consumer key&scope=r_profile
12 |
13 | ## Consumer Key および Consumer Sercret を書き換える
14 |
15 | object Main {
16 | val CONSUMER_KEY = "XXXXXXXX"
17 | val CONSUMER_SECRET = "XXXXXXXXXXXXXXXX"
18 | :
19 | }
20 |
21 | ## 実行
22 |
23 | $ sbt
24 | > run
25 |
26 | example01.Main と example02.Main のどちらを実行するか聞かれるので、実行する方を選択します。
27 | example01.Main ではユーザIDとグループIDの入力待ちになります。それぞれをスペース区切りで入力します。
28 | example02.Main は友人一覧を取得して終了します。
29 |
--------------------------------------------------------------------------------
/c/http.h:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | struct ssl_info {
4 | SSL* ssl;
5 | SSL_CTX* ctx;
6 | };
7 |
8 | struct http_response {
9 | int status_code;
10 | char* body;
11 | };
12 |
13 | enum ePROTOCOL {
14 | HTTP,
15 | HTTPS
16 | };
17 |
18 | char* new_json_property_value(char* json, char* property_name);
19 |
20 | int get_http_status_code(const char* response);
21 |
22 | char* new_http_response_body(const char* response);
23 |
24 | int connect_to_server(char* host, int port, char* path);
25 |
26 | struct ssl_info ssl_initialize(int s);
27 |
28 | char* receive_http_response(enum ePROTOCOL protocol, int s, SSL* ssl);
29 |
30 | void close_connection(enum ePROTOCOL protocol, int s, struct ssl_info* ssl);
31 |
32 | void send_http_request(enum ePROTOCOL protocol, char* request, int s, SSL* ssl);
33 |
--------------------------------------------------------------------------------
/vba/README.md:
--------------------------------------------------------------------------------
1 | # 実行方法
2 |
3 | ## 準備
4 |
5 | 任意のエクセルのSheet1に本コードを貼り付け、フォームにボタンを3つ追加する。
6 |
7 | Btn_GetAccessToken (Authorization codeでAccess tokenを取得する)
8 | Btn_GetProfile (People APIでプロフィール情報を取得する)
9 | Btn_Refresh (Refresh tokenでAccess tokenを再発行する)
10 |
11 | ## Authorization codeの入手
12 |
13 | 以下のURLにWebブラウザにてアクセスし、リダイレクト先に含まれるcodeパラメータ値を入手する。
14 |
15 | https://mixi.jp/connect_authorize.pl?client_id=Consumer key&scope=r_profile
16 |
17 | ## 以下のセル番号に対応するセルにそれぞれ値を入力する
18 |
19 | Private Const CL_CLIENT_ID = "C5" ' Consumer key
20 | Private Const CL_CLIENT_SECRET = "C6" ' Consumer Secret
21 | Private Const CL_REDIRECT_URI = "C7" ' Redirect URI
22 | Private Const CL_AUTHORIZATION_CODE = "C8" ' Authorization Code
23 |
24 | ## 実行
25 |
26 | フォーム上のボタンを押下して、処理を実行する。
27 |
--------------------------------------------------------------------------------
/c/mixi.h:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | struct client_credential {
4 | char* client_id;
5 | char* client_secret;
6 | char* redirect_uri;
7 | };
8 |
9 | void send_issue_token_request(struct client_credential cc,
10 | char* authorization_code,
11 | char* host,
12 | char* path,
13 | SSL* ssl);
14 |
15 | void send_get_my_profile_request(char* access_token,
16 | char* host,
17 | char* path,
18 | int s);
19 |
20 | struct http_response issue_token(struct client_credential cc,
21 | char* authorization_code);
22 |
23 | struct http_response get_my_profile(char* access_token);
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | mixi Graph APIを利用するためのサンプルコード集です。
2 |
3 |
4 |
6 |
7 |
8 |
9 | To the extent possible under law,
10 |
12 | mixi Inc.
13 | has waived all copyright and related or neighboring rights to
14 | mixi Graph API Examples .
15 | This work is published from:
16 |
18 | Japan .
19 |
20 |
--------------------------------------------------------------------------------
/chrome/mixi.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 認可 をクリックして認可し、クエリパラメータのcodeの値をコピーしてください。
10 |
11 |
12 | コピーした値を にペーストし、アクセストークン取得 をクリックしてください。
13 |
14 |
15 | アクセストークン(未取得 )が取得されたらAPI呼び出し をクリックしてください。
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/bash/README.md:
--------------------------------------------------------------------------------
1 | # 実行方法
2 |
3 | ## スクリプト中の CONSUMER_KEY(Consumer Key), CONSUMER_SECRET(Consumer Secret), REDIRECT_URI(リダイレクトURI) を環境に応じて書き換えます
4 |
5 | CONSUMER_KEY='****'
6 | CONSUMER_SECRET='****'
7 | REDIRECT_URI='****'
8 |
9 | ## Authorization code の入手
10 |
11 | 以下のURLにWebブラウザにてアクセスし、リダイレクト先に含まれるcodeパラメータ値を入手します。
12 |
13 | https://mixi.jp/connect_authorize.pl?client_id=Consumer key&scope=r_profile
14 |
15 | ## 実行
16 |
17 | access_token の入手
18 |
19 | $ ./mixi.sh auth
20 |
21 | access_token のリフレッシュ
22 |
23 | $ ./mixi.sh refresh
24 |
25 | PeopleAPI にて自分自身の情報を取得
26 |
27 | $ ./mixi.sh people self
28 |
29 | PeopleAPI にて友人の情報を取得
30 |
31 | $ ./mixi.sh people friends
32 |
33 | 結果はそれぞれ JSON にて出力されます。
34 | json_xs コマンドが利用可能な場合、JSON を整形して出力します。
35 |
36 |
--------------------------------------------------------------------------------
/c/utils.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include "utils.h"
6 |
7 | int get_integer_digit(int len) {
8 | int i;
9 |
10 | for (i = 0; len != 0; i++) {
11 | len /= 10;
12 | }
13 |
14 | return i;
15 | }
16 |
17 | char* new_concat_strings(int len, ...) {
18 | va_list strings;
19 | int i;
20 | char* string;
21 | int all_len;
22 | char* result;
23 |
24 | va_start(strings, len);
25 | all_len = 0;
26 | for (i = 0; i < len; i++) {
27 | string = va_arg(strings, char*);
28 | all_len += strlen(string);
29 | }
30 | va_end(strings);
31 |
32 | result = calloc(all_len + 1, 1);
33 | va_start(strings, len);
34 | for (i = 0; i < len; i++) {
35 | string = va_arg(strings, char*);
36 | strcat(result, string);
37 | }
38 | va_end(strings);
39 |
40 | result[all_len] = '\0';
41 | return result;
42 | }
43 |
--------------------------------------------------------------------------------
/cs/README.md:
--------------------------------------------------------------------------------
1 | # INSTRUCTION
2 | ## Rewrite Credentials
3 | Please rewrite credentials in sample code about CONSUMER_KEY, CONSUMER_SECRET and REDIRECT_URL.
4 |
5 | ## Framework
6 | This sample application can run on .NET Framework of after version 3.5.
7 |
8 | ## Reference Settings for Build
9 | This sample application require reference settings of System.Web.Extentions.
10 |
11 | ## Run
12 | (Windows)
13 | Please launch in command line prompt.
14 |
15 | (Macintosh or Linux)
16 | $ mono main.exe
17 |
18 | # 利用案内
19 | ## クレデンシャル情報の書き換え
20 | サンプルコード内のCONSUMER_KEY,CONSUMER_SECRETおよびREDIRECT_URLを適切な内容に書き換えてください。
21 |
22 | ## フレームワーク
23 | このサンプルアプリケーションは.NET Framework 3.5以降で動作します。
24 | .NET Framework 4.0以降を利用する場合、dynamic型を使うことでJSONの取り扱いを簡略化した実装が可能です。
25 |
26 | ## ビルドのための参照設定
27 | System.Web.Extentionsを参照に追加してください。
28 |
29 | ## 実行方法
30 | (Windowsの場合)
31 | コマンドラインで実行してください。
32 |
33 | (MacintoshまたはLinuxの場合)
34 | mono 2.10での実行を確認しています。
35 | ターミナルで実行してください。
36 | $ mono main.exe
37 |
--------------------------------------------------------------------------------
/Clojure/README.markdown:
--------------------------------------------------------------------------------
1 | # clj-mixi-graph-api
2 |
3 | Clojure sample for using mixi Graph API.
4 |
5 | ## Usage
6 |
7 | 0. Leiningen を入れる
8 |
9 | https://github.com/technomancy/leiningen
10 |
11 |
12 | 1. ConsumeKey と ConsumerSecret 及び、必要があれば RedirectUri を書き換える
13 |
14 | (def consumer-info
15 | {:key "xxxxxxxxxxxxxxxxxxxx"
16 | :secret "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
17 | :redirect-uri "https://mixi.jp/connect_authorize_success.html"})
18 |
19 | 2. 依存を解決する
20 |
21 | % lein deps
22 |
23 | 2. REPLで実行する
24 |
25 | request-access-token にはユーザーの認可で得た authorization code を渡してください。
26 |
27 | % lein repl
28 | clj-mixi-graph-api.core=> (def first-token (get-token (request-access-token "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")))
29 | clj-mixi-graph-api.core=> (get-my-friends first-token)
30 | clj-mixi-graph-api.core=> (def refreshed-token (get-token (refresh-access-token (:refresh-token first-token))))
31 | clj-mixi-graph-api.core=> (get-my-friends refreshed-token)
32 |
--------------------------------------------------------------------------------
/erlang/test.erl:
--------------------------------------------------------------------------------
1 | -module(test).
2 | -export([main/1]).
3 |
4 | main(AuthorizationCode) ->
5 | initialize(),
6 | ClientId = "[Client ID]",
7 | ClientSecret = "[Client secret]",
8 | RedirectUri = "[Redirect URI]",
9 | try mixi:get_token(AuthorizationCode,
10 | ClientId,
11 | ClientSecret,
12 | RedirectUri) of
13 | {AccessToken, RefreshToken} ->
14 | io:format("Access token: ~p Refresh token: ~p~n",
15 | [AccessToken, RefreshToken]),
16 | Response = mixi:get_my_friends(AccessToken),
17 | {_, Entries} = lists:keyfind(<<"entry">>, 1, Response),
18 | lists:foreach(fun({struct, Entry}) ->
19 | {_, DisplayName} = lists:keyfind(
20 | <<"displayName">>, 1, Entry),
21 | io:format("~ts~n", [DisplayName])
22 | end, Entries)
23 | catch
24 | throw:{Status, Error, Description} ->
25 | io:format("~p: ~s : ~s~n",
26 | [Status, Error, Description])
27 | end,
28 | cleanup().
29 |
30 | initialize() ->
31 | inets:start(),
32 | ssl:start().
33 |
34 | cleanup() ->
35 | ssl:stop(),
36 | inets:stop().
37 |
--------------------------------------------------------------------------------
/chrome/mixi.js:
--------------------------------------------------------------------------------
1 | var CLIENT_ID = "YOUR CLIENT ID";
2 | var CLIENT_SECRET = "YOUR CLIENT SECRET";
3 | var REDIRECT_URI = encodeURIComponent("YOUR REDIRECT URI");
4 |
5 | function authorize(code) {
6 | var xhr = new XMLHttpRequest();
7 | xhr.onreadystatechange = function(){
8 | if (xhr.readyState == 4 && xhr.status == 200){
9 | var json = eval('(' + xhr.responseText + ')');
10 | document.getElementById('access_token').innerHTML = json['access_token'];
11 | }
12 | }
13 | xhr.open('POST', 'https://secure.mixi-platform.com/2/token');
14 | xhr.setRequestHeader("Content-Type" , "application/x-www-form-urlencoded");
15 | xhr.send("grant_type=authorization_code&client_id=" + CLIENT_ID +
16 | "&client_secret=" + CLIENT_SECRET + "&code=" + code + "&redirect_uri=" + REDIRECT_URI);
17 | }
18 |
19 | function call(accessToken) {
20 | var xhr = new XMLHttpRequest();
21 | xhr.onreadystatechange = function(){
22 | if (xhr.readyState == 4 && xhr.status == 200){
23 | document.getElementById('json').value = xhr.responseText;
24 | }
25 | }
26 | xhr.open('GET', 'http://api.mixi-platform.com/2/people/@me/@friends');
27 | xhr.setRequestHeader("Authorization" , "OAuth " + accessToken);
28 | xhr.send();
29 | }
30 |
--------------------------------------------------------------------------------
/c/test.c:
--------------------------------------------------------------------------------
1 | #include "http.h"
2 | #include "mixi.h"
3 |
4 | int main(int argc, char* argv[]) {
5 | char* error;
6 | char* access_token;
7 | char* display_name;
8 | struct http_response token_response;
9 | struct http_response my_profile_response;
10 |
11 | if (argc != 2) {
12 | printf("Error: Authorization code is required.\n");
13 | exit(1);
14 | }
15 |
16 | struct client_credential cc = {
17 | "YOUR CLIENT ID",
18 | "YOUR CLIENT SECRET",
19 | "YOUR REDIRECT URI"
20 | };
21 |
22 | token_response = issue_token(cc, argv[1]);
23 | if (token_response.status_code != 200) {
24 | error = new_json_property_value(token_response.body, "error");
25 | printf("Error at retrieving token: (%d) %s\n",
26 | token_response.status_code, error);
27 |
28 | free(error);
29 | } else {
30 | access_token =
31 | new_json_property_value(token_response.body, "access_token");
32 | my_profile_response = get_my_profile(access_token);
33 | if (my_profile_response.status_code != 200) {
34 | printf("Error at retrieve peron: (%d)\n",
35 | my_profile_response.status_code);
36 | } else {
37 | display_name =
38 | new_json_property_value(my_profile_response.body, "displayName");
39 | printf("%s\n", display_name);
40 | free(display_name);
41 | }
42 |
43 | free(access_token);
44 | free(my_profile_response.body);
45 | }
46 |
47 | free(token_response.body);
48 | return 0;
49 | }
50 |
--------------------------------------------------------------------------------
/Ruby/sample.rb:
--------------------------------------------------------------------------------
1 | require 'rubygems'
2 | require 'json'
3 | require 'net/https'
4 | require 'net/http'
5 | require 'pp'
6 |
7 | module Mixi
8 | CONSUMER_KEY = 'YOUR CLIENT ID'
9 | CONSUMER_SECRET = 'YOUR CONSUMER SECRET'
10 | REDIRECT_URI = 'YOUR REDIRECT URI'
11 |
12 | class Client
13 | def self.example
14 | raise 'authcode is mandatory.' if ARGV.empty?
15 | client = Mixi::Client.new
16 | client.authorize! ARGV.first
17 | pp client.call('/people/@me/@self')
18 | end
19 |
20 | def authorize!(auth_code)
21 | params = "grant_type=authorization_code&client_id=#{CONSUMER_KEY}&client_secret=#{
22 | CONSUMER_SECRET}&code=#{auth_code}&redirect_uri=#{REDIRECT_URI}"
23 | https = Net::HTTP.new('secure.mixi-platform.com', 443)
24 | https.use_ssl = true
25 | https.start do
26 | response = https.post('/2/token', params).body
27 | json = JSON.parse(response)
28 | @access_token = json['access_token']
29 | @refresh_token = json['refresh_token']
30 | end
31 | end
32 |
33 | def call(endpoint)
34 | http = Net::HTTP.new('api.mixi-platform.com', 80)
35 | http.start do
36 | response = http.get("/2#{endpoint}",
37 | 'Authorization' => "OAuth #{@access_token}",
38 | 'HOST' => 'api.mixi-platform.com').body
39 | JSON.parse(response)
40 | end
41 | end
42 | end
43 | end
44 |
45 | Mixi::Client.example
46 |
--------------------------------------------------------------------------------
/R/lib/mixiGraphAPI.R:
--------------------------------------------------------------------------------
1 | get_token<-function(client_id,client_secret,code,redirect_uri){
2 | token_raw<-postForm("https://secure.mixi-platform.com/2/token",
3 | grant_type=grant_type,
4 | client_id=client_id,
5 | client_secret=client_secret,
6 | code=code,
7 | redirect_uri=redirect_uri
8 | )
9 | parser<-newJSONParser()
10 | parser$addData(token_raw)
11 | token <- parser$getObject()
12 | return(token)
13 | }
14 |
15 |
16 | get_people<-function(type,access_token){
17 | url<-paste("https://api.mixi-platform.com/2/people/@me/",type,sep="")
18 | res_people_raw<-getForm(url,oauth_token=access_token)
19 | parser<-newJSONParser()
20 | parser$addData(res_people_raw)
21 | res_people <- parser$getObject()
22 | return(res_people)
23 | }
24 |
25 |
26 | refresh_token<-function(refresh_token,client_id,client_secret){
27 | res_raw_token <- postForm("https://secure.mixi-platform.com/2/token",
28 | grant_type="refresh_token",
29 | client_id=client_id,
30 | client_secret=client_secret,
31 | refresh_token=refresh_token
32 | )
33 | parser<-newJSONParser()
34 | parser$addData(res_raw_token)
35 | res_token=parser$getObject()
36 | return(res_token)
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/haskell/show_friend.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE OverloadedStrings #-}
2 | import Text.JSON
3 | import System.Environment
4 | import Network.HTTP.Enumerator
5 | import Data.List (sort)
6 | import Data.ByteString.Char8 hiding (sort, putStrLn)
7 | import qualified Data.ByteString.Lazy.Char8 as L
8 |
9 | data Token = Token {
10 | accessToken :: String,
11 | refreshToken :: String
12 | } deriving Show
13 |
14 | clientId = "B" :: ByteString
15 | clientSecret = "xyzzy" :: ByteString
16 | redirectUri = "https://mixi.jp/connect_authorize_success.html" :: ByteString
17 |
18 | tokenRequest :: Monad m => String -> Request m
19 | tokenRequest code =
20 | urlEncodedBody [("grant_type", "authorization_code"),
21 | ("client_id", clientId),
22 | ("client_secret", clientSecret),
23 | ("code", pack code),
24 | ("redirect_uri", redirectUri)]
25 | $ def { host = "secure.mixi-platform.com",
26 | port = 443,
27 | path = "/2/token",
28 | secure = True }
29 |
30 | peopleRequest :: Monad m => String -> Request m
31 | peopleRequest token = def {
32 | host = "api.mixi-platform.com",
33 | path = "/2/people/@me/@friends",
34 | requestHeaders = [
35 | ("Authorization", append "OAuth " (pack token))
36 | ]
37 | }
38 |
39 | parseTokenResponse :: String -> Result Token
40 | parseTokenResponse res = do
41 | json <- decode res
42 | case sort $ fromJSObject json of
43 | [("access_token", JSString acc),
44 | ("expires_in", _),
45 | ("refresh_token", JSString ref),
46 | ("scope", _)] ->
47 | return $ Token {
48 | accessToken = fromJSString acc,
49 | refreshToken = fromJSString ref
50 | }
51 | _ -> fail ("couldn't handle response:" ++ res)
52 |
53 | getAccessToken :: String -> IO (Result Token)
54 | getAccessToken code = do
55 | res <- withManager (httpLbs $ tokenRequest code)
56 | return $ parseTokenResponse (L.unpack $ responseBody res)
57 |
58 | showFriends :: Token -> IO ()
59 | showFriends (Token token _) =
60 | withManager (httpLbs $ peopleRequest token) >>= L.putStrLn . responseBody
61 |
62 | main :: IO ()
63 | main = do code:_ <- getArgs
64 | token <- getAccessToken code
65 | case token of
66 | Ok token -> showFriends token
67 | Error err -> putStrLn err
68 |
--------------------------------------------------------------------------------
/Clojure/test/clj_mixi_graph_api/test/core.clj:
--------------------------------------------------------------------------------
1 | (ns clj-mixi-graph-api.test.core
2 | (:use [clj-mixi-graph-api.core :as m])
3 | (:use [clojure.test]))
4 |
5 | (deftest test-mk-token
6 | (let [token {"refresh_token" "hoge"
7 | "access_token" "fuga"
8 | "expires_in" "piyo"}]
9 | (is (= {:refresh-token "hoge"
10 | :access-token "fuga"
11 | :expires-in "piyo"}
12 | (m/mk-token token)))))
13 |
14 | (deftest test-mk-person
15 | (let [person {"id" "foo" "thumbnailUrl" "bar"
16 | "displayName" "baz" "profileUrl" "qux"}]
17 | (is (= {:id "foo" :thumbnail-url "bar"
18 | :display-name "baz" :profile-url "qux"}
19 | (m/mk-person person)))))
20 |
21 | (deftest test-get-token
22 | (let [resp {:content "{\"refresh_token\":\"hoge\",\"access_token\":\"fuga\",\"expires_in\":\"piyo\"}"}]
23 | (is (= {:refresh-token "hoge"
24 | :access-token "fuga"
25 | :expires-in "piyo"}
26 | (m/get-token resp)))))
27 |
28 | (deftest test-build-header
29 | (let [headers {"foo" "bar"}]
30 | (is (= "bar" (:foo (build-headers headers))))))
31 |
32 | (deftest test-get-oauth-error
33 | (let [has-error-header {:WWW-Authenticate "OAuth error='error!'"}
34 | has-expired-error-header {:WWW-Authenticate "OAuth error='expired_token'"}]
35 | (is (= "error!" (m/get-oauth-error has-error-header)))
36 | (is (= "expired_token" (m/get-oauth-error has-expired-error-header)))))
37 |
38 | (deftest test-has-oauth-error?
39 | (let [no-error-header {:foo "bar"}
40 | has-error-header {:WWW-Authenticate "OAuth error='error!'"}
41 | has-expired-error-header {:WWW-Authenticate "OAuth error='expired_token'"}]
42 | (is (not (m/has-oauth-error? no-error-header)))
43 | (is (m/has-oauth-error? has-error-header))
44 | (is (m/has-oauth-error? has-expired-error-header))))
45 |
46 | (deftest test-expired?
47 | (let [no-error-resp {:headers {"foo" "bar"}}
48 | has-error-resp {:headers {"WWW-Authenticate" "OAuth error='error!'"}}
49 | has-expired-error-resp {:headers {"WWW-Authenticate" "OAuth error='expired_token'"}}]
50 | (is (not (m/expired? no-error-resp)))
51 | (is (not (m/expired? has-error-resp)))
52 | (is (m/expired? has-expired-error-resp))))
53 |
--------------------------------------------------------------------------------
/objc/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // mixi-objc
4 | //
5 |
6 | #import
7 |
8 | #define kMixiApiUri @"http://api.mixi-platform.com/2/people/@me/@self"
9 | #define kMixiUpgradeUri @"https://secure.mixi-platform.com/2/token"
10 | #define kMixiUpgradeParamsFormat @"grant_type=authorization_code&client_id=%@&client_secret=%@&code=%@&redirect_uri=%@"
11 | #define kMixiClientId @"YOUR CLIENT ID"
12 | #define kMixiClientSecret @"YOUR CLIENT SECRET"
13 | #define kMixiRedirectUri @"YOUR REDIRECT URI"
14 |
15 | // JSONのパース?はいい加減なので参考にしないでください。
16 | NSString* getAccessToken(NSString* json) {
17 | NSRange match = [json rangeOfString:@"\"access_token\":\""];
18 | if (match.location != NSNotFound) {
19 | match.location += match.length;
20 | match.length = 40;
21 | return [json substringWithRange:match];
22 | } else {
23 | return nil;
24 | }
25 | }
26 |
27 | int main (int argc, const char * argv[])
28 | {
29 |
30 | NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
31 |
32 | if (argc < 2) {
33 | NSLog(@"authcode is mandatory.");
34 | return 1;
35 | }
36 | NSString *code = [[[NSString alloc] initWithCString:argv[1] encoding:NSUTF8StringEncoding] autorelease];
37 |
38 | NSURL *url = [[[NSURL alloc] initWithString:kMixiUpgradeUri] autorelease];
39 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
40 | request.HTTPMethod = @"POST";
41 | request.HTTPBody = [[NSString stringWithFormat:kMixiUpgradeParamsFormat, kMixiClientId, kMixiClientSecret, code, kMixiRedirectUri] dataUsingEncoding:NSUTF8StringEncoding];
42 | NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
43 | NSString *json = [[[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding] autorelease];
44 | NSString *accessToken = getAccessToken(json);
45 |
46 | url = [[[NSURL alloc] initWithString:kMixiApiUri] autorelease];
47 | request = [NSMutableURLRequest requestWithURL:url];
48 | [request setValue:[NSString stringWithFormat:@"OAuth %@", accessToken] forHTTPHeaderField:@"Authorization"];
49 | result = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
50 | json = [[[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding] autorelease];
51 | NSLog(@"%@", json);
52 |
53 | [pool drain];
54 | return 0;
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/erlang/mixi.erl:
--------------------------------------------------------------------------------
1 | -module(mixi).
2 | -export([get_token/4,
3 | get_my_friends/1]).
4 |
5 | get_token(AuthorizationCode,
6 | ClientId,
7 | ClientSecret,
8 | RedirectUri) ->
9 | Response = httpc:request(
10 | post,
11 | {
12 | "https://secure.mixi-platform.com/2/token",
13 | [],
14 | "application/x-www-form-urlencoded",
15 | lists:append([
16 | "grant_type=authorization_code",
17 | "&client_id=", ClientId,
18 | "&client_secret=", ClientSecret,
19 | "&redirect_uri=", edoc_lib:escape_uri(RedirectUri),
20 | "&code=", AuthorizationCode
21 | ])
22 | },
23 | [],
24 | []),
25 | parse_response(Response,
26 | fun(Json) ->
27 | { get_property_value("access_token", Json),
28 | get_property_value("refresh_token", Json) }
29 | end
30 | ).
31 |
32 | get_my_friends(AccessToken) ->
33 | Response = httpc:request(
34 | get,
35 | {
36 | "http://api.mixi-platform.com/2/people/@me/@friends",
37 | [
38 | {"Authorization", lists:append("OAuth ", AccessToken)}
39 | ]
40 | },
41 | [],
42 | []),
43 | parse_response(Response,
44 | fun(Json) ->
45 | Json
46 | end
47 | ).
48 |
49 | parse_response({ok, {{_, 200, _}, _, Body}}, F) ->
50 | {struct, Json} = mochijson2:decode(Body),
51 | F(Json);
52 | parse_response({ok, {{_, Status, _}, Headers, Body}}, _) ->
53 | case lists:keyfind("www-authenticate", 1, Headers) of
54 | {_, Reason} ->
55 | throw(
56 | { Status,
57 | Reason }
58 | );
59 | _ ->
60 | {struct, Error} = mochijson2:decode(Body),
61 | throw(
62 | { Status,
63 | get_property_value("error", Error),
64 | get_property_value("error_description", Error) }
65 | )
66 | end.
67 |
68 | get_property_value(KeyName, Json) ->
69 | case lists:keyfind(list_to_binary(KeyName), 1, Json) of
70 | {_, Value} ->
71 | binary_to_list(Value);
72 | _ ->
73 | []
74 | end.
75 |
--------------------------------------------------------------------------------
/Python/mixi.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | from google.appengine.ext import webapp
5 | from google.appengine.ext.webapp import util
6 | import os
7 | from google.appengine.ext.webapp import template
8 | from google.appengine.ext.webapp.util import run_wsgi_app
9 | from google.appengine.api import urlfetch
10 | import urllib
11 | from django.utils import simplejson
12 |
13 | AUTHORIZATION_URL_BASE = "https://mixi.jp/connect_authorize.pl?"
14 | REDIRECTION_URI = "http://localhost:8080/redirect"
15 | TOKEN_ENDPOINT = "https://secure.mixi-platform.com/2/token"
16 | FRIENDS_TIMELINE_ENDPOINT = "http://api.mixi-platform.com/2/people/@me/@friends"
17 |
18 | CONSUMER_KEY = "*******************"
19 | CONSUMER_SECRET = "**************************************"
20 |
21 | class MainHandler(webapp.RequestHandler):
22 |
23 | def get_access_token(self,auth_code):
24 |
25 | token_params = {
26 | "grant_type":"authorization_code",
27 | "client_id":CONSUMER_KEY,
28 | "client_secret":CONSUMER_SECRET,
29 | "code":auth_code,
30 | "redirect_uri":REDIRECTION_URI,
31 | }
32 | form_data = urllib.urlencode(token_params)
33 | result = urlfetch.fetch(url=TOKEN_ENDPOINT,
34 | payload=form_data,
35 | method=urlfetch.POST,
36 | headers={'Content-Type':'application/x-www-form-urlencoded'})
37 |
38 | json = simplejson.loads(result.content)
39 | return json['access_token']
40 |
41 | def get_friends_timeline(self,access_token):
42 | result = urlfetch.fetch(url=FRIENDS_TIMELINE_ENDPOINT,
43 | method=urlfetch.GET,
44 | headers={'Authorization':'OAuth %s'%access_token})
45 | return simplejson.loads(result.content)
46 |
47 | def get(self, mode=""):
48 |
49 | if mode == "login":
50 |
51 | query = {
52 | "client_id":CONSUMER_KEY,
53 | "response_type":"code",
54 | "scope":"r_profile",
55 | }
56 | url = AUTHORIZATION_URL_BASE + urllib.urlencode(query)
57 | self.redirect(url)
58 |
59 | if mode == "redirect":
60 |
61 | auth_code = self.request.get("code")
62 | access_token = self.get_access_token(auth_code)
63 |
64 | results = self.get_friends_timeline(access_token)
65 |
66 | template_values = {'results': results['entry'],}
67 | path = os.path.join(os.path.dirname(__file__), 'mixi.html')
68 | self.response.out.write(template.render(path, template_values))
69 |
70 | def main():
71 | application = webapp.WSGIApplication([('/(.*)', MainHandler)],
72 | debug=True)
73 | util.run_wsgi_app(application)
74 |
75 | if __name__ == '__main__':
76 | main()
--------------------------------------------------------------------------------
/Clojure/src/clj_mixi_graph_api/core.clj:
--------------------------------------------------------------------------------
1 | (ns clj-mixi-graph-api.core
2 | (:require [com.twinql.clojure.http :as http])
3 | (:require [clj-json.core :as json]))
4 |
5 | (def consumer-info
6 | {:key "xxxxxxxxxxxxxxxxxxxx"
7 | :secret "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
8 | :redirect-uri "https://mixi.jp/connect_authorize_success.html"})
9 |
10 | (def endpoint
11 | {:token "https://secure.mixi-platform.com/2/token"
12 | :api "http://api.mixi-platform.com/2"})
13 |
14 | (defstruct token-info :refresh-token :access-token :expires-in)
15 | (defn mk-token
16 | "make token-info structure from json-parsed response of request or refresh token"
17 | [parsed-resp]
18 | (let [{:strs [refresh_token access_token expires_in]} parsed-resp]
19 | (struct token-info refresh_token access_token expires_in)))
20 |
21 | (defstruct person :id :thumbnail-url :display-name :profile-url)
22 | (defn mk-person
23 | "make person structure from people element"
24 | [data]
25 | (let [{:strs [id thumbnailUrl displayName profileUrl]} data]
26 | (struct person id thumbnailUrl displayName profileUrl)))
27 |
28 | (defn post-to-token-with
29 | "post request to token end point with query"
30 | [query]
31 | (http/post (endpoint :token)
32 | :query (assoc query :client_id (consumer-info :key)
33 | :client_secret (consumer-info :secret))
34 | :as :string))
35 |
36 | (defn request-access-token [code]
37 | (post-to-token-with
38 | {:grant_type "authorization_code"
39 | :code code
40 | :redirect_uri (consumer-info :redirect-uri)}))
41 |
42 | (defn refresh-access-token [token-info]
43 | (post-to-token-with
44 | {:grant_type "refresh_token"
45 | :refresh_token token-info}))
46 |
47 | (defn get-token
48 | "get token-info structure from response"
49 | [{content :content}]
50 | (mk-token (json/parse-string content)))
51 |
52 | (defn read-people
53 | [{token-info :token
54 | user-id :user-id
55 | group-id :group-id
56 | res-format :format}]
57 | (http/get (str (endpoint :api) "/people/" user-id "/" group-id)
58 | :query {:format res-format
59 | :oauth_token (token-info :access-token)}
60 | :as :string))
61 |
62 | (defn build-headers [headers]
63 | (reduce
64 | (fn [res header] (assoc res (keyword (first header)) (second header)))
65 | {}
66 | headers))
67 |
68 | (defn get-oauth-error [{oauth-error :WWW-Authenticate}]
69 | (nth (re-find #"OAuth error='(.+)'" oauth-error) 1))
70 |
71 | (defn has-oauth-error? [{oauth-error :WWW-Authenticate}]
72 | (not (nil? oauth-error)))
73 |
74 | (defn expired? [resp]
75 | (let [built-headers (build-headers (:headers resp))]
76 | (and
77 | (has-oauth-error? built-headers)
78 | (= "expired_token" (get-oauth-error built-headers)))))
79 |
80 | (defn get-my-friends
81 | "sample of accessing a protected resource"
82 | [token-info]
83 | (let [resp (read-people {:token token-info
84 | :user-id "@me"
85 | :group-id "@friends"
86 | :format "json"})]
87 | (if (expired? resp)
88 | (recur (get-token (refresh-access-token (:refresh-token token-info))))
89 | (map mk-person (get (json/parse-string (:content resp)) "entry")))))
90 |
--------------------------------------------------------------------------------
/Perl/sample.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 |
3 | use strict;
4 | use warnings;
5 |
6 | use constant {
7 | CONSUMER_KEY => '[YOUR CONSUMER KEY]',
8 | CONSUMER_SECRET => '[YOUR CONSUMER SECRET]',
9 | REDIRECT_URI => '[YOUR REDIRECT URI]',
10 |
11 | MIXI_TOKEN_ENDPOINT => 'https://secure.mixi-platform.com/2/token',
12 | MIXI_API_ENDPOINT => 'http://api.mixi-platform.com/2'
13 | };
14 |
15 | use URI::Escape qw/ uri_escape /;
16 | use HTTP::Request;
17 | use LWP::UserAgent;
18 | use JSON::XS;
19 | use Data::Dumper;
20 |
21 | sub request {
22 | my ($method, $url, $data_arr) = @_;
23 |
24 | my $req = HTTP::Request->new(
25 | $method => $url
26 | );
27 |
28 | if ($method eq 'POST') {
29 | my $data_str = join '&', map { uri_escape($_) . '=' . uri_escape($data_arr->{$_}) } keys %$data_arr;
30 | $req->content_type('application/x-www-form-urlencoded');
31 | $req->content($data_str);
32 | }
33 |
34 | my $ua = LWP::UserAgent->new();
35 | my $res = $ua->request($req);
36 |
37 | return $res;
38 | }
39 |
40 | sub get_token {
41 | my $auth_code = shift;
42 |
43 | my %data_arr = (
44 | 'grant_type' => 'authorization_code',
45 | 'client_id' => CONSUMER_KEY,
46 | 'client_secret' => CONSUMER_SECRET,
47 | 'code' => $auth_code,
48 | 'redirect_uri' => REDIRECT_URI,
49 | );
50 |
51 | my $res = request('POST', MIXI_TOKEN_ENDPOINT, \%data_arr);
52 | die 'Request failed. ' . $res->status_line unless $res->is_success;
53 |
54 | return decode_json($res->content);
55 | }
56 |
57 | sub get_new_token {
58 | my $refresh_token = shift;
59 |
60 | my %data_arr = (
61 | 'grant_type' => 'refresh_token',
62 | 'client_id' => CONSUMER_KEY,
63 | 'client_secret' => CONSUMER_SECRET,
64 | 'refresh_token' => $refresh_token,
65 | );
66 |
67 | my $res = request('POST', MIXI_TOKEN_ENDPOINT, \%data_arr);
68 | die 'Request failed. ' . $res->status_line unless $res->is_success;
69 |
70 | return decode_json($res->content);
71 | }
72 |
73 | sub call {
74 | my ($endpoint, $token) = @_;
75 |
76 | my $url = MIXI_API_ENDPOINT . $endpoint . '?oauth_token=' . uri_escape($token->{'access_token'});
77 | my $res = request('GET', $url);
78 |
79 | if (defined $res->header('WWW-Authenticate')) {
80 | my $error_msg = $res->header('WWW-Authenticate');
81 |
82 | if ($error_msg =~ /invalid_request/) {
83 | die 'Invalid request.';
84 | } elsif ($error_msg =~ /invalid_token/) {
85 | die 'Invalid token.';
86 | } elsif ($error_msg =~ /expired_token/) {
87 | $token = get_new_token($token->{'refresh_token'});
88 | $url = MIXI_API_ENDPOINT . $endpoint . '?oauth_token=' . uri_escape($token->{'access_token'});
89 | return decode_json(request('GET', $url)->{'_content'});
90 | } elsif ($error_msg =~ /insufficient_scope/) {
91 | die 'Insufficient scope.';
92 | }
93 | }
94 |
95 | return decode_json($res->content);
96 | }
97 |
98 | my $auth_code = $ARGV[0];
99 | my $token = get_token($auth_code);
100 | my $json_href = call('/people/@me/@self', $token);
101 |
102 | print Data::Dumper::Dumper($json_href);
103 |
104 | 1;
105 |
106 |
--------------------------------------------------------------------------------
/bash/mixi.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | CONSUMER_KEY='****'
4 | CONSUMER_SECRET='****'
5 | REDIRECT_URI='****'
6 |
7 | echo_json() {
8 | local json=$1
9 |
10 | local cmd_json_xs=`which json_xs 2>/dev/null`
11 | if [ $cmd_json_xs ]; then
12 | echo "$json" | $cmd_json_xs 2>/dev/null
13 | local retval=$?
14 | if [ $retval -eq 0 ]; then
15 | return
16 | fi
17 | fi
18 |
19 | echo "$json"
20 | }
21 |
22 | auth() {
23 | local code=$1
24 | local result=`curl -d grant_type=authorization_code \
25 | -d client_id=$CONSUMER_KEY \
26 | -d client_secret=$CONSUMER_SECRET \
27 | -d code=$code \
28 | -d redirect_uri=$REDIRECT_URI \
29 | https://secure.mixi-platform.com/2/token \
30 | 2>/dev/null`
31 | local retval=$?
32 | if [ $retval -ne 0 ]; then
33 | echo "curl error" >&2
34 | return 1
35 | fi
36 |
37 | echo_json "$result"
38 | return 0
39 | }
40 |
41 | refresh() {
42 | local token=$1
43 | local result=`curl -d grant_type=refresh_token \
44 | -d client_id=$CONSUMER_KEY \
45 | -d client_secret=$CONSUMER_SECRET \
46 | -d refresh_token=$token \
47 | https://secure.mixi-platform.com/2/token \
48 | 2>/dev/null`
49 | local retval=$?
50 | if [ $retval -ne 0 ]; then
51 | echo "curl error" >&2
52 | return 1
53 | fi
54 |
55 | echo_json "$result"
56 | return 0
57 | }
58 |
59 | people() {
60 | local type=$1
61 | local token=$2
62 | local result=`curl -w "\n%{http_code}" \
63 | https://secure.mixi-platform.com/2/people/@me/@$type?oauth_token=$token \
64 | 2>/dev/null`
65 | local retval=$?
66 | if [ $retval -ne 0 ]; then
67 | echo "curl error" >&2
68 | return 1
69 | fi
70 |
71 | local http_code=`echo "$result" | tail -n 1`
72 | if [ $http_code -ne 200 ]; then
73 | echo "ERROR (HTTP CODE = $http_code)" >&2
74 | return 1
75 | fi
76 |
77 | local line_count=`echo "$result" | wc -l`
78 | local content_line_count=`expr $line_count - 1`
79 | local content=`echo "$result" | head -n $content_line_count`
80 |
81 | echo_json "$content"
82 |
83 | return 0
84 | }
85 |
86 | usage() {
87 | echo "Usage: $0 {auth|refresh|people} OPTIONS" >&2
88 | }
89 |
90 | usage_auth() {
91 | echo "Usage: $0 auth CODE" >&2
92 | }
93 |
94 | usage_refresh() {
95 | echo "Usage: $0 refresh REFRESH_TOKEN" >&2
96 | }
97 |
98 | usage_people() {
99 | echo "Usage: $0 people {self|friends} ACCESS_TOKEN" >&2
100 | }
101 |
102 | retval=1
103 |
104 | case "$1" in
105 | auth | refresh)
106 | if [ $# -ne 2 ]; then
107 | usage_$1
108 | retval=1
109 | else
110 | $1 $2
111 | retval=$?
112 | fi
113 | ;;
114 | people)
115 | if [ $# -ne 3 ]; then
116 | usage_people
117 | retval=1
118 | else
119 | case "$2" in
120 | self | friends)
121 | people $2 $3
122 | retval=$?
123 | ;;
124 | *)
125 | usage_people
126 | retval=1
127 | ;;
128 | esac
129 | fi
130 | ;;
131 | *)
132 | usage
133 | retval=1
134 | ;;
135 | esac
136 |
137 | exit $retval
138 |
139 |
--------------------------------------------------------------------------------
/c/mixi.c:
--------------------------------------------------------------------------------
1 | #include "utils.h"
2 | #include "http.h"
3 | #include "mixi.h"
4 |
5 | void send_issue_token_request(struct client_credential cc,
6 | char* authorization_code,
7 | char* host,
8 | char* path,
9 | SSL* ssl) {
10 | int ret;
11 | int len;
12 | int digit;
13 | char* post_body;
14 | char* request;
15 | char* post_body_len;
16 |
17 | post_body =
18 | new_concat_strings(8,
19 | "grant_type=authorization_code&client_id=",
20 | cc.client_id,
21 | "&client_secret=",
22 | cc.client_secret,
23 | "&redirect_uri=",
24 | cc.redirect_uri,
25 | "&code=",
26 | authorization_code);
27 | len = (int)(strlen(post_body));
28 | digit = get_integer_digit(len);
29 | post_body_len = malloc(digit + 1);
30 | sprintf(post_body_len, "%d", len);
31 | request =
32 | new_concat_strings(11,
33 | "POST ",
34 | path,
35 | " HTTP/1.1\r\n",
36 | "Host: ",
37 | host,
38 | "\r\n",
39 | "Content-Type: application/x-www-form-urlencoded\r\n",
40 | "Content-Length: ",
41 | post_body_len,
42 | "\r\n\r\n",
43 | post_body);
44 | send_http_request(HTTPS, request, 0, ssl);
45 |
46 | free(post_body);
47 | free(post_body_len);
48 | free(request);
49 | }
50 |
51 | void send_get_my_profile_request(char* access_token,
52 | char* host,
53 | char* path,
54 | int s) {
55 | char* request;
56 | int ret;
57 |
58 | request =
59 | new_concat_strings(10,
60 | "GET ",
61 | path,
62 | " HTTP/1.1\r\n",
63 | "Host: ",
64 | host,
65 | "\r\n",
66 | "Accept: application/json\r\n",
67 | "Authorization: OAuth ",
68 | access_token,
69 | "\r\n\r\n");
70 | send_http_request(HTTP, request, s, NULL);
71 |
72 | free(request);
73 | }
74 |
75 | struct http_response issue_token(struct client_credential cc,
76 | char* authorization_code) {
77 | char* host;
78 | char* path;
79 | char* response;
80 | int ret;
81 | int s;
82 | struct ssl_info ssl;
83 | struct http_response result;
84 |
85 | host = "secure.mixi-platform.com";
86 | path = "/2/token";
87 |
88 | s = connect_to_server(host, 443, path);
89 | ssl = ssl_initialize(s);
90 |
91 | send_issue_token_request(cc, authorization_code, host, path, ssl.ssl);
92 | response = receive_http_response(HTTPS, 0, ssl.ssl);
93 |
94 | close_connection(HTTPS, s, &ssl);
95 |
96 | result.status_code = get_http_status_code(response);
97 | result.body = new_http_response_body(response);
98 |
99 | free(response);
100 | return result;
101 | }
102 |
103 | struct http_response get_my_profile(char* access_token) {
104 | int s;
105 | char* host;
106 | char* path;
107 | char* response;
108 | struct http_response result;
109 |
110 | host = "api.mixi-platform.com";
111 | path = "/2/people/@me/@self";
112 |
113 | s = connect_to_server(host, 80, path);
114 | send_get_my_profile_request(access_token, host, path, s);
115 | response = receive_http_response(HTTP, s, NULL);
116 |
117 | close_connection(HTTP, s, NULL);
118 |
119 | result.status_code = get_http_status_code(response);
120 |
121 | result.body = new_http_response_body(response);
122 |
123 | free(response);
124 | return result;
125 | }
126 |
--------------------------------------------------------------------------------
/cs/Main.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using System.Net;
4 | using System.Web.Script.Serialization;
5 | using System.Collections.Generic;
6 | using System.Collections.Specialized;
7 |
8 | namespace MixiGraphAPIExample
9 | {
10 | class MainClass
11 | {
12 | private const string CONSUMER_KEY = "[YOUR CONSUMER KEY]";
13 | private const string CONSUMER_SECRET = "[YOUR CONSUMER SECRET]";
14 | private const string REDIRECT_URL = "[YOUR REDIRECT URL]";
15 |
16 | public static void Main (string[] args)
17 | {
18 | MixiAPIClient client = new MixiAPIClient(CONSUMER_KEY,CONSUMER_SECRET,REDIRECT_URL);
19 |
20 | Console.WriteLine("1. Open this url and allow your application access.");
21 | Console.WriteLine(client.GetAuthorizeUrl());
22 |
23 | Console.WriteLine("2. Input 'code' parameter value of redirected url.");
24 | string code = Console.ReadLine();
25 | client.GetToken(code);
26 |
27 | Console.WriteLine("----");
28 | string resText = client.Call("/people/@me/@self");
29 | Dictionary result = MixiAPIClient.JsonToDictionary(resText);
30 | Dictionary entry = (Dictionary)result["entry"];
31 | foreach(string key in entry.Keys){
32 | Console.WriteLine(key + " : " + entry[key]);
33 | }
34 | }
35 | }
36 |
37 | class MixiAPIClient
38 | {
39 | private const string MIXI_TOKEN_ENDPOINT = "https://secure.mixi-platform.com/2/token";
40 | private const string MIXI_API_ENDPOINT = "http://api.mixi-platform.com/2";
41 | private const string MIXI_AUTHORIZE_URL = "https://mixi.jp/connect_authorize.pl";
42 |
43 | private string consumer_key;
44 | private string consumer_secret;
45 | private string redirect_url;
46 |
47 | public string token = "";
48 | public string refreshToken = "";
49 |
50 | public static Dictionary JsonToDictionary(string jsonText)
51 | {
52 | JavaScriptSerializer serializer = new JavaScriptSerializer();
53 | return serializer.Deserialize>(jsonText);
54 | }
55 |
56 | public MixiAPIClient(string consumer_key, string consumer_secret, string redirect_url)
57 | {
58 | this.consumer_key = consumer_key;
59 | this.consumer_secret = consumer_secret;
60 | this.redirect_url = redirect_url;
61 | }
62 |
63 | public string GetAuthorizeUrl()
64 | {
65 | return MIXI_AUTHORIZE_URL + "?scope=r_profile&client_id=" + consumer_key;
66 | }
67 |
68 | public void GetToken(string authorizationCode)
69 | {
70 | NameValueCollection data = new NameValueCollection();
71 | data.Add ("grant_type","authorization_code");
72 | data.Add ("client_id",consumer_key);
73 | data.Add ("client_secret",consumer_secret);
74 | data.Add ("redirect_uri",redirect_url);
75 | data.Add ("code",authorizationCode);
76 | WebClient wc = new WebClient();
77 | Byte[] resData = wc.UploadValues(MIXI_TOKEN_ENDPOINT, data);
78 | string resText = Encoding.UTF8.GetString(resData);
79 | Dictionary result = MixiAPIClient.JsonToDictionary(resText);
80 | token = result["access_token"].ToString();
81 | refreshToken = result["refresh_token"].ToString();
82 | }
83 |
84 | public string Call(string endpoint)
85 | {
86 | string url = MIXI_API_ENDPOINT + endpoint + "?oauth_token=" + token;
87 | WebClient wc = new WebClient();
88 | byte[] resData = wc.DownloadData(url);
89 | return Encoding.UTF8.GetString(resData);
90 | }
91 | }
92 | }
93 |
94 |
--------------------------------------------------------------------------------
/scala/src/main/scala/example02/Main.scala:
--------------------------------------------------------------------------------
1 | package example02
2 |
3 | import scala.annotation.tailrec
4 | import dispatch.json.{Js, JsObject, JsString, JsValue}
5 | import org.apache.commons.httpclient.{HttpClient, HttpMethodBase, HttpStatus}
6 | import org.apache.commons.httpclient.methods.{GetMethod, PostMethod}
7 |
8 | trait Response
9 | case class Ok(body: java.io.InputStream) extends Response
10 | case class Unauthorized(headers: Map[String, String]) extends Response
11 |
12 | object Conversions {
13 | implicit def jsObject2Map(js: JsObject): Map[JsString, JsValue] = js.self
14 | implicit def jsString2String(js: JsString): String = js.self
15 | implicit def string2JsString(value: String): JsString = JsString(value)
16 |
17 | implicit def any2Caster[T](value: T): Caster[T] = new Caster[T](value)
18 | class Caster[T](value: T) {
19 | def as[U<:T:Manifest]: Option[U] =
20 | if (manifest[U].erasure.isInstance(value)) Some[U](value.asInstanceOf[U])
21 | else None
22 | }
23 | }
24 |
25 | object Main extends App {
26 | import Conversions._
27 |
28 | val CONSUMER_KEY = ""
29 | val CONSUMER_SECRET = ""
30 | val REDIRECT_URI = "http://mixi.jp/connect_authorize_success.html"
31 | val REQUEST_TOKEN_BASE_PARAMS = Map("client_id" -> CONSUMER_KEY,
32 | "client_secret" -> CONSUMER_SECRET)
33 |
34 | for {
35 | authorizationCode <- args.headOption
36 | tokens <- getTokens(authorizationCode)
37 | friends <- get(tokens, "/people/@me/@friends")
38 | } println(friends)
39 |
40 | def getTokens(authorizationCode: String): Option[(String, String)] =
41 | retrieveTokens(REQUEST_TOKEN_BASE_PARAMS +
42 | ("grant_type" -> "authorization_code") +
43 | ("code" -> authorizationCode) +
44 | ("redirect_uri" -> REDIRECT_URI))
45 |
46 | def refreshTokens(refreshToken: String): Option[(String, String)] =
47 | retrieveTokens(REQUEST_TOKEN_BASE_PARAMS +
48 | ("grant_type" -> "refresh_token") +
49 | ("refresh_token" -> refreshToken))
50 |
51 | def retrieveTokens(params: Map[String, String]): Option[(String, String)] =
52 | using(new PostMethod("https://secure.mixi-platform.com/2/token")) { method =>
53 | for ((name, value) <- params) method.addParameter(name, value)
54 | for {
55 | response <- executeHttpMethod(method)
56 | Ok(body) <- response.as[Ok]
57 | x <- Js(body).as[JsObject]
58 | refreshToken <- x.get("refresh_token").flatMap(_.as[JsString])
59 | accessToken <- x.get("access_token").flatMap(_.as[JsString])
60 | } yield (refreshToken, accessToken)
61 | }
62 |
63 | val OAuthError = """\s*OAuth\s+error='([^']+)'""".r
64 | @tailrec
65 | def get(tokens: (String, String), path: String): Option[JsValue] = {
66 | def _get(accessToken: String, url: String): Either[Symbol, JsValue] =
67 | using(new GetMethod(url)) { method =>
68 | method.setDoAuthentication(false)
69 | method.addRequestHeader("Authorization", "OAuth " + accessToken)
70 | executeHttpMethod(method) match {
71 | case Some(Ok(body)) => Right(Js(body))
72 | case Some(Unauthorized(headers)) => Left(
73 | headers.get("WWW-Authenticate") match {
74 | case Some(OAuthError(reason)) => Symbol(reason)
75 | case _ => 'unauthorized
76 | })
77 | case _ => Left('other)
78 | }
79 | }
80 |
81 | _get(tokens._2, "http://api.mixi-platform.com/2" + path) match {
82 | case Right(result) => Some(result)
83 | case Left('expired_token) => refreshTokens(tokens._1) match {
84 | case Some(nextTokens) => get(nextTokens, path)
85 | case _ => None
86 | }
87 | case _ => None
88 | }
89 | }
90 |
91 | def executeHttpMethod(method: HttpMethodBase): Option[Response] =
92 | new HttpClient executeMethod(method) match {
93 | case HttpStatus.SC_OK => Some(Ok(method.getResponseBodyAsStream))
94 | case HttpStatus.SC_UNAUTHORIZED => Some(Unauthorized(
95 | method.getResponseHeaders
96 | .map { x => x.getName -> x.getValue } toMap
97 | ))
98 | case _ => None
99 | }
100 |
101 | def using[A <: HttpMethodBase, B](method: A)(block: A => B): B =
102 | try { block(method) }
103 | finally { method.releaseConnection }
104 | }
105 |
--------------------------------------------------------------------------------
/PHP/sample.php:
--------------------------------------------------------------------------------
1 | authorize($auth_code);
15 | }
16 |
17 | private function post($uri, $data) {
18 | $context = array('http' => array (
19 | 'method' => 'POST',
20 | 'header' => 'Content-Type: application/x-www-form-urlencoded',
21 | 'content' => http_build_query($data, null, '&'),
22 | 'ignore_errors' => true,
23 | ));
24 | $body = file_get_contents($uri, false, stream_context_create($context));
25 | $header = $this->parseHeader($http_response_header);
26 | if ($this->isHttpFail($header['Status'])) {
27 | throw new UnexpectedValueException('Post Request Fail:'.PHP_EOL.$uri.PHP_EOL.var_export($header, true));
28 | }
29 | return $body;
30 | }
31 |
32 | private function authorize($auth_code) {
33 | $data = array(
34 | 'grant_type' => 'authorization_code',
35 | 'client_id' => CONSUMER_KEY,
36 | 'client_secret' => CONSUMER_SECRET,
37 | 'code' => $auth_code,
38 | 'redirect_uri' => REDIRECT_URI,
39 | );
40 | $this->token = json_decode($this->post(self::MIXI_TOKEN_ENDPOINT, $data), true);
41 | }
42 |
43 | private function refreshToken() {
44 | $data = array(
45 | 'grant_type' => 'refresh_token',
46 | 'client_id' => CONSUMER_KEY,
47 | 'client_secret' => CONSUMER_SECRET,
48 | 'refresh_token' => $this->token['refresh_token'],
49 | );
50 | $this->token = json_decode($this->post(self::MIXI_TOKEN_ENDPOINT, $data), true);
51 | }
52 |
53 | private function parseHeader($headers) {
54 | $statusLine = array_shift($headers);
55 | list(, $result['Status'], ) = explode(' ', $statusLine);
56 | foreach ($headers as $header) {
57 | list($key, $value) = explode(': ', $header);
58 | $result[$key] = $value;
59 | }
60 | return $result;
61 | }
62 |
63 | private function isHttpFail($status) {
64 | return (bool)(empty($status) || ($status >= 400));
65 | }
66 |
67 | private function isExpired($headers) {
68 | $result = false;
69 | if (array_key_exists('WWW-Authenticate', $headers)) {
70 | if (preg_match('/expired_token/', $headers['WWW-Authenticate'])) {
71 | $result = true;
72 | }
73 | }
74 | return $result;
75 | }
76 |
77 | private function call($location) {
78 | static $retry_count = 0;
79 |
80 | $uri = self::MIXI_API_ENDPOINT . $location . '?oauth_token=' . $this->token['access_token'];
81 | $response = file_get_contents($uri, false, stream_context_create(array('http' => array('ignore_errors' => true))));
82 | $header = $this->parseHeader($http_response_header);
83 |
84 | if ($this->isHttpFail($header['Status'])) {
85 | if ($this->isExpired($header)) {
86 | if ($retry_count++ > 1) {
87 | throw new RangeException('Token Refresh Too many retry. '.PHP_EOL.var_export($this->token, true).PHP_EOL.var_export($header, true));
88 | }
89 |
90 | $this->refreshToken();
91 | $response = $this->call($location);
92 | $retry_count = 0;
93 | } else {
94 | throw new UnexpectedValueException('Invalid API Access:'.PHP_EOL.$uri.PHP_EOL.var_export($header, true));
95 | }
96 | }
97 |
98 | return $response;
99 | }
100 |
101 | public function execute($endpoint) {
102 | return json_decode($this->call($endpoint), true);
103 | }
104 |
105 | public static function getInstance($auth_code) {
106 | return new self($auth_code);
107 | }
108 | }
109 |
110 | if (debug_backtrace()) return;
111 | if ($_SERVER['argc'] != 2) {
112 | exit("Please input your Authorization Code\n Usage : {$_SERVER['argv'][0]} [YOUR AUTHORIZATION CODE]\n");
113 | }
114 |
115 | try {
116 | $response = \MixiGraphAPIExample::getInstance($_SERVER['argv'][1])->execute('/people/@me/@self');
117 | var_dump($response);
118 | } catch (Exception $e) {
119 | var_dump($e->getMessage());
120 | }
121 |
--------------------------------------------------------------------------------
/Java/Mixi.java:
--------------------------------------------------------------------------------
1 | import java.net.URL;
2 | import java.net.HttpURLConnection;
3 | import java.net.URLEncoder;
4 | import java.io.PrintWriter;
5 | import java.io.InputStream;
6 | import java.io.BufferedInputStream;
7 | import java.io.ByteArrayOutputStream;
8 | import java.io.OutputStreamWriter;
9 | import java.io.IOException;
10 | import java.io.UnsupportedEncodingException;
11 |
12 | public class Mixi {
13 |
14 | private static final String CLIENT_ID = "YOUR Client ID";
15 | private static final String CLIENT_SECRET = "YOUR Client secret";
16 | private static final String REDIRECT_URI = "YOUR Redirect URI";
17 |
18 | private String accessToken;
19 |
20 | public void authorize(String authorizationCode) throws IOException {
21 | PrintWriter out = null;
22 | try {
23 | String params = buildParamsForAuthorization(authorizationCode);
24 | URL url = new URL("https://secure.mixi-platform.com/2/token");
25 | HttpURLConnection connection = (HttpURLConnection)url.openConnection();
26 | connection.setDoOutput(true);
27 | out = new PrintWriter(new OutputStreamWriter(
28 | connection.getOutputStream(), "UTF-8"));
29 | out.print(params);
30 | out.flush();
31 | int responseCode = connection.getResponseCode();
32 | if (responseCode == HttpURLConnection.HTTP_OK) {
33 | String responseBody = readStream(connection.getInputStream());
34 | accessToken = getPropertyValue(responseBody, "access_token");
35 | } else {
36 | String responseBody = readStream(connection.getErrorStream());
37 | throw new IOException(responseCode + ": " + responseBody);
38 | }
39 | } finally {
40 | if (out != null) {
41 | out.close();
42 | }
43 | }
44 | }
45 |
46 | public String call(String endpoint) throws IOException {
47 | URL url = new URL("http://api.mixi-platform.com/2" + endpoint);
48 | HttpURLConnection connection = (HttpURLConnection)url.openConnection();
49 | connection.setRequestProperty("Authorization", "OAuth " + accessToken);
50 | int responseCode = connection.getResponseCode();
51 | if (responseCode == HttpURLConnection.HTTP_OK) {
52 | String responseBody = readStream(connection.getInputStream());
53 | return responseBody;
54 | } else {
55 | String responseBody = readStream(connection.getErrorStream());
56 | throw new IOException(responseCode + ": " + responseBody);
57 | }
58 | }
59 |
60 | private String buildParamsForAuthorization(String authorizationCode) {
61 | try {
62 | StringBuilder sb = new StringBuilder();
63 | sb.append("client_id=");
64 | sb.append(CLIENT_ID);
65 | sb.append("&client_secret=");
66 | sb.append(CLIENT_SECRET);
67 | sb.append("&redirect_uri=");
68 | sb.append(URLEncoder.encode(REDIRECT_URI, "UTF-8"));
69 | sb.append("&code=");
70 | sb.append(authorizationCode);
71 | sb.append("&grant_type=authorization_code");
72 | return sb.toString();
73 | } catch(UnsupportedEncodingException e) {
74 | throw new IllegalStateException(e);
75 | }
76 | }
77 |
78 | private String readStream(InputStream in) throws IOException {
79 | ByteArrayOutputStream out = new ByteArrayOutputStream();
80 | try {
81 | byte[] buf = new byte[1024];
82 | int len = -1;
83 | BufferedInputStream bis = new BufferedInputStream(in, 1024);
84 | while((len = bis.read(buf, 0, 1024)) != -1) {
85 | out.write(buf);
86 | }
87 | return new String(out.toByteArray(), "UTF-8");
88 | } finally {
89 | try {
90 | out.close();
91 | } catch(IOException e) {
92 | throw new IllegalStateException(e);
93 | }
94 | }
95 | }
96 |
97 | private String getPropertyValue(String json, String propertyName) {
98 | String name = "\"" + propertyName + "\":\"";
99 | int pos = json.indexOf(name) + name.length();
100 | String value = json.substring(pos, json.indexOf("\"", pos + 1));
101 | return value;
102 | }
103 |
104 | public static void main(String[] args) throws IOException {
105 | if (args.length != 1) {
106 | throw new IllegalArgumentException("Authorization code is mandatory.");
107 | }
108 | String authorizationCode = args[0];
109 | Mixi mixi = new Mixi();
110 | mixi.authorize(authorizationCode);
111 | String response = mixi.call("/people/@me/@self");
112 | System.out.println(mixi.getPropertyValue(response, "displayName"));
113 | }
114 |
115 | }
--------------------------------------------------------------------------------
/c/http.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include "http.h"
7 |
8 | #define BUF_LEN 256
9 |
10 | char* new_json_property_value(char* json, char* property_name) {
11 | char* property;
12 | int len;
13 | char* base_pos;
14 | char* end_pos;
15 | char* result;
16 |
17 | len = strlen(property_name);
18 | property = malloc(len + 3);
19 | property[0] = '"';
20 | strncpy(property + 1, property_name, len);
21 | property[len + 1] = '"';
22 | property[len + 2] = '\0';
23 |
24 | base_pos = strstr(json, property);
25 | if (base_pos == NULL) {
26 | result = malloc(1);
27 | result[0] = '\0';
28 | } else {
29 | base_pos += strlen(property) + 2;
30 | end_pos = strstr(base_pos, "\"");
31 | len = (int)(end_pos - base_pos);
32 |
33 | result = malloc(len + 1);
34 | strncpy(result, base_pos, len);
35 | result[len] = '\0';
36 | }
37 |
38 | free(property);
39 | return result;
40 | }
41 |
42 | int get_http_status_code(const char* response) {
43 | char buf[4];
44 |
45 | strncpy(buf, response + 9, 3);
46 | buf[3] = '\0';
47 | return atoi(buf);
48 | }
49 |
50 | char* new_http_response_body(const char* response) {
51 | char* pos;
52 | char* result;
53 |
54 | pos = strstr(response, "\r\n\r\n") + 4;
55 | result = malloc(strlen(pos) + 1);
56 | strcpy(result, pos);
57 |
58 | return result;
59 | }
60 |
61 | int connect_to_server(char* host, int port, char* path) {
62 | int s;
63 |
64 | struct hostent* servhost;
65 | struct sockaddr_in server;
66 |
67 | servhost = gethostbyname(host);
68 | if (servhost == NULL) {
69 | fprintf(stderr, "Failed to change from [%s] to IP address.\n", host);
70 | exit(1);
71 | }
72 | memset((char*)&server, 0, sizeof(server));
73 | server.sin_family = AF_INET;
74 | memcpy((char*)&server.sin_addr, servhost->h_addr, servhost->h_length);
75 | server.sin_port = htons(port);
76 | s = socket(AF_INET, SOCK_STREAM, 0);
77 | if (s < 0) {
78 | fprintf(stderr, "Failed to create a socket.\n");
79 | exit(1);
80 | }
81 | if (connect(s, (struct sockaddr*)&server, sizeof(server)) == -1) {
82 | fprintf(stderr, "Failed to connect.\n");
83 | exit(1);
84 | }
85 |
86 | return s;
87 | }
88 |
89 | struct ssl_info ssl_initialize(int s) {
90 | int ret;
91 | unsigned short rand_ret;
92 |
93 | SSL* ssl;
94 | SSL_CTX* ctx;
95 |
96 | struct ssl_info result;
97 |
98 | SSL_load_error_strings();
99 | SSL_library_init();
100 | ctx = SSL_CTX_new(SSLv23_client_method());
101 | if (ctx == NULL) {
102 | ERR_print_errors_fp(stderr);
103 | exit(1);
104 | }
105 | ssl = SSL_new(ctx);
106 | if (ssl == NULL) {
107 | ERR_print_errors_fp(stderr);
108 | exit(1);
109 | }
110 | ret = SSL_set_fd(ssl, s);
111 | if (ret == 0) {
112 | ERR_print_errors_fp(stderr);
113 | exit(1);
114 | }
115 | RAND_poll();
116 | while(RAND_status() == 0) {
117 | rand_ret = rand() % 65536;
118 | RAND_seed(&rand_ret, sizeof(rand_ret));
119 | }
120 | ret = SSL_connect(ssl);
121 | if (ret != 1) {
122 | ERR_print_errors_fp(stderr);
123 | exit(1);
124 | }
125 |
126 | result.ssl = ssl;
127 | result.ctx = ctx;
128 | return result;
129 | }
130 |
131 | char* receive_http_response(enum ePROTOCOL protocol, int s, SSL* ssl) {
132 | int cnt;
133 | int sum;
134 | int read_size;
135 |
136 | char buf[BUF_LEN];
137 | char* response;
138 |
139 | response = malloc(BUF_LEN);
140 | cnt = 1;
141 | sum = 0;
142 | while(1) {
143 | if (protocol == HTTPS) {
144 | read_size = SSL_read(ssl, buf, sizeof(buf));
145 | } else {
146 | read_size = read(s, buf, sizeof(buf));
147 | }
148 | if (read_size > 0) {
149 | if ((sum + read_size + 1) > (BUF_LEN * cnt)) {
150 | response = realloc(response, BUF_LEN * ++cnt + 1);
151 | }
152 | memcpy(response + sum, buf, read_size);
153 | sum += read_size;
154 | } else if (read_size == 0) {
155 | response[sum] = '\0';
156 | break;
157 | } else {
158 | ERR_print_errors_fp(stderr);
159 | exit(1);
160 | }
161 | }
162 |
163 | return response;
164 | }
165 |
166 | void close_connection(enum ePROTOCOL protocol, int s, struct ssl_info* ssl) {
167 | int ret;
168 |
169 | if (protocol == HTTPS) {
170 | ret = SSL_shutdown(ssl->ssl);
171 | if (ret != 1) {
172 | ERR_print_errors_fp(stderr);
173 | exit(1);
174 | }
175 | SSL_free(ssl->ssl);
176 | SSL_CTX_free(ssl->ctx);
177 | ERR_free_strings();
178 | }
179 | close(s);
180 | }
181 |
182 | void send_http_request(enum ePROTOCOL protocol, char* request, int s, SSL* ssl) {
183 | int ret;
184 |
185 | if (protocol == HTTPS) {
186 | ret = SSL_write(ssl, request, strlen(request));
187 | } else {
188 | ret = write(s, request, strlen(request));
189 | }
190 | if (ret < 1) {
191 | ERR_print_errors_fp(stderr);
192 | exit(1);
193 | }
194 | }
195 |
--------------------------------------------------------------------------------
/cpp/sample.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "clx/https.h"
3 | #include "clx/uri.h"
4 | #include "clx/ssl.h"
5 | #include "clx/json.h"
6 |
7 | using namespace std;
8 |
9 | class mixi_client {
10 | public:
11 | mixi_client() {
12 | CLIENT_ID= "YOUR Client ID";
13 | CLIENT_SECRET = "YOUR Client secret";
14 | REDIRECT_URI = "YOUR Redirect URI";
15 | secure_host = "secure.mixi-platform.com";
16 | api_host = "api.mixi-platform.com";
17 | token_path = "/2/token/";
18 | }
19 |
20 | void get_auth_token(string auth_code) {
21 | mapheader;
22 | header.insert(map::value_type( "Content-Type","application/x-www-form-urlencoded" ) );
23 |
24 | clx::https httpClient(secure_host, 443);
25 | string query = get_auth_token_param(auth_code);
26 | httpClient.post(token_path, query, header);
27 | if (httpClient.code() != 200) {
28 | std::cout << "error" << std::endl << httpClient.body() << std::endl;
29 | return ;
30 | }
31 | clx::json response(httpClient.body());
32 | access_token = response["access_token"];
33 | refresh_token = response["refresh_token"];
34 | }
35 |
36 | clx::json get_people(string access_token, string user, string group, bool do_retry=true){
37 | mapheader;
38 | string token;
39 | token.append("OAuth ").append(access_token);
40 | header.insert(map::value_type("Authorization", token));
41 | header.insert(map::value_type("Content-Type", "application/x-www-form-urlencoded"));
42 | string path = "/2/people/";
43 | path.append(user).append("/")
44 | .append(group).append("/");
45 | clx::http httpClient(api_host);
46 | httpClient.get(clx::uri::encode(path), header);
47 | if (httpClient.code() != 200) {
48 | if (is_token_expired(httpClient) && do_retry) {
49 | return get_people(excahge_token(refresh_token),
50 | user, group, false);
51 | }
52 | std::cout << "error code:" << httpClient.code() << std::endl
53 | << httpClient.body() << std::endl;
54 | std::exit(-1);
55 | }
56 | clx::json results(httpClient.body());
57 | clx::json entity(results["entry"]);
58 | return entity;
59 | }
60 |
61 | clx::json get_people(string user, string group){
62 | return get_people(access_token,user,group);
63 | }
64 |
65 | private:
66 | const char* CLIENT_ID;
67 | const char* CLIENT_SECRET;
68 | const char* REDIRECT_URI;
69 | const char* secure_host;
70 | const char* api_host;
71 | const char* token_path;
72 | string access_token;
73 | string refresh_token;
74 |
75 | string excahge_token(string refresh_token) {
76 | mapheader;
77 | header.insert(map::value_type("Content-Type", "application/x-www-form-urlencoded"));
78 |
79 | clx::https httpClient(secure_host, 443);
80 | string query = get_refresh_token_param(refresh_token);
81 | httpClient.post(token_path, query, header);
82 | clx::json response(httpClient.body());
83 | access_token = response["access_token"];
84 | refresh_token = response["refresh_token"];
85 | return access_token;
86 | }
87 |
88 | bool is_token_expired(clx::http client){
89 | if (client.code() == 401) {
90 | if (client.head()["WWW-Authenticate"].length()) {
91 | return true;
92 | }
93 | }
94 | return false;
95 | }
96 |
97 | string get_refresh_token_param(string refresh_token) {
98 | ostringstream buff;
99 | buff << "client_id=" << CLIENT_ID
100 | << "&client_secret=" << CLIENT_SECRET
101 | << "&refresh_token=" << refresh_token
102 | << "&grant_type=refresh_token";
103 | return buff.str();
104 | }
105 |
106 | string get_auth_token_param(string code) {
107 | ostringstream buff;
108 | buff << "client_id=" << CLIENT_ID
109 | << "&client_secret=" << CLIENT_SECRET
110 | << "&redirect_uri=" << url_encode(REDIRECT_URI)
111 | << "&code=" << code
112 | << "&grant_type=authorization_code";
113 | return buff.str();
114 | }
115 |
116 | string url_encode(const string& src) {
117 | ostringstream buff;
118 | buff << std::hex << std::setfill('0');
119 | typedef string::const_iterator Iterator;
120 | Iterator end = src.end();
121 | for (Iterator itr = src.begin(); itr != end; ++itr) {
122 | if((*itr >= 'a' && *itr <= 'z')
123 | || (*itr >= 'A' && *itr <= 'Z')
124 | || (*itr >= '0' && *itr <= '9')
125 | || *itr == '-' || *itr == '.'
126 | || *itr == '_' || *itr == '~') {
127 | buff << *itr;
128 | } else {
129 | buff << '%' << std::setw(2)
130 | << static_cast(static_cast(*itr));
131 | }
132 | }
133 | return buff.str();
134 | }
135 | };
136 |
137 | int main(int argc, char* argv[]) {
138 |
139 | mixi_client client ;
140 | if (argc > 1) {
141 | string auth_code = argv[1];
142 | client.get_auth_token(auth_code);
143 | }
144 |
145 | clx::json entity =client.get_people("@me","@self");
146 | for (clx::json::iterator pos = entity.begin(); pos != entity.end(); ++pos) {
147 | std::cout << pos->first << " " << pos->second << std::endl;
148 | }
149 | return 0;
150 | }
151 |
--------------------------------------------------------------------------------
/scala/src/main/scala/example01/Main.scala:
--------------------------------------------------------------------------------
1 | package example01
2 |
3 | import scala.annotation.tailrec
4 |
5 | import dispatch.json.{Js, JsArray, JsObject, JsString, JsValue}
6 | import org.apache.commons.httpclient.{HttpClient, HttpMethodBase, HttpStatus}
7 | import org.apache.commons.httpclient.methods.{GetMethod, PostMethod}
8 | import sjson.json.{DefaultProtocol, Format, JsonSerialization, Reads}
9 |
10 | case class Tokens(refreshToken: String, expiresIn: Int, accessToken: String)
11 | case class Response(entries: List[Entry])
12 | case class Entry(id: String, displayName: String, thumbnailUrl: String, profileUrl: String)
13 |
14 | object Protocols extends DefaultProtocol {
15 | implicit val TokensFormat: Format[Tokens] =
16 | asProduct3("refresh_token", "expires_in", "access_token")(Tokens)(Tokens.unapply(_).get)
17 | implicit val EntryFormat: Format[Entry] =
18 | asProduct4("id", "displayName", "thumbnailUrl", "profileUrl")(Entry)(Entry.unapply(_).get)
19 |
20 | implicit object ResponseFormat extends Reads[Response] {
21 | import JsonSerialization.fromjson
22 | def reads(js: JsValue) = js match {
23 | case JsObject(x) => x(JsString("entry")) match {
24 | case y: JsObject => Response(fromjson[Entry](y) :: Nil)
25 | case ys: JsArray => Response(fromjson[List[Entry]](ys))
26 | case y => sys.error("Require object or array.(%s)".format(y))
27 | }
28 | case x => sys.error("Require object.(%s)".format(x))
29 | }
30 | }
31 | }
32 |
33 | object Main {
34 | import JsonSerialization.fromjson
35 | import Protocols._
36 |
37 | val CONSUMER_KEY = ""
38 | val CONSUMER_SECRET = ""
39 |
40 | val TOKEN_ENDPOINT = "https://secure.mixi-platform.com/2/token"
41 | val API_ENDPOINT_BASE = "http://api.mixi-platform.com/2"
42 | val REDIRECT_URI = "http://mixi.jp/connect_authorize_success.html"
43 |
44 | val REQUEST_TOKEN_BASE_PARAMS = Map("client_id" -> CONSUMER_KEY,
45 | "client_secret" -> CONSUMER_SECRET)
46 |
47 | def main(args: Array[String]) {
48 | args match {
49 | case Array(authorizationCode, _*) => repl(getTokens(authorizationCode))
50 | case _ => printf("""Usage: sbt run
51 | | please access the following url and get Autohrization Code.
52 | | https://mixi.jp/connect_authorize.pl?client_id=%s&response_type=code&scope=r_profile
53 | |""".stripMargin,
54 | CONSUMER_KEY)
55 | }
56 | }
57 |
58 | def getTokens(authorizationCode: String): Tokens =
59 | retrieveTokens(REQUEST_TOKEN_BASE_PARAMS +
60 | ("grant_type" -> "authorization_code") +
61 | ("code" -> authorizationCode) +
62 | ("redirect_uri" -> REDIRECT_URI))
63 |
64 | def refreshTokens(tokens: Tokens): Tokens =
65 | retrieveTokens(REQUEST_TOKEN_BASE_PARAMS +
66 | ("grant_type" -> "refresh_token") +
67 | ("refresh_token" -> tokens.refreshToken))
68 |
69 | def retrieveTokens(params: Map[String, String]): Tokens =
70 | using(new PostMethod(TOKEN_ENDPOINT)) { method =>
71 | for ((name, value) <- params)
72 | method.addParameter(name, value)
73 |
74 | new HttpClient executeMethod(method) match {
75 | case HttpStatus.SC_OK =>
76 | fromjson[Tokens](Js(method.getResponseBodyAsStream))
77 | case _ =>
78 | sys.error("Failure: %s".format(method.getStatusLine))
79 | }
80 | }
81 |
82 | val InputFormat = """\A\s*(@me|\w+)\s+(@self|@friends|\w+)\s*\z""".r
83 | @tailrec
84 | def repl(tokens: Tokens) {
85 |
86 | def read = Console.readLine("Input : ") match {
87 | case InputFormat(userId, groupId) => Some((userId, groupId))
88 | case _ => None
89 | }
90 |
91 | def eval(userId: String, groupId: String): (Tokens, List[Entry]) =
92 | request(tokens, "/people/%s/%s".format(userId, groupId)) match {
93 | case (nextTokens, Some(value)) => (nextTokens,
94 | fromjson[Response](value).entries)
95 | case (nextTokens, None) => (nextTokens, Nil)
96 | }
97 |
98 | def print(entries: List[Entry]) =
99 | for {
100 | Entry(id, displayName, thumbnailUrl, profileUrl) <- entries
101 | text = """Entry(id: %s
102 | | displayName: %s
103 | | thumbnailUrl: %s
104 | | profileUrl: %s)""".stripMargin
105 | .format(id, displayName, thumbnailUrl, profileUrl)
106 | } println(text)
107 |
108 | val nextTokens = for {
109 | (userId, groupId) <- read
110 | (tokens, entries) = eval(userId, groupId)
111 | } yield {
112 | print(entries)
113 | tokens
114 | }
115 |
116 | repl(nextTokens.getOrElse(tokens))
117 | }
118 |
119 | val ErrorPattern = """\A\s*OAuth\s+.*error='([^']+)'.*\z""".r
120 | @tailrec
121 | def request(tokens: Tokens, path: String): (Tokens, Option[JsValue]) = {
122 |
123 | def _request(accessToken: String, path: String): Either[Any, JsValue] =
124 | using(new GetMethod(API_ENDPOINT_BASE + path)) { method =>
125 | method.setDoAuthentication(false)
126 | method.addRequestHeader("Authorization",
127 | "OAuth %s".format(accessToken))
128 | new HttpClient executeMethod(method) match {
129 | case HttpStatus.SC_OK => Right(Js(method.getResponseBodyAsStream))
130 | case HttpStatus.SC_UNAUTHORIZED =>
131 | method.getResponseHeaders("WWW-Authenticate").map(_.getValue) match {
132 | case Array(ErrorPattern(reason), _*) => Left(Symbol(reason))
133 | case _ => Left(method.getStatusLine)
134 | }
135 | case _ => Left(method.getStatusLine)
136 | }
137 | }
138 |
139 | _request(tokens.accessToken, path) match {
140 | case Right(js) => (tokens, Some(js))
141 | case Left('expired_token) => request(refreshTokens(tokens), path)
142 | case Left(reason) => printf("Failure.(reason: %s)\n", reason)
143 | (tokens, None)
144 | }
145 | }
146 |
147 | def using[A <: HttpMethodBase, B](method: A)(block: A => B): B =
148 | try { block(method) }
149 | finally { method.releaseConnection }
150 | }
151 |
--------------------------------------------------------------------------------
/golang/mixi.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "encoding/json"
5 | "errors"
6 | "io/ioutil"
7 | "log"
8 | "net"
9 | "net/http"
10 | "net/http/httputil"
11 |
12 | "net/url"
13 | "strings"
14 | "text/template"
15 | )
16 |
17 | type friend struct {
18 | DisplayName string
19 | ThumbnailUrl string
20 | ProfileUrl string
21 | }
22 |
23 | type tokens struct {
24 | AccessToken string
25 | RefreshToken string
26 | }
27 |
28 | const (
29 | AUTHORIZE_URL_BASE = "https://mixi.jp/connect_authorize.pl?response_type=code&scope=r_profile&client_id="
30 | TOKENS_ENDPOINT = "https://secure.mixi-platform.com/2/token"
31 | FRIEND_LIST_ENDPOINT = "http://api.mixi-platform.com/2/people/@me/@friends"
32 | CONFIG_FILENAME = "config.json"
33 | TOKENS_FILENAME = "tokens.txt"
34 | TEMPLATE = `
35 |
36 | Friend Lit
37 |
38 |
39 | {.repeated section Friends}
40 |
41 |
42 | {DisplayName}
43 |
44 | {.end}
45 |
46 |
47 |
48 | `
49 | )
50 |
51 | var config map[string]string
52 | var currentTokens *tokens
53 |
54 | func NewTokens(accessToken string, refreshToken string) *tokens {
55 | return &tokens{accessToken, refreshToken}
56 | }
57 |
58 | func RestoreTokens() *tokens {
59 | if bytes, err := ioutil.ReadFile(TOKENS_FILENAME); err == nil {
60 | pair := strings.Split(string(bytes), "\n")
61 | return &tokens{pair[0], pair[1]}
62 | }
63 | return nil
64 | }
65 |
66 | func (t *tokens) store() {
67 | ioutil.WriteFile(TOKENS_FILENAME, []byte(t.AccessToken+
68 | "\n"+t.RefreshToken), 0666)
69 | }
70 |
71 | func authorizeCode(authCode string) (err error) {
72 | return updateTokens(map[string][]string{
73 | "grant_type": {"authorization_code"},
74 | "client_id": {config["client_id"]},
75 | "client_secret": {config["client_secret"]},
76 | "code": {authCode},
77 | "redirect_uri": {"http://localhost:" + config["redirect_port"]},
78 | })
79 | }
80 |
81 | func refreshToken() (err error) {
82 | return updateTokens(map[string][]string{
83 | "grant_type": {"refresh_token"},
84 | "client_id": {config["client_id"]},
85 | "client_secret": {config["client_secret"]},
86 | "refresh_token": {currentTokens.RefreshToken},
87 | })
88 | }
89 |
90 | func updateTokens(params map[string][]string) (err error) {
91 | println("Call: " + TOKENS_ENDPOINT)
92 | response, _ := http.PostForm(TOKENS_ENDPOINT, params)
93 | b, _ := ioutil.ReadAll(response.Body)
94 | println(string(b))
95 |
96 | var responseJson map[string]interface{}
97 | json.Unmarshal(b, &responseJson)
98 | if errorMessage, ok := responseJson["error"]; ok {
99 | return errors.New(errorMessage.(string))
100 | } else {
101 | currentTokens = &tokens{responseJson["access_token"].(string), responseJson["refresh_token"].(string)}
102 | currentTokens.store()
103 | return nil
104 | }
105 | return errors.New("access_token is null")
106 | }
107 |
108 | func oauthGet(accessToken string, urlString string) (*http.Response, error) {
109 | url_, _ := url.Parse(urlString)
110 | conn, _ := net.Dial("tcp", url_.Host+":80")
111 |
112 | clientConn := httputil.NewClientConn(conn, nil)
113 | header := map[string][]string{"Authorization": {"OAuth " + accessToken}}
114 | request := http.Request{Method: "GET", URL: url_, Header: header}
115 | clientConn.Write(&request)
116 | return clientConn.Read(&request)
117 | }
118 |
119 | func getFriendList() (friends []friend, err error) {
120 | println("Call: " + FRIEND_LIST_ENDPOINT)
121 | response, _ := oauthGet(currentTokens.AccessToken, FRIEND_LIST_ENDPOINT)
122 | if response.StatusCode == 401 {
123 | if err = refreshToken(); err == nil {
124 | return getFriendList()
125 | }
126 | return nil, err
127 | }
128 | b, _ := ioutil.ReadAll(response.Body)
129 | println(string(b))
130 |
131 | var responseJson map[string]interface{}
132 | json.Unmarshal(b, &responseJson)
133 | entry := responseJson["entry"].([]interface{})
134 | totalResults := int(responseJson["totalResults"].(float64))
135 | itemsPerPage := int(responseJson["itemsPerPage"].(float64))
136 | var itemsCount int
137 | if itemsPerPage < totalResults {
138 | itemsCount = itemsPerPage
139 | } else {
140 | itemsCount = totalResults
141 | }
142 | friends = make([]friend, itemsCount)
143 | for i := 0; i < itemsCount; i++ {
144 | data := entry[i].(map[string]interface{})
145 | friends[i] = friend{
146 | DisplayName: data["displayName"].(string),
147 | ThumbnailUrl: data["thumbnailUrl"].(string),
148 | ProfileUrl: data["profileUrl"].(string),
149 | }
150 | }
151 | return friends, nil
152 | }
153 |
154 | func redirect(writer http.ResponseWriter, request *http.Request, redirectUrl string) {
155 | println("Redirect to: " + redirectUrl)
156 | http.Redirect(writer, request, redirectUrl, http.StatusFound)
157 | }
158 |
159 | func handleFriendList(writer http.ResponseWriter, request *http.Request) {
160 | if request.URL.Path == "/favicon.ico" {
161 | return
162 | }
163 |
164 | var (
165 | friends []friend
166 | err error
167 | )
168 |
169 | authorizeUrl := AUTHORIZE_URL_BASE + config["client_id"]
170 | parts := strings.Split(request.URL.RawPath, "?code=")
171 | if 2 <= len(parts) {
172 | if err = authorizeCode(parts[1]); err != nil {
173 | redirect(writer, request, authorizeUrl)
174 | } else {
175 | redirect(writer, request, "/")
176 | }
177 | return
178 | } else if currentTokens == nil {
179 | redirect(writer, request, authorizeUrl)
180 | return
181 | }
182 |
183 | if friends, err = getFriendList(); err != nil {
184 | redirect(writer, request, authorizeUrl)
185 | } else {
186 | params := new(struct{ Friends []friend })
187 | params.Friends = friends
188 | tmpl, _ := template.New("mixi").Parse(TEMPLATE)
189 | tmpl.Execute(writer, params)
190 | }
191 | }
192 |
193 | func main() {
194 | var (
195 | bytes []byte
196 | err error
197 | )
198 |
199 | if bytes, err = ioutil.ReadFile(CONFIG_FILENAME); err != nil {
200 | log.Fatal("ioutil.ReadFile:", err)
201 | }
202 | if err = json.Unmarshal(bytes, &config); err != nil {
203 | log.Fatal("json.Unmarshal:", err)
204 | }
205 | currentTokens = RestoreTokens()
206 |
207 | http.Handle("/", http.HandlerFunc(handleFriendList))
208 |
209 | addr := "localhost:" + config["redirect_port"]
210 | println("Please open http://" + addr + " on a web browser.")
211 | if err = http.ListenAndServe(addr, nil); err != nil {
212 | log.Fatal("http.ListenAndServe:", err)
213 | }
214 | }
215 |
--------------------------------------------------------------------------------