summaryrefslogtreecommitdiffstats
path: root/Godeps
diff options
context:
space:
mode:
author=Corey Hulen <corey@hulen.com>2015-06-25 12:21:47 -0400
committer=Corey Hulen <corey@hulen.com>2015-06-25 12:21:47 -0400
commit16505ffe94ef09102e2bd1ecdca72541c2d85ae6 (patch)
tree4260356d839f8905c237eee62ba18aa928d23159 /Godeps
parent6ee153d7f8cfc14d3339e5e341e8ead330456c0d (diff)
downloadchat-16505ffe94ef09102e2bd1ecdca72541c2d85ae6.tar.gz
chat-16505ffe94ef09102e2bd1ecdca72541c2d85ae6.tar.bz2
chat-16505ffe94ef09102e2bd1ecdca72541c2d85ae6.zip
updating make
Diffstat (limited to 'Godeps')
-rw-r--r--Godeps/Godeps.json13
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/CHANGELOG.md47
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/CONTRIBUTING.md7
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/LICENSE19
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/README.md347
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/api.go180
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/app.go255
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/batch_result.go52
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/const.go74
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/facebook_test.go1469
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/misc.go131
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/paging_result.go146
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/params.go227
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/result.go1097
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/session.go667
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/type.go127
16 files changed, 4 insertions, 4854 deletions
diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index 093b2a1fc..db118f512 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -89,11 +89,6 @@
"Rev": "6fd0f867fef40c540fa05c59f86396de10a632a6"
},
{
- "ImportPath": "github.com/huandu/facebook",
- "Comment": "v1.5.2",
- "Rev": "7c46d89211b9a3f01087f47f6a399b815801ade4"
- },
- {
"ImportPath": "github.com/mssola/user_agent",
"Comment": "v0.4.1-2-g35c7f18",
"Rev": "35c7f18f5261cc18c698a461053c119aebaf8542"
@@ -123,6 +118,10 @@
"Rev": "74f810a0152f4c50a16195f6b9ff44afc35594e8"
},
{
+ "ImportPath": "golang.org/x/image/bmp",
+ "Rev": "eb11b45157c1b71f30b3cec66306f1cd779a689e"
+ },
+ {
"ImportPath": "gopkg.in/bufio.v1",
"Comment": "v1",
"Rev": "567b2bfa514e796916c4747494d6ff5132a1dfce"
@@ -136,10 +135,6 @@
"ImportPath": "gopkg.in/redis.v2",
"Comment": "v2.3.2",
"Rev": "e6179049628164864e6e84e973cfb56335748dea"
- },
- {
- "ImportPath": "golang.org/x/image/bmp",
- "Rev": "eb11b45157c1b71f30b3cec66306f1cd779a689e"
}
]
}
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/CHANGELOG.md b/Godeps/_workspace/src/github.com/huandu/facebook/CHANGELOG.md
deleted file mode 100644
index d1c14a215..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/CHANGELOG.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# Change Log #
-
-## v1.5.2 ##
-
-* `[FIX]` [#32](https://github.com/huandu/facebook/pull/32) BatchApi/Batch returns facebook error when access token is not valid.
-
-## v1.5.1 ##
-
-* `[FIX]` [#31](https://github.com/huandu/facebook/pull/31) When `/oauth/access_token` returns a query string instead of json, this package can correctly handle it.
-
-## v1.5.0 ##
-
-* `[NEW]` [#28](https://github.com/huandu/facebook/pull/28) Support debug mode introduced by facebook graph API v2.3.
-* `[FIX]` Removed all test cases depending on facebook graph API v1.0.
-
-## v1.4.1 ##
-
-* `[NEW]` [#27](https://github.com/huandu/facebook/pull/27) Timestamp value in Graph API response can be decoded as a `time.Time` value now. Thanks, [@Lazyshot](https://github.com/Lazyshot).
-
-## v1.4.0 ##
-
-* `[FIX]` [#23](https://github.com/huandu/facebook/issues/24) Algorithm change: Camel case string to underscore string supports abbreviation
-
-Fix for [#23](https://github.com/huandu/facebook/issues/24) could be a breaking change. Camel case string `HTTPServer` will be converted to `http_server` instead of `h_t_t_p_server`. See issue description for detail.
-
-## v1.3.0 ##
-
-* `[NEW]` [#22](https://github.com/huandu/facebook/issues/22) Add a new helper struct `BatchResult` to hold batch request responses.
-
-## v1.2.0 ##
-
-* `[NEW]` [#20](https://github.com/huandu/facebook/issues/20) Add Decode functionality for paging results. Thanks, [@cbroglie](https://github.com/cbroglie).
-* `[FIX]` [#21](https://github.com/huandu/facebook/issues/21) `Session#Inspect` cannot return error if access token is invalid.
-
-Fix for [#21](https://github.com/huandu/facebook/issues/21) will result a possible breaking change in `Session#Inspect`. It was return whole result returned by facebook inspect api. Now it only return its "data" sub-tree. As facebook puts everything including error message in "data" sub-tree, I believe it's reasonable to make this change.
-
-## v1.1.0 ##
-
-* `[FIX]` [#19](https://github.com/huandu/facebook/issues/19) Any valid int64 number larger than 2^53 or smaller than -2^53 can be correctly decoded without precision lost.
-
-Fix for [#19](https://github.com/huandu/facebook/issues/19) will result a possible breaking change in `Result#Get` and `Result#GetField`. If a JSON field is a number, these two functions will return json.Number instead of float64.
-
-The fix also introduces a side effect in `Result#Decode` and `Result#DecodeField`. A number field (`int*` and `float*`) can be decoded to a string. It was not allowed in previous version.
-
-## v1.0.0 ##
-
-Initial tag. Library is stable enough for all features mentioned in README.md.
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/CONTRIBUTING.md b/Godeps/_workspace/src/github.com/huandu/facebook/CONTRIBUTING.md
deleted file mode 100644
index c001d2511..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/CONTRIBUTING.md
+++ /dev/null
@@ -1,7 +0,0 @@
-Thanks for contributing this project!
-
-Please don't forget to use `gofmt` to make your code look good.
-
-Here is the command I use. Please always use the same parameters.
-
- go fmt
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/LICENSE b/Godeps/_workspace/src/github.com/huandu/facebook/LICENSE
deleted file mode 100644
index 9569215e9..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/LICENSE
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2012 - 2015 Huan Du
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/README.md b/Godeps/_workspace/src/github.com/huandu/facebook/README.md
deleted file mode 100644
index a21de8d7c..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/README.md
+++ /dev/null
@@ -1,347 +0,0 @@
-# A Facebook Graph API SDK In Golang #
-
-[![Build Status](https://travis-ci.org/huandu/facebook.png?branch=master)](https://travis-ci.org/huandu/facebook)
-
-This is a Go package fully supports Facebook Graph API with file upload, batch request, FQL and multi-FQL. It can be used in Google App Engine.
-
-API documents can be found on [godoc](http://godoc.org/github.com/huandu/facebook).
-
-Feel free to create an issue or send me a pull request if you have any "how-to" question or bug or suggestion when using this package. I'll try my best to reply it.
-
-## Get It ##
-
-Use `go get -u github.com/huandu/facebook` to get or update it.
-
-## Usage ##
-
-### Quick start ###
-
-Here is a sample to read my Facebook username by uid.
-
-```go
-package main
-
-import (
- "fmt"
- fb "github.com/huandu/facebook"
-)
-
-func main() {
- res, _ := fb.Get("/538744468", fb.Params{
- "fields": "username",
- "access_token": "a-valid-access-token",
- })
- fmt.Println("here is my facebook username:", res["username"])
-}
-```
-
-Type of `res` is `fb.Result` (a.k.a. `map[string]interface{}`).
-This type has several useful methods to decode `res` to any Go type safely.
-
-```go
-// Decode "username" to a Go string.
-var username string
-res.DecodeField("username", &username)
-fmt.Println("alternative way to get username:", username)
-
-// It's also possible to decode the whole result into a predefined struct.
-type User struct {
- Username string
-}
-
-var user User
-res.Decode(&user)
-fmt.Println("print username in struct:", user.Username)
-```
-
-### Read a graph `user` object with a valid access token ###
-
-```go
-res, err := fb.Get("/me/feed", fb.Params{
- "access_token": "a-valid-access-token",
-})
-
-if err != nil {
- // err can be an facebook API error.
- // if so, the Error struct contains error details.
- if e, ok := err.(*Error); ok {
- fmt.Logf("facebook error. [message:%v] [type:%v] [code:%v] [subcode:%v]",
- e.Message, e.Type, e.Code, e.ErrorSubcode)
- return
- }
-
- return
-}
-
-// read my last feed.
-fmt.Println("my latest feed story is:", res.Get("data.0.story"))
-```
-
-### Read a graph `search` for page and decode slice of maps
-
-```go
-res, _ := fb.Get("/search", fb.Params{
- "access_token": "a-valid-access-token",
- "type": "page",
- "q": "nightlife,singapore",
- })
-
-var items []fb.Result
-
-err := res.DecodeField("data", &items)
-
-if err != nil {
- fmt.Logf("An error has happened %v", err)
- return
-}
-
-for _, item := range items {
- fmt.Println(item["id"])
-}
-```
-
-### Use `App` and `Session` ###
-
-It's recommended to use `App` and `Session` in a production app. They provide more controls over all API calls. They can also make code clear and concise.
-
-```go
-// create a global App var to hold app id and secret.
-var globalApp = fb.New("your-app-id", "your-app-secret")
-
-// facebook asks for a valid redirect uri when parsing signed request.
-// it's a new enforced policy starting in late 2013.
-globalApp.RedirectUri = "http://your.site/canvas/url/"
-
-// here comes a client with a facebook signed request string in query string.
-// creates a new session with signed request.
-session, _ := globalApp.SessionFromSignedRequest(signedRequest)
-
-// if there is another way to get decoded access token,
-// creates a session directly with the token.
-session := globalApp.Session(token)
-
-// validate access token. err is nil if token is valid.
-err := session.Validate()
-
-// use session to send api request with access token.
-res, _ := session.Get("/me/feed", nil)
-```
-
-### Use `paging` field in response. ###
-
-Some Graph API responses use a special JSON structure to provide paging information. Use `Result.Paging()` to walk through all data in such results.
-
-```go
-res, _ := session.Get("/me/home", nil)
-
-// create a paging structure.
-paging, _ := res.Paging(session)
-
-// get current results.
-results := paging.Data()
-
-// get next page.
-noMore, err := paging.Next()
-results = paging.Data()
-```
-
-### Read graph api response and decode result into a struct ###
-
-As facebook Graph API always uses lower case words as keys in API response.
-This package can convert go's camel-case-style struct field name to facebook's underscore-style API key name.
-
-For instance, to decode following JSON response...
-
-```json
-{
- "foo_bar": "player"
-}
-```
-
-One can use following struct.
-
-```go
-type Data struct {
- FooBar string // "FooBar" maps to "foo_bar" in JSON automatically in this case.
-}
-```
-
-Decoding behavior can be changed per field through field tag -- just like what `encoding/json` does.
-
-Following is a sample shows all possible field tags.
-
-```go
-// define a facebook feed object.
-type FacebookFeed struct {
- Id string `facebook:",required"` // this field must exist in response.
- // mind the "," before "required".
- Story string
- FeedFrom *FacebookFeedFrom `facebook:"from"` // use customized field name "from"
- CreatedTime string `facebook:"created_time,required"` // both customized field name and "required" flag.
-}
-
-type FacebookFeedFrom struct {
- Name, Id string
-}
-
-// create a feed object direct from graph api result.
-var feed FacebookFeed
-res, _ := session.Get("/me/feed", nil)
-res.DecodeField("data.0", &feed) // read latest feed
-```
-
-### Send a batch request ###
-
-```go
-params1 := Params{
- "method": fb.GET,
- "relative_url": "me",
-}
-params2 := Params{
- "method": fb.GET,
- "relative_url": uint64(100002828925788),
-}
-results, err := fb.BatchApi(your_access_token, params1, params2)
-
-if err != nil {
- // check error...
- return
-}
-
-// batchResult1 and batchResult2 are response for params1 and params2.
-batchResult1, _ := results[0].Batch()
-batchResult2, _ := results[1].Batch()
-
-// Use parsed result.
-var id string
-res := batchResult1.Result
-res.DecodeField("id", &id)
-
-// Use response header.
-contentType := batchResult1.Header.Get("Content-Type")
-```
-
-### Send FQL query ###
-
-```go
-results, _ := fb.FQL("SELECT username FROM page WHERE page_id = 20531316728")
-fmt.Println(results[0]["username"]) // print "facebook"
-
-// most FQL query requires access token. create session to hold access token.
-session := &fb.Session{}
-session.SetAccessToken("A-VALID-ACCESS-TOKEN")
-results, _ := session.FQL("SELECT username FROM page WHERE page_id = 20531316728")
-fmt.Println(results[0]["username"]) // print "facebook"
-```
-
-### Make multi-FQL ###
-
-```go
-res, _ := fb.MultiFQL(Params{
- "query1": "SELECT username FROM page WHERE page_id = 20531316728",
- "query2": "SELECT uid FROM user WHERE uid = 538744468",
-})
-var query1, query2 []Result
-
-// get response for query1 and query2.
-res.DecodeField("query1", &query1)
-res.DecodeField("query2", &query2)
-
-// most FQL query requires access token. create session to hold access token.
-session := &fb.Session{}
-session.SetAccessToken("A-VALID-ACCESS-TOKEN")
-res, _ := session.MultiFQL(Params{
- "query1": "...",
- "query2": "...",
-})
-
-// same as the sample without access token...
-```
-
-### Use it in Google App Engine ###
-
-Google App Engine provide `appengine/urlfetch` package as standard http client package. Default client in `net/http` doesn't work. One must explicitly set http client in `Session` to make it work.
-
-```go
-import (
- "appengine"
- "appengine/urlfetch"
-)
-
-// suppose it's the appengine context initialized somewhere.
-var context appengine.Context
-
-// default Session object uses http.DefaultClient which is not allowed to use
-// in appengine. one has to create a Session and assign it a special client.
-seesion := globalApp.Session("a-access-token")
-session.HttpClient = urlfetch.Client(context)
-
-// now, session uses appengine http client now.
-res, err := session.Get("/me", nil)
-```
-
-### Select Graph API version ###
-
-See [Platform Versioning](https://developers.facebook.com/docs/apps/versions) to understand facebook versioning strategy.
-
-```go
-// this package uses default version which is controlled by facebook app setting.
-// change following global variable to specific a global default version.
-fb.Version = "v2.0"
-
-// starting with graph api v2.0, it's not allowed to get user information without access token.
-fb.Api("huan.du", GET, nil)
-
-// it's possible to specify version per session.
-session := &fb.Session{}
-session.Version = "v2.0" // overwrite global default.
-```
-
-### Enable `appsecret_proof` ###
-
-Facebook can verify Graph API Calls with `appsecret_proof`. It's a feature to make Graph API call more secure. See [Securing Graph API Requests](https://developers.facebook.com/docs/graph-api/securing-requests) to know more about it.
-
-```go
-globalApp := fb.New("your-app-id", "your-app-secret")
-
-// enable "appsecret_proof" for all sessions created by this app.
-globalApp.EnableAppsecretProof = true
-
-// all calls in this session are secured.
-session := globalApp.Session("a-valid-access-token")
-session.Get("/me", nil)
-
-// it's also possible to enable/disable this feature per session.
-session.EnableAppsecretProof(false)
-```
-
-### Debugging API Requests ###
-
-Facebook introduces a way to debug graph API calls. See [Debugging API Requests](https://developers.facebook.com/docs/graph-api/using-graph-api/v2.3#debugging) for details.
-
-This package provides both package level and per session debug flag. Set `Debug` to a `DEBUG_*` constant to change debug mode globally; or use `Session#SetDebug` to change debug mode for one session.
-
-When debug mode is turned on, use `Result#DebugInfo` to get `DebugInfo` struct from result.
-
-```go
-fb.Debug = fb.DEBUG_ALL
-
-res, _ := fb.Get("/me", fb.Params{"access_token": "xxx"})
-debugInfo := res.DebugInfo()
-
-fmt.Println("http headers:", debugInfo.Header)
-fmt.Println("facebook api version:", debugInfo.FacebookApiVersion)
-```
-
-## Change Log ##
-
-See [CHANGELOG.md](CHANGELOG.md).
-
-## Out of Scope ##
-
-1. No OAuth integration. This package only provides APIs to parse/verify access token and code generated in OAuth 2.0 authentication process.
-2. No old RESTful API support. Such APIs are deprecated for years. Forget about them.
-
-## License ##
-
-This package is licensed under MIT license. See LICENSE for details.
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/api.go b/Godeps/_workspace/src/github.com/huandu/facebook/api.go
deleted file mode 100644
index 57945d26e..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/api.go
+++ /dev/null
@@ -1,180 +0,0 @@
-// A facebook graph api client in go.
-// https://github.com/huandu/facebook/
-//
-// Copyright 2012 - 2015, Huan Du
-// Licensed under the MIT license
-// https://github.com/huandu/facebook/blob/master/LICENSE
-
-// This is a Go library fully supports Facebook Graph API (both 1.0 and 2.x) with
-// file upload, batch request, FQL and multi-FQL. It can be used in Google App Engine.
-//
-// Library design is highly influenced by facebook official PHP/JS SDK.
-// If you have experience with PHP/JS SDK, you may feel quite familiar with it.
-//
-// Go to project home page to see samples. Link: https://github.com/huandu/facebook
-//
-// This library doesn't implement any deprecated old RESTful API. And it won't.
-package facebook
-
-import (
- "net/http"
-)
-
-var (
- // Default facebook api version.
- // It can be any valid version string (e.g. "v2.3") or empty.
- //
- // See https://developers.facebook.com/docs/apps/versions for details.
- Version string
-
- // Set app level debug mode.
- // After setting DebugMode, all newly created session will use the mode
- // to communicate with graph API.
- //
- // See https://developers.facebook.com/docs/graph-api/using-graph-api/v2.3#debugging
- Debug DebugMode
-)
-
-// Makes a facebook graph api call with default session.
-//
-// Method can be GET, POST, DELETE or PUT.
-//
-// Params represents query strings in this call.
-// Keys and values in params will be encoded for URL automatically. So there is
-// no need to encode keys or values in params manually. Params can be nil.
-//
-// If you want to get
-// https://graph.facebook.com/huandu?fields=name,username
-// Api should be called as following
-// Api("/huandu", GET, Params{"fields": "name,username"})
-// or in a simplified way
-// Get("/huandu", Params{"fields": "name,username"})
-//
-// Api is a wrapper of Session.Api(). It's designed for graph api that doesn't require
-// app id, app secret and access token. It can be called in multiple goroutines.
-//
-// If app id, app secret or access token is required in graph api, caller should
-// create a new facebook session through App instance instead.
-func Api(path string, method Method, params Params) (Result, error) {
- return defaultSession.Api(path, method, params)
-}
-
-// Get is a short hand of Api(path, GET, params).
-func Get(path string, params Params) (Result, error) {
- return Api(path, GET, params)
-}
-
-// Post is a short hand of Api(path, POST, params).
-func Post(path string, params Params) (Result, error) {
- return Api(path, POST, params)
-}
-
-// Delete is a short hand of Api(path, DELETE, params).
-func Delete(path string, params Params) (Result, error) {
- return Api(path, DELETE, params)
-}
-
-// Put is a short hand of Api(path, PUT, params).
-func Put(path string, params Params) (Result, error) {
- return Api(path, PUT, params)
-}
-
-// Makes a batch facebook graph api call with default session.
-//
-// BatchApi supports most kinds of batch calls defines in facebook batch api document,
-// except uploading binary data. Use Batch to do so.
-//
-// Note: API response is stored in "body" field of a Result.
-// results, _ := BatchApi(accessToken, Params{...}, Params{...})
-//
-// // Use first batch api response.
-// var res1 *BatchResult
-// var err error
-// res1, err = results[0].Batch()
-//
-// if err != nil {
-// // this is not a valid batch api response.
-// }
-//
-// // Use BatchResult#Result to get response body content as Result.
-// res := res1.Result
-//
-// Facebook document: https://developers.facebook.com/docs/graph-api/making-multiple-requests
-func BatchApi(accessToken string, params ...Params) ([]Result, error) {
- return Batch(Params{"access_token": accessToken}, params...)
-}
-
-// Makes a batch facebook graph api call with default session.
-// Batch is designed for more advanced usage including uploading binary files.
-//
-// An uploading files sample
-// // equivalent to following curl command (borrowed from facebook docs)
-// // curl \
-// // -F 'access_token=…' \
-// // -F 'batch=[{"method":"POST","relative_url":"me/photos","body":"message=My cat photo","attached_files":"file1"},{"method":"POST","relative_url":"me/photos","body":"message=My dog photo","attached_files":"file2"},]' \
-// // -F 'file1=@cat.gif' \
-// // -F 'file2=@dog.jpg' \
-// // https://graph.facebook.com
-// Batch(Params{
-// "access_token": "the-access-token",
-// "file1": File("cat.gif"),
-// "file2": File("dog.jpg"),
-// }, Params{
-// "method": "POST",
-// "relative_url": "me/photos",
-// "body": "message=My cat photo",
-// "attached_files": "file1",
-// }, Params{
-// "method": "POST",
-// "relative_url": "me/photos",
-// "body": "message=My dog photo",
-// "attached_files": "file2",
-// })
-//
-// Facebook document: https://developers.facebook.com/docs/graph-api/making-multiple-requests
-func Batch(batchParams Params, params ...Params) ([]Result, error) {
- return defaultSession.Batch(batchParams, params...)
-}
-
-// Makes a FQL query with default session.
-// Returns a slice of Result. If there is no query result, the result is nil.
-//
-// FQL can only make query without "access_token". For query requiring "access_token", create
-// Session and call its FQL method.
-//
-// Facebook document: https://developers.facebook.com/docs/technical-guides/fql#query
-func FQL(query string) ([]Result, error) {
- return defaultSession.FQL(query)
-}
-
-// Makes a multi FQL query with default session.
-// Returns a parsed Result. The key is the multi query key, and the value is the query result.
-//
-// MultiFQL can only make query without "access_token". For query requiring "access_token", create
-// Session and call its MultiFQL method.
-//
-// See Session.MultiFQL document for samples.
-//
-// Facebook document: https://developers.facebook.com/docs/technical-guides/fql#multi
-func MultiFQL(queries Params) (Result, error) {
- return defaultSession.MultiFQL(queries)
-}
-
-// Makes an arbitrary HTTP request with default session.
-// It expects server responses a facebook Graph API response.
-// request, _ := http.NewRequest("https://graph.facebook.com/538744468", "GET", nil)
-// res, err := Request(request)
-// fmt.Println(res["gender"]) // get "male"
-func Request(request *http.Request) (Result, error) {
- return defaultSession.Request(request)
-}
-
-// DefaultHttpClient returns the http client for default session.
-func DefaultHttpClient() HttpClient {
- return defaultSession.HttpClient
-}
-
-// SetHttpClient updates the http client of default session.
-func SetHttpClient(client HttpClient) {
- defaultSession.HttpClient = client
-}
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/app.go b/Godeps/_workspace/src/github.com/huandu/facebook/app.go
deleted file mode 100644
index d8787aa87..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/app.go
+++ /dev/null
@@ -1,255 +0,0 @@
-// A facebook graph api client in go.
-// https://github.com/huandu/facebook/
-//
-// Copyright 2012 - 2015, Huan Du
-// Licensed under the MIT license
-// https://github.com/huandu/facebook/blob/master/LICENSE
-
-package facebook
-
-import (
- "bytes"
- "crypto/hmac"
- "crypto/sha256"
- "encoding/json"
- "fmt"
- "strings"
-)
-
-// Creates a new App and sets app id and secret.
-func New(appId, appSecret string) *App {
- return &App{
- AppId: appId,
- AppSecret: appSecret,
- }
-}
-
-// Gets application access token, useful for gathering public information about users and applications.
-func (app *App) AppAccessToken() string {
- return app.AppId + "|" + app.AppSecret
-}
-
-// Parses signed request.
-func (app *App) ParseSignedRequest(signedRequest string) (res Result, err error) {
- strs := strings.SplitN(signedRequest, ".", 2)
-
- if len(strs) != 2 {
- err = fmt.Errorf("invalid signed request format.")
- return
- }
-
- sig, e1 := decodeBase64URLEncodingString(strs[0])
-
- if e1 != nil {
- err = fmt.Errorf("cannot decode signed request sig. error is %v.", e1)
- return
- }
-
- payload, e2 := decodeBase64URLEncodingString(strs[1])
-
- if e2 != nil {
- err = fmt.Errorf("cannot decode signed request payload. error is %v.", e2)
- return
- }
-
- err = json.Unmarshal(payload, &res)
-
- if err != nil {
- err = fmt.Errorf("signed request payload is not a valid json string. error is %v.", err)
- return
- }
-
- var hashMethod string
- err = res.DecodeField("algorithm", &hashMethod)
-
- if err != nil {
- err = fmt.Errorf("signed request payload doesn't contains a valid 'algorithm' field.")
- return
- }
-
- hashMethod = strings.ToUpper(hashMethod)
-
- if hashMethod != "HMAC-SHA256" {
- err = fmt.Errorf("signed request payload uses an unknown HMAC method. expect 'HMAC-SHA256'. actual '%v'.", hashMethod)
- return
- }
-
- hash := hmac.New(sha256.New, []byte(app.AppSecret))
- hash.Write([]byte(strs[1])) // note: here uses the payload base64 string, not decoded bytes
- expectedSig := hash.Sum(nil)
-
- if bytes.Compare(sig, expectedSig) != 0 {
- err = fmt.Errorf("bad signed request signiture.")
- return
- }
-
- return
-}
-
-// ParseCode redeems code for a valid access token.
-// It's a shorthand call to ParseCodeInfo(code, "").
-//
-// In facebook PHP SDK, there is a CSRF state to avoid attack.
-// That state is not checked in this library.
-// Caller is responsible to store and check state if possible.
-func (app *App) ParseCode(code string) (token string, err error) {
- token, _, _, err = app.ParseCodeInfo(code, "")
- return
-}
-
-// ParseCodeInfo redeems code for access token and returns extra information.
-// The machineId is optional.
-//
-// See https://developers.facebook.com/docs/facebook-login/access-tokens#extending
-func (app *App) ParseCodeInfo(code, machineId string) (token string, expires int, newMachineId string, err error) {
- if code == "" {
- err = fmt.Errorf("code is empty")
- return
- }
-
- var res Result
- res, err = defaultSession.sendOauthRequest("/oauth/access_token", Params{
- "client_id": app.AppId,
- "redirect_uri": app.RedirectUri,
- "code": code,
- })
-
- if err != nil {
- err = fmt.Errorf("cannot parse facebook response. error is %v.", err)
- return
- }
-
- err = res.DecodeField("access_token", &token)
-
- if err != nil {
- return
- }
-
- err = res.DecodeField("expires_in", &expires)
-
- if err != nil {
- return
- }
-
- if _, ok := res["machine_id"]; ok {
- err = res.DecodeField("machine_id", &newMachineId)
- }
-
- return
-}
-
-// Exchange a short lived access token to a long lived access token.
-// Return new access token and its expires time.
-func (app *App) ExchangeToken(accessToken string) (token string, expires int, err error) {
- if accessToken == "" {
- err = fmt.Errorf("short lived accessToken is empty")
- return
- }
-
- var res Result
- res, err = defaultSession.sendOauthRequest("/oauth/access_token", Params{
- "grant_type": "fb_exchange_token",
- "client_id": app.AppId,
- "client_secret": app.AppSecret,
- "fb_exchange_token": accessToken,
- })
-
- if err != nil {
- err = fmt.Errorf("cannot parse facebook response. error is %v.", err)
- return
- }
-
- err = res.DecodeField("access_token", &token)
-
- if err != nil {
- return
- }
-
- err = res.DecodeField("expires_in", &expires)
- return
-}
-
-// Get code from a long lived access token.
-// Return the code retrieved from facebook.
-func (app *App) GetCode(accessToken string) (code string, err error) {
- if accessToken == "" {
- err = fmt.Errorf("long lived accessToken is empty")
- return
- }
-
- var res Result
- res, err = defaultSession.sendOauthRequest("/oauth/client_code", Params{
- "client_id": app.AppId,
- "client_secret": app.AppSecret,
- "redirect_uri": app.RedirectUri,
- "access_token": accessToken,
- })
-
- if err != nil {
- err = fmt.Errorf("cannot get code from facebook. error is %v.", err)
- return
- }
-
- err = res.DecodeField("code", &code)
- return
-}
-
-// Creates a session based on current App setting.
-func (app *App) Session(accessToken string) *Session {
- return &Session{
- accessToken: accessToken,
- app: app,
- enableAppsecretProof: app.EnableAppsecretProof,
- }
-}
-
-// Creates a session from a signed request.
-// If signed request contains a code, it will automatically use this code
-// to exchange a valid access token.
-func (app *App) SessionFromSignedRequest(signedRequest string) (session *Session, err error) {
- var res Result
-
- res, err = app.ParseSignedRequest(signedRequest)
-
- if err != nil {
- return
- }
-
- var id, token string
-
- res.DecodeField("user_id", &id) // it's ok without user id.
- err = res.DecodeField("oauth_token", &token)
-
- if err == nil {
- session = &Session{
- accessToken: token,
- app: app,
- id: id,
- enableAppsecretProof: app.EnableAppsecretProof,
- }
- return
- }
-
- // cannot get "oauth_token"? try to get "code".
- err = res.DecodeField("code", &token)
-
- if err != nil {
- // no code? no way to continue.
- err = fmt.Errorf("cannot find 'oauth_token' and 'code'. no way to continue.")
- return
- }
-
- token, err = app.ParseCode(token)
-
- if err != nil {
- return
- }
-
- session = &Session{
- accessToken: token,
- app: app,
- id: id,
- enableAppsecretProof: app.EnableAppsecretProof,
- }
- return
-}
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/batch_result.go b/Godeps/_workspace/src/github.com/huandu/facebook/batch_result.go
deleted file mode 100644
index 43a38358e..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/batch_result.go
+++ /dev/null
@@ -1,52 +0,0 @@
-// A facebook graph api client in go.
-// https://github.com/huandu/facebook/
-//
-// Copyright 2012 - 2015, Huan Du
-// Licensed under the MIT license
-// https://github.com/huandu/facebook/blob/master/LICENSE
-
-package facebook
-
-import (
- "encoding/json"
- "net/http"
-)
-
-type batchResultHeader struct {
- Name string `facebook=",required"`
- Value string `facebook=",required"`
-}
-
-type batchResultData struct {
- Code int `facebook=",required"`
- Headers []batchResultHeader `facebook=",required"`
- Body string `facebook=",required"`
-}
-
-func newBatchResult(res Result) (*BatchResult, error) {
- var data batchResultData
- err := res.Decode(&data)
-
- if err != nil {
- return nil, err
- }
-
- result := &BatchResult{
- StatusCode: data.Code,
- Header: http.Header{},
- Body: data.Body,
- }
-
- err = json.Unmarshal([]byte(result.Body), &result.Result)
-
- if err != nil {
- return nil, err
- }
-
- // add headers to result.
- for _, header := range data.Headers {
- result.Header.Add(header.Name, header.Value)
- }
-
- return result, nil
-}
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/const.go b/Godeps/_workspace/src/github.com/huandu/facebook/const.go
deleted file mode 100644
index aa8be0de2..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/const.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// A facebook graph api client in go.
-// https://github.com/huandu/facebook/
-//
-// Copyright 2012 - 2015, Huan Du
-// Licensed under the MIT license
-// https://github.com/huandu/facebook/blob/master/LICENSE
-
-package facebook
-
-import (
- "encoding/json"
- "reflect"
- "regexp"
- "time"
-)
-
-// Facebook graph api methods.
-const (
- GET Method = "GET"
- POST Method = "POST"
- DELETE Method = "DELETE"
- PUT Method = "PUT"
-)
-
-const (
- ERROR_CODE_UNKNOWN = -1 // unknown facebook graph api error code.
-
- _MIME_FORM_URLENCODED = "application/x-www-form-urlencoded"
-)
-
-// Graph API debug mode values.
-const (
- DEBUG_OFF DebugMode = "" // turn off debug.
-
- DEBUG_ALL DebugMode = "all"
- DEBUG_INFO DebugMode = "info"
- DEBUG_WARNING DebugMode = "warning"
-)
-
-const (
- debugInfoKey = "__debug__"
- debugProtoKey = "__proto__"
- debugHeaderKey = "__header__"
-
- facebookApiVersionHeader = "facebook-api-version"
- facebookDebugHeader = "x-fb-debug"
- facebookRevHeader = "x-fb-rev"
-)
-
-var (
- // Maps aliases to Facebook domains.
- // Copied from Facebook PHP SDK.
- domainMap = map[string]string{
- "api": "https://api.facebook.com/",
- "api_video": "https://api-video.facebook.com/",
- "api_read": "https://api-read.facebook.com/",
- "graph": "https://graph.facebook.com/",
- "graph_video": "https://graph-video.facebook.com/",
- "www": "https://www.facebook.com/",
- }
-
- // checks whether it's a video post.
- regexpIsVideoPost = regexp.MustCompile(`/^(\/)(.+)(\/)(videos)$/`)
-
- // default facebook session.
- defaultSession = &Session{}
-
- typeOfPointerToBinaryData = reflect.TypeOf(&binaryData{})
- typeOfPointerToBinaryFile = reflect.TypeOf(&binaryFile{})
- typeOfJSONNumber = reflect.TypeOf(json.Number(""))
- typeOfTime = reflect.TypeOf(time.Time{})
-
- facebookSuccessJsonBytes = []byte("true")
-)
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/facebook_test.go b/Godeps/_workspace/src/github.com/huandu/facebook/facebook_test.go
deleted file mode 100644
index 154881f38..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/facebook_test.go
+++ /dev/null
@@ -1,1469 +0,0 @@
-// A facebook graph api client in go.
-// https://github.com/huandu/facebook/
-//
-// Copyright 2012 - 2015, Huan Du
-// Licensed under the MIT license
-// https://github.com/huandu/facebook/blob/master/LICENSE
-
-package facebook
-
-import (
- "bytes"
- "encoding/base64"
- "encoding/json"
- "fmt"
- "testing"
- "time"
-)
-
-const (
- FB_TEST_APP_ID = "169186383097898"
- FB_TEST_APP_SECRET = "b2e4262c306caa3c7f5215d2d099b319"
-
- // remeber to change it to a valid token to run test
- //FB_TEST_VALID_ACCESS_TOKEN = "CAACZA38ZAD8CoBAFCaVgLBNdz0RrH45yUBUA95exI1FY5i4mZBY5iULfM3YEpS53nP6eSF4cf3nmoiePHvMkdSZApkxu1heAupW7OE8tmiySRZAYkZBZBvhveCZCgPaJlFovlI0ZAhWdWTLxxmJaZCKDG0B8n9VGEvcN3zoS1AHjokSz4aNos39xthp7XtAz9X3NRvp1qU4UTOlxK8IJOC1ApAMmvcEE0kWvgZD"
- FB_TEST_VALID_ACCESS_TOKEN = ""
-
- // remember to change it to a valid signed request to run test
- //FB_TEST_VALID_SIGNED_REQUEST = "ZAxP-ILRQBOwKKxCBMNlGmVraiowV7WFNg761OYBNGc.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEzNDM0OTg0MDAsImlzc3VlZF9hdCI6MTM0MzQ5MzI2NSwib2F1dGhfdG9rZW4iOiJBQUFDWkEzOFpBRDhDb0JBRFpCcmZ5TFpDanBNUVczdThVTWZmRldSWkNpZGw5Tkx4a1BsY2tTcXZaQnpzTW9OWkF2bVk2RUd2NG1hUUFaQ0t2VlpBWkJ5VXA5a0FCU2x6THFJejlvZTdOdHBzdzhyQVpEWkQiLCJ1c2VyIjp7ImNvdW50cnkiOiJ1cyIsImxvY2FsZSI6ImVuX1VTIiwiYWdlIjp7Im1pbiI6MjF9fSwidXNlcl9pZCI6IjUzODc0NDQ2OCJ9"
- FB_TEST_VALID_SIGNED_REQUEST = ""
-
- // test binary file base64 value
- FB_TEST_BINARY_JPG_FILE = "/9j/4AAQSkZJRgABAQEASABIAAD/4gv4SUNDX1BST0ZJTEUAAQEAAAvoAAAAAAIAAABtbnRy" +
- "UkdCIFhZWiAH2QADABsAFQAkAB9hY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAA" +
- "9tYAAQAAAADTLQAAAAAp+D3er/JVrnhC+uTKgzkNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
- "AAAAAAAAABBkZXNjAAABRAAAAHliWFlaAAABwAAAABRiVFJDAAAB1AAACAxkbWRkAAAJ4AAA" +
- "AIhnWFlaAAAKaAAAABRnVFJDAAAB1AAACAxsdW1pAAAKfAAAABRtZWFzAAAKkAAAACRia3B0" +
- "AAAKtAAAABRyWFlaAAAKyAAAABRyVFJDAAAB1AAACAx0ZWNoAAAK3AAAAAx2dWVkAAAK6AAA" +
- "AId3dHB0AAALcAAAABRjcHJ0AAALhAAAADdjaGFkAAALvAAAACxkZXNjAAAAAAAAAB9zUkdC" +
- "IElFQzYxOTY2LTItMSBibGFjayBzY2FsZWQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
- "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
- "WFlaIAAAAAAAACSgAAAPhAAAts9jdXJ2AAAAAAAABAAAAAAFAAoADwAUABkAHgAjACgALQAy" +
- "ADcAOwBAAEUASgBPAFQAWQBeAGMAaABtAHIAdwB8AIEAhgCLAJAAlQCaAJ8ApACpAK4AsgC3" +
- "ALwAwQDGAMsA0ADVANsA4ADlAOsA8AD2APsBAQEHAQ0BEwEZAR8BJQErATIBOAE+AUUBTAFS" +
- "AVkBYAFnAW4BdQF8AYMBiwGSAZoBoQGpAbEBuQHBAckB0QHZAeEB6QHyAfoCAwIMAhQCHQIm" +
- "Ai8COAJBAksCVAJdAmcCcQJ6AoQCjgKYAqICrAK2AsECywLVAuAC6wL1AwADCwMWAyEDLQM4" +
- "A0MDTwNaA2YDcgN+A4oDlgOiA64DugPHA9MD4APsA/kEBgQTBCAELQQ7BEgEVQRjBHEEfgSM" +
- "BJoEqAS2BMQE0wThBPAE/gUNBRwFKwU6BUkFWAVnBXcFhgWWBaYFtQXFBdUF5QX2BgYGFgYn" +
- "BjcGSAZZBmoGewaMBp0GrwbABtEG4wb1BwcHGQcrBz0HTwdhB3QHhgeZB6wHvwfSB+UH+AgL" +
- "CB8IMghGCFoIbgiCCJYIqgi+CNII5wj7CRAJJQk6CU8JZAl5CY8JpAm6Cc8J5Qn7ChEKJwo9" +
- "ClQKagqBCpgKrgrFCtwK8wsLCyILOQtRC2kLgAuYC7ALyAvhC/kMEgwqDEMMXAx1DI4MpwzA" +
- "DNkM8w0NDSYNQA1aDXQNjg2pDcMN3g34DhMOLg5JDmQOfw6bDrYO0g7uDwkPJQ9BD14Peg+W" +
- "D7MPzw/sEAkQJhBDEGEQfhCbELkQ1xD1ERMRMRFPEW0RjBGqEckR6BIHEiYSRRJkEoQSoxLD" +
- "EuMTAxMjE0MTYxODE6QTxRPlFAYUJxRJFGoUixStFM4U8BUSFTQVVhV4FZsVvRXgFgMWJhZJ" +
- "FmwWjxayFtYW+hcdF0EXZReJF64X0hf3GBsYQBhlGIoYrxjVGPoZIBlFGWsZkRm3Gd0aBBoq" +
- "GlEadxqeGsUa7BsUGzsbYxuKG7Ib2hwCHCocUhx7HKMczBz1HR4dRx1wHZkdwx3sHhYeQB5q" +
- "HpQevh7pHxMfPh9pH5Qfvx/qIBUgQSBsIJggxCDwIRwhSCF1IaEhziH7IiciVSKCIq8i3SMK" +
- "IzgjZiOUI8Ij8CQfJE0kfCSrJNolCSU4JWgllyXHJfcmJyZXJocmtyboJxgnSSd6J6sn3CgN" +
- "KD8ocSiiKNQpBik4KWspnSnQKgIqNSpoKpsqzysCKzYraSudK9EsBSw5LG4soizXLQwtQS12" +
- "Last4S4WLkwugi63Lu4vJC9aL5Evxy/+MDUwbDCkMNsxEjFKMYIxujHyMioyYzKbMtQzDTNG" +
- "M38zuDPxNCs0ZTSeNNg1EzVNNYc1wjX9Njc2cjauNuk3JDdgN5w31zgUOFA4jDjIOQU5Qjl/" +
- "Obw5+To2OnQ6sjrvOy07azuqO+g8JzxlPKQ84z0iPWE9oT3gPiA+YD6gPuA/IT9hP6I/4kAj" +
- "QGRApkDnQSlBakGsQe5CMEJyQrVC90M6Q31DwEQDREdEikTORRJFVUWaRd5GIkZnRqtG8Ec1" +
- "R3tHwEgFSEtIkUjXSR1JY0mpSfBKN0p9SsRLDEtTS5pL4kwqTHJMuk0CTUpNk03cTiVObk63" +
- "TwBPSU+TT91QJ1BxULtRBlFQUZtR5lIxUnxSx1MTU19TqlP2VEJUj1TbVShVdVXCVg9WXFap" +
- "VvdXRFeSV+BYL1h9WMtZGllpWbhaB1pWWqZa9VtFW5Vb5Vw1XIZc1l0nXXhdyV4aXmxevV8P" +
- "X2Ffs2AFYFdgqmD8YU9homH1YklinGLwY0Njl2PrZEBklGTpZT1lkmXnZj1mkmboZz1nk2fp" +
- "aD9olmjsaUNpmmnxakhqn2r3a09rp2v/bFdsr20IbWBtuW4SbmtuxG8eb3hv0XArcIZw4HE6" +
- "cZVx8HJLcqZzAXNdc7h0FHRwdMx1KHWFdeF2Pnabdvh3VnezeBF4bnjMeSp5iXnnekZ6pXsE" +
- "e2N7wnwhfIF84X1BfaF+AX5ifsJ/I3+Ef+WAR4CogQqBa4HNgjCCkoL0g1eDuoQdhICE44VH" +
- "hauGDoZyhteHO4efiASIaYjOiTOJmYn+imSKyoswi5aL/IxjjMqNMY2Yjf+OZo7OjzaPnpAG" +
- "kG6Q1pE/kaiSEZJ6kuOTTZO2lCCUipT0lV+VyZY0lp+XCpd1l+CYTJi4mSSZkJn8mmia1ZtC" +
- "m6+cHJyJnPedZJ3SnkCerp8dn4uf+qBpoNihR6G2oiailqMGo3aj5qRWpMelOKWpphqmi6b9" +
- "p26n4KhSqMSpN6mpqhyqj6sCq3Wr6axcrNCtRK24ri2uoa8Wr4uwALB1sOqxYLHWskuywrM4" +
- "s660JbSctRO1irYBtnm28Ldot+C4WbjRuUq5wro7urW7LrunvCG8m70VvY++Cr6Evv+/er/1" +
- "wHDA7MFnwePCX8Lbw1jD1MRRxM7FS8XIxkbGw8dBx7/IPci8yTrJuco4yrfLNsu2zDXMtc01" +
- "zbXONs62zzfPuNA50LrRPNG+0j/SwdNE08bUSdTL1U7V0dZV1tjXXNfg2GTY6Nls2fHadtr7" +
- "24DcBdyK3RDdlt4c3qLfKd+v4DbgveFE4cziU+Lb42Pj6+Rz5PzlhOYN5pbnH+ep6DLovOlG" +
- "6dDqW+rl63Dr++yG7RHtnO4o7rTvQO/M8Fjw5fFy8f/yjPMZ86f0NPTC9VD13vZt9vv3ivgZ" +
- "+Kj5OPnH+lf65/t3/Af8mP0p/br+S/7c/23//2Rlc2MAAAAAAAAALklFQyA2MTk2Ni0yLTEg" +
- "RGVmYXVsdCBSR0IgQ29sb3VyIFNwYWNlIC0gc1JHQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
- "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
- "AABYWVogAAAAAAAAYpkAALeFAAAY2lhZWiAAAAAAAAAAAABQAAAAAAAAbWVhcwAAAAAAAAAB" +
- "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACWFlaIAAAAAAAAAMWAAADMwAAAqRYWVogAAAAAAAA" +
- "b6IAADj1AAADkHNpZyAAAAAAQ1JUIGRlc2MAAAAAAAAALVJlZmVyZW5jZSBWaWV3aW5nIENv" +
- "bmRpdGlvbiBpbiBJRUMgNjE5NjYtMi0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
- "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYWVog" +
- "AAAAAAAA9tYAAQAAAADTLXRleHQAAAAAQ29weXJpZ2h0IEludGVybmF0aW9uYWwgQ29sb3Ig" +
- "Q29uc29ydGl1bSwgMjAwOQAAc2YzMgAAAAAAAQxEAAAF3///8yYAAAeUAAD9j///+6H///2i" +
- "AAAD2wAAwHX/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEPERETFhwXExQa" +
- "FRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4eHh4eHh4e" +
- "Hh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/wAARCAAxADIDASIAAhEB" +
- "AxEB/8QAHQAAAQQDAQEAAAAAAAAAAAAAAAUGBwgBAwQJAv/EADYQAAEDAwIEAgcGBwAAAAAA" +
- "AAECAwQABREGIQcSEzFBUQgUIjJhgZEVQnFyobEWIzeFkrLx/8QAGQEBAAMBAQAAAAAAAAAA" +
- "AAAABAECAwUG/8QAKREAAgEDAgQFBQAAAAAAAAAAAAECAxEhBBITMUGBBRQzscEiMlFhcf/a" +
- "AAwDAQACEQMRAD8A23GcGQVdFS2BgPLSfdHiaZnEjWdtslhaehy0rcceCm2G0+1sd1DPbsae" +
- "EvTlylyWnnG5MVbYw44hsHrIIIKVDwG/6VWTXaHJ2qJwiuuyWmXVNoUrJPKk4Hxoiozg1vTX" +
- "YSqkJp7Gmd184namuAS03MSy2kJ91tKlE+ZJFK2iOMGu9OT/AFpq5IlNqQErZksJW2tIOcbA" +
- "EfiDTHi2h1SA6GnNiAsFJwnPY58jQ7Floe6K0FByBvt3pEYJ/bgzluSyXh4N8WbLxEjLjttG" +
- "33lhHO/DWrmCk9ittX3k589xnfzqRDXnroO+TtE8QbVdFKciuw5iA8CO7ROHEkeIKSa9CkLb" +
- "dQl1lYW0sBSFA5CkncH6UiN+oeSszHyorNFSVOt1hooV/KQdj90VRdFmeZ4x6gtcpohaZLx5" +
- "AAAoFfMPwGCk58Kvear3xq0tDsvFWzau6eIl05oM7yC1JPTV8M45f8aPX6N/z5XsJ0rW+wl6" +
- "fYhyz9lyrVDCgA0oNykO4z2CwB7JPfFcz+kXXLq0hNjYmLIKOvIc5W2UeCUoAPN8zTtkQ7PZ" +
- "bJ1oCGmQVJUrlABAGNzj4Ab/AIVmPqQLkSHYBDkVCeo4txPK2CfAKPjQZVat9sVj8noI0YW+" +
- "p5RCPpC6RRbplrnwkIDzmGHEp2ClAeyf3H0q3mj0BrSVnaBJCILKdz5IAqAdfSbc65b7tqRa" +
- "W7e1cI63EkcwS3zjm7fAmpI0nxo0LqPWTWk7C7NfdWFIjyBG5WF8iSSE5PMAAnYkAGmaW6ja" +
- "T5YOP4go8S8VzySTRXzmilnNuKWaS9T2S36gtTtuuLCXWXB2I7HuD9QD8qUqwTUSgpKz5Exk" +
- "4u6K9a0tU+yvvwFOuMpcOGHSkLHnjfYn/tN6FEU6EMTOmpCXAtTjrhUV/AA7AUn+m9qWYNV2" +
- "SwxnXGmokcyiWyQS6okA5HkAfqaj7SOp4lyt5/iCZLPQbPUSl3AOPEgbkGiwpykttzqUta4L" +
- "lkdfEWbF1A1PZVJS1aYLC+rI+6XMYAT54P67VF3D25XDTd4b1FBe9XkRN2XAMnON9j3GNsfG" +
- "tl8v0nUjyYMVr1K0ML5m2UjHNjsVeZ8h4V1x4DK2Exjnp8u/L479hVnTUFh4DTq8WX7LFwPS" +
- "V04qCwqXpy7iQWkl0NcpQF435Sd8ZziioOQEpQlKUAJAwBjsKKr5iRXgIvpWFdqKKaEKVemf" +
- "/Vj+3M/7KqEo3vK/LRRR6XJ9/dm8+nb4HFC7R/yinDA9wfL9qKK01Hpopp/UOs0UUUAWf//Z"
-)
-
-var (
- testGlobalApp = New(FB_TEST_APP_ID, FB_TEST_APP_SECRET)
-)
-
-type AllTypes struct {
- Int int
- Int8 int8
- Int16 int16
- Int32 int32
- Int64 int64
- Uint uint
- Uint8 uint8
- Uint16 uint16
- Uint32 uint32
- Uint64 uint64
- Float32 float32
- Float64 float64
- String string
- ArrayOfInt []int
- MapOfString map[string]string
- NestedStruct *NestedStruct
-}
-
-type NestedStruct struct {
- Int int
- String string
- ArrayOfString []string
-}
-
-type ParamsStruct struct {
- Foo string
- Bar *ParamsNestedStruct
-}
-
-type ParamsNestedStruct struct {
- AAA int
- BBB string
- CCC bool
-}
-
-type FieldTagStruct struct {
- Field1 string `facebook:"field2"`
- Required string `facebook:",required"`
- Foo string `facebook:"bar,required"`
- CanAbsent string
-}
-
-type MessageTag struct {
- Id string
- Name string
- Type string
-}
-
-type MessageTags map[string][]*MessageTag
-
-type NullStruct struct {
- Null *int
-}
-
-func TestApiGetUserInfoV2(t *testing.T) {
- Version = "v2.2"
- defer func() {
- Version = ""
- }()
-
- // It's not allowed to get user info by name. So I get "me" with access token instead.
- if FB_TEST_VALID_ACCESS_TOKEN != "" {
- me, err := Api("me", GET, Params{
- "access_token": FB_TEST_VALID_ACCESS_TOKEN,
- })
-
- if err != nil {
- t.Fatalf("cannot get my info. [e:%v]", err)
- }
-
- if e := me.Err(); e != nil {
- t.Fatalf("facebook returns error. [e:%v]", e)
- }
-
- t.Logf("my info. %v", me)
- }
-}
-
-func TestBatchApiGetInfo(t *testing.T) {
- if FB_TEST_VALID_ACCESS_TOKEN == "" {
- t.Skipf("cannot call batch api without access token. skip this test.")
- }
-
- verifyBatchResult := func(t *testing.T, index int, res Result) {
- batch, err := res.Batch()
-
- if err != nil {
- t.Fatalf("cannot parse batch api results[%v]. [e:%v] [result:%v]", index, err, res)
- }
-
- if batch.StatusCode != 200 {
- t.Fatalf("facebook returns unexpected http status code in results[%v]. [code:%v] [result:%v]", index, batch.StatusCode, res)
- }
-
- contentType := batch.Header.Get("Content-Type")
-
- if contentType == "" {
- t.Fatalf("facebook returns unexpected http header in results[%v]. [header:%v]", index, batch.Header)
- }
-
- if batch.Body == "" {
- t.Fatalf("facebook returns unexpected http body in results[%v]. [body:%v]", index, batch.Body)
- }
-
- var id string
- err = batch.Result.DecodeField("id", &id)
-
- if err != nil {
- t.Fatalf("cannot get 'id' field in results[%v]. [result:%v]", index, res)
- }
-
- if id == "" {
- t.Fatalf("facebook should return account id in results[%v].", index)
- }
- }
-
- test := func(t *testing.T) {
- params1 := Params{
- "method": GET,
- "relative_url": "me",
- }
- params2 := Params{
- "method": GET,
- "relative_url": uint64(100002828925788), // id of my another facebook account
- }
-
- results, err := BatchApi(FB_TEST_VALID_ACCESS_TOKEN, params1, params2)
-
- if err != nil {
- t.Fatalf("cannot get batch result. [e:%v]", err)
- }
-
- if len(results) != 2 {
- t.Fatalf("batch api should return results in an array with 2 entries. [len:%v]", len(results))
- }
-
- if Version == "" {
- t.Log("use default facebook version.")
- } else {
- t.Logf("global facebook version: %v", Version)
- }
-
- for index, result := range results {
- verifyBatchResult(t, index, result)
- }
- }
-
- // Use default Version.
- Version = ""
- test(t)
-
- // User "v2.2".
- Version = "v2.2"
- defer func() {
- Version = ""
- }()
- test(t)
-
- // when providing an invalid access token, BatchApi should return a facebook error.
- _, err := BatchApi("an_invalid_access_token", Params{
- "method": GET,
- "relative_url": "me",
- })
-
- if err == nil {
- t.Fatalf("expect an error when providing an invalid access token to BatchApi.")
- }
-
- if _, ok := err.(*Error); !ok {
- t.Fatalf("batch result error must be an *Error. [e:%v]", err)
- }
-}
-
-func TestApiParseSignedRequest(t *testing.T) {
- if FB_TEST_VALID_SIGNED_REQUEST == "" {
- t.Logf("skip this case as we don't have a valid signed request.")
- return
- }
-
- app := New(FB_TEST_APP_ID, FB_TEST_APP_SECRET)
- res, err := app.ParseSignedRequest(FB_TEST_VALID_SIGNED_REQUEST)
-
- if err != nil {
- t.Fatalf("cannot parse signed request. [e:%v]", err)
- }
-
- t.Logf("signed request is '%v'.", res)
-}
-
-func TestSession(t *testing.T) {
- if FB_TEST_VALID_ACCESS_TOKEN == "" {
- t.Skipf("skip this case as we don't have a valid access token.")
- }
-
- session := &Session{}
- session.SetAccessToken(FB_TEST_VALID_ACCESS_TOKEN)
-
- test := func(t *testing.T, session *Session) {
- id, err := session.User()
-
- if err != nil {
- t.Fatalf("cannot get current user id. [e:%v]", err)
- }
-
- t.Logf("current user id is %v", id)
-
- result, e := session.Api("/me", GET, Params{
- "fields": "id,email,website",
- })
-
- if e != nil {
- t.Fatalf("cannot get my extended info. [e:%v]", e)
- }
-
- if Version == "" {
- t.Log("use default facebook version.")
- } else {
- t.Logf("global facebook version: %v", Version)
- }
-
- if session.Version == "" {
- t.Log("use default session facebook version.")
- } else {
- t.Logf("session facebook version: %v", session.Version)
- }
-
- t.Logf("my extended info is: %v", result)
- }
-
- // Default version.
- test(t, session)
-
- // Global version overwrite default session version.
- func() {
- Version = "v2.2"
- defer func() {
- Version = ""
- }()
-
- test(t, session)
- }()
-
- // Session version overwrite default version.
- func() {
- Version = "vx.y" // an invalid version.
- session.Version = "v2.2"
- defer func() {
- Version = ""
- }()
-
- test(t, session)
- }()
-
- // Session with appsecret proof enabled.
- if FB_TEST_VALID_ACCESS_TOKEN != "" {
- app := New(FB_TEST_APP_ID, FB_TEST_APP_SECRET)
- app.EnableAppsecretProof = true
- session := app.Session(FB_TEST_VALID_ACCESS_TOKEN)
-
- _, e := session.Api("/me", GET, Params{
- "fields": "id",
- })
-
- if e != nil {
- t.Fatalf("cannot get my info with proof. [e:%v]", e)
- }
- }
-}
-
-func TestUploadingBinary(t *testing.T) {
- if FB_TEST_VALID_ACCESS_TOKEN == "" {
- t.Skipf("skip this case as we don't have a valid access token.")
- }
-
- buf := bytes.NewBufferString(FB_TEST_BINARY_JPG_FILE)
- reader := base64.NewDecoder(base64.StdEncoding, buf)
-
- session := &Session{}
- session.SetAccessToken(FB_TEST_VALID_ACCESS_TOKEN)
-
- result, e := session.Api("/me/photos", POST, Params{
- "message": "Test photo from https://github.com/huandu/facebook",
- "source": Data("my_profile.jpg", reader),
- })
-
- if e != nil {
- t.Fatalf("cannot create photo on my timeline. [e:%v]", e)
- }
-
- var id string
- e = result.DecodeField("id", &id)
-
- if e != nil {
- t.Fatalf("facebook should return photo id on success. [e:%v]", e)
- }
-
- t.Logf("newly created photo id is %v", id)
-}
-
-func TestUploadBinaryWithBatch(t *testing.T) {
- if FB_TEST_VALID_ACCESS_TOKEN == "" {
- t.Skipf("skip this case as we don't have a valid access token.")
- }
-
- buf1 := bytes.NewBufferString(FB_TEST_BINARY_JPG_FILE)
- reader1 := base64.NewDecoder(base64.StdEncoding, buf1)
- buf2 := bytes.NewBufferString(FB_TEST_BINARY_JPG_FILE)
- reader2 := base64.NewDecoder(base64.StdEncoding, buf2)
-
- session := &Session{}
- session.SetAccessToken(FB_TEST_VALID_ACCESS_TOKEN)
-
- // sample comes from facebook batch api sample.
- // https://developers.facebook.com/docs/reference/api/batch/
- //
- // curl
- // -F 'access_token=…' \
- // -F 'batch=[{"method":"POST","relative_url":"me/photos","body":"message=My cat photo","attached_files":"file1"},{"method":"POST","relative_url":"me/photos","body":"message=My dog photo","attached_files":"file2"},]' \
- // -F 'file1=@cat.gif' \
- // -F 'file2=@dog.jpg' \
- // https://graph.facebook.com
- result, e := session.Batch(Params{
- "file1": Data("cat.jpg", reader1),
- "file2": Data("dog.jpg", reader2),
- }, Params{
- "method": POST,
- "relative_url": "me/photos",
- "body": "message=My cat photo",
- "attached_files": "file1",
- }, Params{
- "method": POST,
- "relative_url": "me/photos",
- "body": "message=My dog photo",
- "attached_files": "file2",
- })
-
- if e != nil {
- t.Fatalf("cannot create photo on my timeline. [e:%v]", e)
- }
-
- t.Logf("batch call result. [result:%v]", result)
-}
-
-func TestSimpleFQL(t *testing.T) {
- defer func() {
- Version = ""
- }()
-
- test := func(t *testing.T, session *Session) {
- me, err := session.FQL("SELECT name FROM user WHERE uid = 538744468")
-
- if err != nil {
- t.Fatalf("cannot get my info. [e:%v]", err)
- }
-
- if len(me) != 1 {
- t.Fatalf("expect to get only 1 result. [len:%v]", len(me))
- }
-
- t.Logf("my name. %v", me[0]["name"])
- }
-
- // v2.2 api doesn't allow me to query user without access token.
- if FB_TEST_VALID_ACCESS_TOKEN == "" {
- return
- }
-
- Version = "v2.2"
- session := &Session{}
- session.SetAccessToken(FB_TEST_VALID_ACCESS_TOKEN)
- test(t, session)
-}
-
-func TestMultiFQL(t *testing.T) {
- defer func() {
- Version = ""
- }()
-
- test := func(t *testing.T, session *Session) {
- res, err := session.MultiFQL(Params{
- "query1": "SELECT username FROM page WHERE page_id = 20531316728",
- "query2": "SELECT uid FROM user WHERE uid = 538744468",
- })
-
- if err != nil {
- t.Fatalf("cannot get my info. [e:%v]", err)
- }
-
- if err = res.Err(); err != nil {
- t.Fatalf("fail to parse facebook api error. [e:%v]", err)
- }
-
- var query1, query2 []Result
-
- err = res.DecodeField("query1", &query1)
-
- if err != nil {
- t.Fatalf("cannot get result of query1. [e:%v]", err)
- }
-
- if len(query1) != 1 {
- t.Fatalf("expect to get only 1 result in query1. [len:%v]", len(query1))
- }
-
- err = res.DecodeField("query2", &query2)
-
- if err != nil {
- t.Fatalf("cannot get result of query2. [e:%v]", err)
- }
-
- if len(query2) != 1 {
- t.Fatalf("expect to get only 1 result in query2. [len:%v]", len(query2))
- }
-
- var username string
- var uid string
-
- err = query1[0].DecodeField("username", &username)
-
- if err != nil {
- t.Fatalf("cannot decode username from query1. [e:%v]", err)
- }
-
- if username != "facebook" {
- t.Fatalf("username is expected to be 'facebook'. [username:%v]", username)
- }
-
- err = query2[0].DecodeField("uid", &uid)
-
- if err != nil {
- t.Fatalf("cannot decode username from query2. [e:%v] [query2:%v]", err, query2)
- }
-
- if uid != "538744468" {
- t.Fatalf("username is expected to be 'facebook'. [username:%v]", username)
- }
- }
-
- // v2.2 api doesn't allow me to query user without access token.
- if FB_TEST_VALID_ACCESS_TOKEN == "" {
- return
- }
-
- Version = "v2.2"
- session := &Session{}
- session.SetAccessToken(FB_TEST_VALID_ACCESS_TOKEN)
- test(t, session)
-}
-
-func TestGraphDebuggingAPI(t *testing.T) {
- if FB_TEST_VALID_ACCESS_TOKEN == "" {
- t.Skipf("cannot call batch api without access token. skip this test.")
- }
-
- test := func(t *testing.T, session *Session) {
- session.SetAccessToken(FB_TEST_VALID_ACCESS_TOKEN)
- defer session.SetAccessToken("")
-
- // test app must not grant "read_friendlists" permission.
- // otherwise there is no way to get a warning from facebook.
- res, _ := session.Get("/me/friendlists", nil)
-
- if res == nil {
- t.Fatalf("res must not be nil.")
- }
-
- debugInfo := res.DebugInfo()
-
- if debugInfo == nil {
- t.Fatalf("debug info must exist.")
- }
-
- t.Logf("facebook response is: %v", res)
- t.Logf("debug info is: %v", *debugInfo)
-
- if debugInfo.Messages == nil && len(debugInfo.Messages) > 0 {
- t.Fatalf("facebook must warn me for the permission issue.")
- }
-
- msg := debugInfo.Messages[0]
-
- if msg.Type == "" || msg.Message == "" {
- t.Fatalf("facebook must say something. [msg:%v]", msg)
- }
-
- if debugInfo.FacebookApiVersion == "" {
- t.Fatalf("facebook must tell me api version.")
- }
-
- if debugInfo.FacebookDebug == "" {
- t.Fatalf("facebook must tell me X-FB-Debug.")
- }
-
- if debugInfo.FacebookRev == "" {
- t.Fatalf("facebook must tell me x-fb-rev.")
- }
- }
-
- defer func() {
- Debug = DEBUG_OFF
- Version = ""
- }()
-
- Version = "v2.2"
- Debug = DEBUG_ALL
- test(t, defaultSession)
- session := &Session{}
- session.SetDebug(DEBUG_ALL)
- test(t, session)
-
- // test changing debug mode.
- old := session.SetDebug(DEBUG_OFF)
-
- if old != DEBUG_ALL {
- t.Fatalf("debug mode must be DEBUG_ALL. [debug:%v]", old)
- }
-
- if session.Debug() != DEBUG_ALL {
- t.Fatalf("debug mode must be DEBUG_ALL [debug:%v]", session.Debug())
- }
-
- Debug = DEBUG_OFF
-
- if session.Debug() != DEBUG_OFF {
- t.Fatalf("debug mode must be DEBUG_OFF. [debug:%v]", session.Debug())
- }
-}
-
-func TestResultDecode(t *testing.T) {
- strNormal := `{
- "int": 1234,
- "int8": 23,
- "int16": 12345,
- "int32": -127372843,
- "int64": 192438483489298,
- "uint": 1283829,
- "uint8": 233,
- "uint16": 62121,
- "uint32": 3083747392,
- "uint64": 2034857382993849,
- "float32": 9382.38429,
- "float64": 3984.293848292,
- "map_of_string": {"a": "1", "b": "2"},
- "array_of_int": [12, 34, 56],
- "string": "abcd",
- "notused": 1234,
- "nested_struct": {
- "string": "hello",
- "int": 123,
- "array_of_string": ["a", "b", "c"]
- }
- }`
- strOverflow := `{
- "int": 1234,
- "int8": 23,
- "int16": 12345,
- "int32": -127372843,
- "int64": 192438483489298,
- "uint": 1283829,
- "uint8": 233,
- "uint16": 62121,
- "uint32": 383083747392,
- "uint64": 2034857382993849,
- "float32": 9382.38429,
- "float64": 3984.293848292,
- "string": "abcd",
- "map_of_string": {"a": "1", "b": "2"},
- "array_of_int": [12, 34, 56],
- "string": "abcd",
- "notused": 1234,
- "nested_struct": {
- "string": "hello",
- "int": 123,
- "array_of_string": ["a", "b", "c"]
- }
- }`
- strMissAField := `{
- "int": 1234,
- "int8": 23,
- "int16": 12345,
- "int32": -127372843,
-
- "missed": "int64",
-
- "uint": 1283829,
- "uint8": 233,
- "uint16": 62121,
- "uint32": 383083747392,
- "uint64": 2034857382993849,
- "float32": 9382.38429,
- "float64": 3984.293848292,
- "string": "abcd",
- "map_of_string": {"a": "1", "b": "2"},
- "array_of_int": [12, 34, 56],
- "string": "abcd",
- "notused": 1234,
- "nested_struct": {
- "string": "hello",
- "int": 123,
- "array_of_string": ["a", "b", "c"]
- }
- }`
- var result Result
- var err error
- var normal, withError AllTypes
- var anInt int
-
- err = json.Unmarshal([]byte(strNormal), &result)
-
- if err != nil {
- t.Fatalf("cannot unmarshal json string. [e:%v]", err)
- }
-
- err = result.Decode(&normal)
-
- if err != nil {
- t.Fatalf("cannot decode normal struct. [e:%v]", err)
- }
-
- err = json.Unmarshal([]byte(strOverflow), &result)
-
- if err != nil {
- t.Fatalf("cannot unmarshal json string. [e:%v]", err)
- }
-
- err = result.Decode(&withError)
-
- if err == nil {
- t.Fatalf("struct should be overflow")
- }
-
- t.Logf("overflow struct. e:%v", err)
-
- err = json.Unmarshal([]byte(strMissAField), &result)
-
- if err != nil {
- t.Fatalf("cannot unmarshal json string. [e:%v]", err)
- }
-
- err = result.Decode(&withError)
-
- if err == nil {
- t.Fatalf("a field in struct should absent in json map.")
- }
-
- t.Logf("miss-a-field struct. e:%v", err)
-
- err = result.DecodeField("array_of_int.2", &anInt)
-
- if err != nil {
- t.Fatalf("cannot decode array item. [e:%v]", err)
- }
-
- if anInt != 56 {
- t.Fatalf("invalid array value. expected 56, actual %v", anInt)
- }
-
- err = result.DecodeField("nested_struct.int", &anInt)
-
- if err != nil {
- t.Fatalf("cannot decode nested struct item. [e:%v]", err)
- }
-
- if anInt != 123 {
- t.Fatalf("invalid array value. expected 123, actual %v", anInt)
- }
-}
-
-func TestParamsEncode(t *testing.T) {
- var params Params
- buf := &bytes.Buffer{}
-
- if mime, err := params.Encode(buf); err != nil || mime != _MIME_FORM_URLENCODED || buf.Len() != 0 {
- t.Fatalf("empty params must encode to an empty string. actual is [e:%v] [str:%v] [mime:%v]", err, buf.String(), mime)
- }
-
- buf.Reset()
- params = Params{}
- params["need_escape"] = "&=+"
- expectedEncoding := "need_escape=%26%3D%2B"
-
- if mime, err := params.Encode(buf); err != nil || mime != _MIME_FORM_URLENCODED || buf.String() != expectedEncoding {
- t.Fatalf("wrong params encode result. expected is '%v'. actual is '%v'. [e:%v] [mime:%v]", expectedEncoding, buf.String(), err, mime)
- }
-
- buf.Reset()
- data := ParamsStruct{
- Foo: "hello, world!",
- Bar: &ParamsNestedStruct{
- AAA: 1234,
- BBB: "bbb",
- CCC: true,
- },
- }
- params = MakeParams(data)
- /* there is no easy way to compare two encoded maps. so i just write expect map here, not test it.
- expectedParams := Params{
- "foo": "hello, world!",
- "bar": map[string]interface{}{
- "aaa": 1234,
- "bbb": "bbb",
- "ccc": true,
- },
- }
- */
-
- if params == nil {
- t.Fatalf("make params error.")
- }
-
- mime, err := params.Encode(buf)
- t.Logf("complex encode result is '%v'. [e:%v] [mime:%v]", buf.String(), err, mime)
-}
-
-func TestStructFieldTag(t *testing.T) {
- strNormalField := `{
- "field2": "hey",
- "required": "my",
- "bar": "dear"
- }`
- strMissingField2Field := `{
- "field1": "hey",
- "required": "my",
- "bar": "dear"
- }`
- strMissingRequiredField := `{
- "field1": "hey",
- "bar": "dear",
- "can_absent": "babe"
- }`
- strMissingBarField := `{
- "field1": "hey",
- "required": "my"
- }`
-
- var result Result
- var value FieldTagStruct
- var err error
-
- err = json.Unmarshal([]byte(strNormalField), &result)
-
- if err != nil {
- t.Fatalf("cannot unmarshal json string. [e:%v]", err)
- }
-
- err = result.Decode(&value)
-
- if err != nil {
- t.Fatalf("cannot decode struct. [e:%v]", err)
- }
-
- result = Result{}
- value = FieldTagStruct{}
- err = json.Unmarshal([]byte(strMissingField2Field), &result)
-
- if err != nil {
- t.Fatalf("cannot unmarshal json string. [e:%v]", err)
- }
-
- err = result.Decode(&value)
-
- if err != nil {
- t.Fatalf("cannot decode struct. [e:%v]", err)
- }
-
- if value.Field1 != "" {
- t.Fatalf("value field1 should be kept unchanged. [field1:%v]", value.Field1)
- }
-
- result = Result{}
- value = FieldTagStruct{}
- err = json.Unmarshal([]byte(strMissingRequiredField), &result)
-
- if err != nil {
- t.Fatalf("cannot unmarshal json string. [e:%v]", err)
- }
-
- err = result.Decode(&value)
-
- if err == nil {
- t.Fatalf("should fail to decode struct.")
- }
-
- t.Logf("expected decode error. [e:%v]", err)
-
- result = Result{}
- value = FieldTagStruct{}
- err = json.Unmarshal([]byte(strMissingBarField), &result)
-
- if err != nil {
- t.Fatalf("cannot unmarshal json string. [e:%v]", err)
- }
-
- err = result.Decode(&value)
-
- if err == nil {
- t.Fatalf("should fail to decode struct.")
- }
-
- t.Logf("expected decode error. [e:%v]", err)
-}
-
-type myTime time.Time
-
-func TestDecodeField(t *testing.T) {
- jsonStr := `{
- "int": 1234,
- "array": ["abcd", "efgh"],
- "map": {
- "key1": 5678,
- "nested_map": {
- "key2": "ijkl",
- "key3": [{
- "key4": "mnop"
- }, {
- "key5": 9012
- }]
- }
- },
- "message_tags": {
- "2": [
- {
- "id": "4838901",
- "name": "Foo Bar",
- "type": "page"
- },
- {
- "id": "293450302",
- "name": "Player Rocks",
- "type": "page"
- }
- ]
- },
- "nullStruct": {
- "null": null
- },
- "timestamp": "2015-01-03T11:15:01+0000",
- "custom_timestamp": "2014-03-04T11:15:01+0000"
- }`
-
- var result Result
- var err error
- var anInt int
- var aString string
- var aSlice []string
- var subResults []Result
- var aNull NullStruct = NullStruct{
- Null: &anInt,
- }
- var aTimestamp time.Time
- var aCustomTimestamp myTime
-
- err = json.Unmarshal([]byte(jsonStr), &result)
-
- if err != nil {
- t.Fatalf("invalid json string. [e:%v]", err)
- }
-
- err = result.DecodeField("int", &anInt)
-
- if err != nil {
- t.Fatalf("cannot decode int field. [e:%v]", err)
- }
-
- if anInt != 1234 {
- t.Fatalf("expected int value is 1234. [int:%v]", anInt)
- }
-
- err = result.DecodeField("array.0", &aString)
-
- if err != nil {
- t.Fatalf("cannot decode array.0 field. [e:%v]", err)
- }
-
- if aString != "abcd" {
- t.Fatalf("expected array.0 value is 'abcd'. [string:%v]", aString)
- }
-
- err = result.DecodeField("array.1", &aString)
-
- if err != nil {
- t.Fatalf("cannot decode array.1 field. [e:%v]", err)
- }
-
- if aString != "efgh" {
- t.Fatalf("expected array.1 value is 'abcd'. [string:%v]", aString)
- }
-
- err = result.DecodeField("array.2", &aString)
-
- if err == nil {
- t.Fatalf("array.2 doesn't exist. expect an error.")
- }
-
- err = result.DecodeField("map.key1", &anInt)
-
- if err != nil {
- t.Fatalf("cannot decode map.key1 field. [e:%v]", err)
- }
-
- if anInt != 5678 {
- t.Fatalf("expected map.key1 value is 5678. [int:%v]", anInt)
- }
-
- err = result.DecodeField("map.nested_map.key2", &aString)
-
- if err != nil {
- t.Fatalf("cannot decode map.nested_map.key2 field. [e:%v]", err)
- }
-
- if aString != "ijkl" {
- t.Fatalf("expected map.nested_map.key2 value is 'ijkl'. [string:%v]", aString)
- }
-
- err = result.DecodeField("array", &aSlice)
-
- if err != nil {
- t.Fatalf("cannot decode array field. [e:%v]", err)
- }
-
- if len(aSlice) != 2 || aSlice[0] != "abcd" || aSlice[1] != "efgh" {
- t.Fatalf("expected array value is ['abcd', 'efgh']. [slice:%v]", aSlice)
- }
-
- err = result.DecodeField("map.nested_map.key3", &subResults)
-
- if err != nil {
- t.Fatalf("cannot decode map.nested_map.key3 field. [e:%v]", err)
- }
-
- if len(subResults) != 2 {
- t.Fatalf("expected sub results len is 2. [len:%v] [results:%v]", subResults)
- }
-
- err = subResults[0].DecodeField("key4", &aString)
-
- if err != nil {
- t.Fatalf("cannot decode key4 field in sub result. [e:%v]", err)
- }
-
- if aString != "mnop" {
- t.Fatalf("expected map.nested_map.key2 value is 'mnop'. [string:%v]", aString)
- }
-
- err = subResults[1].DecodeField("key5", &anInt)
-
- if err != nil {
- t.Fatalf("cannot decode key5 field. [e:%v]", err)
- }
-
- if anInt != 9012 {
- t.Fatalf("expected key5 value is 9012. [int:%v]", anInt)
- }
-
- err = result.DecodeField("message_tags.2.0.id", &aString)
-
- if err != nil {
- t.Fatalf("cannot decode message_tags.2.0.id field. [e:%v]", err)
- }
-
- if aString != "4838901" {
- t.Fatalf("expected message_tags.2.0.id value is '4838901'. [string:%v]", aString)
- }
-
- var messageTags MessageTags
- err = result.DecodeField("message_tags", &messageTags)
-
- if err != nil {
- t.Fatalf("cannot decode message_tags field. [e:%v]", err)
- }
-
- if len(messageTags) != 1 {
- t.Fatalf("expect messageTags have only 1 element. [len:%v]", len(messageTags))
- }
-
- aString = messageTags["2"][1].Id
-
- if aString != "293450302" {
- t.Fatalf("expect messageTags.2.1.id value is '293450302'. [value:%v]", aString)
- }
-
- err = result.DecodeField("nullStruct", &aNull)
-
- if err != nil {
- t.Fatalf("cannot decode nullStruct field. [e:%v]", err)
- }
-
- if aNull.Null != nil {
- t.Fatalf("expect aNull.Null is reset to nil.")
- }
-
- err = result.DecodeField("timestamp", &aTimestamp)
-
- if err != nil {
- t.Fatalf("cannot decode timestamp field. [e:%v]", err)
- }
-
- if !aTimestamp.Equal(time.Date(2015, time.January, 3, 11, 15, 1, 0, time.FixedZone("no-offset", 0))) {
- t.Fatalf("expect aTimestamp date to be 2015-01-03 11:15:01 +0000 [value:%v]", aTimestamp.String())
- }
-
- err = result.DecodeField("custom_timestamp", &aCustomTimestamp)
-
- if err != nil {
- t.Fatalf("cannot decode custom_timestamp field. [e:%v]", err)
- }
-
- if !time.Time(aCustomTimestamp).Equal(time.Date(2014, time.March, 4, 11, 15, 1, 0, time.FixedZone("no-offset", 0))) {
- t.Fatalf("expect aCustomTimestamp date to be 2014-03-04 11:15:01 +0000 [value:%v]", time.Time(aCustomTimestamp).String())
- }
-}
-
-func TestGraphError(t *testing.T) {
- res, err := Get("/me", Params{
- "access_token": "fake",
- })
-
- if err == nil {
- t.Fatalf("facebook should return error for bad access token. [res:%v]", res)
- }
-
- fbErr, ok := err.(*Error)
-
- if !ok {
- t.Fatalf("error must be a *Error. [e:%v]", err)
- }
-
- t.Logf("facebook error. [e:%v] [message:%v] [type:%v] [code:%v] [subcode:%v]", err, fbErr.Message, fbErr.Type, fbErr.Code, fbErr.ErrorSubcode)
-}
-
-type FacebookFriend struct {
- Id string `facebook:",required"`
- Name string `facebook:",required"`
-}
-
-type FacebookFriends struct {
- Friends []FacebookFriend `facebook:"data,required"`
-}
-
-func TestPagingResultDecode(t *testing.T) {
- res := Result{
- "data": []interface{}{
- map[string]interface{}{
- "name": "friend 1",
- "id": "1",
- },
- map[string]interface{}{
- "name": "friend 2",
- "id": "2",
- },
- },
- "paging": map[string]interface{}{
- "next": "https://graph.facebook.com/...",
- },
- }
- paging, err := newPagingResult(nil, res)
- if err != nil {
- t.Fatalf("cannot create paging result. [e:%v]", err)
- }
- var friends FacebookFriends
- if err := paging.Decode(&friends); err != nil {
- t.Fatalf("cannot decode paging result. [e:%v]", err)
- }
- if len(friends.Friends) != 2 {
- t.Fatalf("expect to have 2 friends. [len:%v]", len(friends.Friends))
- }
- if friends.Friends[0].Name != "friend 1" {
- t.Fatalf("expect name to be 'friend 1'. [name:%v]", friends.Friends[0].Name)
- }
- if friends.Friends[0].Id != "1" {
- t.Fatalf("expect id to be '1'. [id:%v]", friends.Friends[0].Id)
- }
- if friends.Friends[1].Name != "friend 2" {
- t.Fatalf("expect name to be 'friend 2'. [name:%v]", friends.Friends[1].Name)
- }
- if friends.Friends[1].Id != "2" {
- t.Fatalf("expect id to be '2'. [id:%v]", friends.Friends[1].Id)
- }
-}
-
-func TestPagingResult(t *testing.T) {
- if FB_TEST_VALID_ACCESS_TOKEN == "" {
- t.Skipf("skip this case as we don't have a valid access token.")
- }
-
- session := &Session{}
- session.SetAccessToken(FB_TEST_VALID_ACCESS_TOKEN)
- res, err := session.Get("/me/home", Params{
- "limit": 2,
- })
-
- if err != nil {
- t.Fatalf("cannot get my home post. [e:%v]", err)
- }
-
- paging, err := res.Paging(session)
-
- if err != nil {
- t.Fatalf("cannot get paging information. [e:%v]", err)
- }
-
- data := paging.Data()
-
- if len(data) != 2 {
- t.Fatalf("expect to have only 2 post. [len:%v]", len(data))
- }
-
- t.Logf("result: %v", res)
- t.Logf("previous: %v", paging.previous)
-
- noMore, err := paging.Previous()
-
- if err != nil {
- t.Fatalf("cannot get paging information. [e:%v]", err)
- }
-
- if !noMore {
- t.Fatalf("should have no more post. %v", *paging.paging.Paging)
- }
-
- noMore, err = paging.Next()
-
- if err != nil {
- t.Fatalf("cannot get paging information. [e:%v]", err)
- }
-
- data = paging.Data()
-
- if len(data) != 2 {
- t.Fatalf("expect to have only 2 post. [len:%v]", len(data))
- }
-
- noMore, err = paging.Next()
-
- if err != nil {
- t.Fatalf("cannot get paging information. [e:%v]", err)
- }
-
- if len(paging.Data()) != 2 {
- t.Fatalf("expect to have only 2 post. [len:%v]", len(paging.Data()))
- }
-}
-
-func TestDecodeLargeInteger(t *testing.T) {
- bigIntegers := []int64{
- 1<<53 - 2,
- 1<<53 - 1,
- 1 << 53,
- 1<<53 + 1,
- 1<<53 + 2,
-
- 1<<54 - 2,
- 1<<54 - 1,
- 1 << 54,
- 1<<54 + 1,
- 1<<54 + 2,
-
- 1<<60 - 2,
- 1<<60 - 1,
- 1 << 60,
- 1<<60 + 1,
- 1<<60 + 2,
-
- 1<<63 - 2,
- 1<<63 - 1,
-
- -(1<<53 - 2),
- -(1<<53 - 1),
- -(1 << 53),
- -(1<<53 + 1),
- -(1<<53 + 2),
-
- -(1<<54 - 2),
- -(1<<54 - 1),
- -(1 << 54),
- -(1<<54 + 1),
- -(1<<54 + 2),
-
- -(1<<60 - 2),
- -(1<<60 - 1),
- -(1 << 60),
- -(1<<60 + 1),
- -(1<<60 + 2),
-
- -(1<<53 - 2),
- -(1<<63 - 1),
- -(1 << 63),
- }
- jsonStr := `{
- "integers": [%v]
- }`
-
- buf := &bytes.Buffer{}
-
- for _, v := range bigIntegers {
- buf.WriteString(fmt.Sprintf("%v", v))
- buf.WriteRune(',')
- }
-
- buf.WriteRune('0')
- json := fmt.Sprintf(jsonStr, buf.String())
-
- res, err := MakeResult([]byte(json))
-
- if err != nil {
- t.Fatalf("cannot make result on test json string. [e:%v]", err)
- }
-
- var actualIntegers []int64
- err = res.DecodeField("integers", &actualIntegers)
-
- if err != nil {
- t.Fatalf("cannot decode integers from json. [e:%v]", err)
- }
-
- if len(actualIntegers) != len(bigIntegers)+1 {
- t.Fatalf("count of decoded integers is not correct. [expected:%v] [actual:%v]", len(bigIntegers)+1, len(actualIntegers))
- }
-
- for k, _ := range bigIntegers {
- if bigIntegers[k] != actualIntegers[k] {
- t.Logf("expected integers: %v", bigIntegers)
- t.Logf("actual integers: %v", actualIntegers)
- t.Fatalf("a decoded integer is not expected. [expected:%v] [actual:%v]", bigIntegers[k], actualIntegers[k])
- }
- }
-}
-
-func TestInspectValidToken(t *testing.T) {
- if FB_TEST_VALID_ACCESS_TOKEN == "" {
- t.Skipf("skip this case as we don't have a valid access token.")
- }
-
- session := testGlobalApp.Session(FB_TEST_VALID_ACCESS_TOKEN)
- result, err := session.Inspect()
-
- if err != nil {
- t.Fatalf("cannot inspect a valid access token. [e:%v]", err)
- }
-
- var isValid bool
- err = result.DecodeField("is_valid", &isValid)
-
- if err != nil {
- t.Fatalf("cannot get 'is_valid' in inspect result. [e:%v]", err)
- }
-
- if !isValid {
- t.Fatalf("inspect result shows access token is invalid. why? [result:%v]", result)
- }
-}
-
-func TestInspectInvalidToken(t *testing.T) {
- invalidToken := "CAACZA38ZAD8CoBAe2bDC6EdThnni3b56scyshKINjZARoC9ZAuEUTgYUkYnKdimqfA2ZAXcd2wLd7Rr8jLmMXTY9vqAhQGqObZBIUz1WwbqVoCsB3AAvLtwoWNhsxM76mK0eiJSLXHZCdPVpyhmtojvzXA7f69Bm6b5WZBBXia8iOpPZAUHTGp1UQLFMt47c7RqJTrYIl3VfAR0deN82GMFL2"
- session := testGlobalApp.Session(invalidToken)
- result, err := session.Inspect()
-
- if err == nil {
- t.Fatalf("facebook should indicate it's an invalid token. why not? [result:%v]", result)
- }
-
- if _, ok := err.(*Error); !ok {
- t.Fatalf("inspect error should be a standard facebook error. why not? [e:%v]", err)
- }
-
- isValid := true
- err = result.DecodeField("is_valid", &isValid)
-
- if err != nil {
- t.Fatalf("cannot get 'is_valid' in inspect result. [e:%v]", err)
- }
-
- if isValid {
- t.Fatalf("inspect result shows access token is valid. why? [result:%v]", result)
- }
-}
-
-func TestCamelCaseToUnderScore(t *testing.T) {
- cases := map[string]string{
- "TestCase": "test_case",
- "HTTPServer": "http_server",
- "NoHTTPS": "no_https",
- "Wi_thF": "wi_th_f",
- "_AnotherTES_TCaseP": "_another_tes_t_case_p",
- "ALL": "all",
- "UserID": "user_id",
- }
-
- for k, v := range cases {
- str := camelCaseToUnderScore(k)
-
- if str != v {
- t.Fatalf("wrong underscore string. [expect:%v] [actual:%v]", v, str)
- }
- }
-}
-
-func TestMakeSliceResult(t *testing.T) {
- jsonStr := `{
- "error": {
- "message": "Invalid OAuth access token.",
- "type": "OAuthException",
- "code": 190
- }
- }`
- var res []Result
- err := makeResult([]byte(jsonStr), &res)
-
- if err == nil {
- t.Fatalf("makeResult must fail")
- }
-
- fbErr, ok := err.(*Error)
-
- if !ok {
- t.Fatalf("error must be a facebook error. [e:%v]", err)
- }
-
- if fbErr.Code != 190 {
- t.Fatalf("invalid facebook error. [e:%v]", fbErr.Error())
- }
-}
-
-func TestMakeSliceResultWithNilElements(t *testing.T) {
- jsonStr := `[
- null,
- {
- "foo": "bar"
- },
- null
- ]`
- var res []Result
- err := makeResult([]byte(jsonStr), &res)
-
- if err != nil {
- t.Fatalf("fail to decode results. [e:%v]", err)
- }
-
- if len(res) != 3 {
- t.Fatalf("expect 3 elements in res. [res:%v]", res)
- }
-
- if res[0] != nil || res[1] == nil || res[2] != nil {
- t.Fatalf("decoded res is not expected. [res:%v]", res)
- }
-
- if res[1]["foo"].(string) != "bar" {
- t.Fatalf("decode res is not expected. [res:%v]", res)
- }
-}
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/misc.go b/Godeps/_workspace/src/github.com/huandu/facebook/misc.go
deleted file mode 100644
index cdf7a9577..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/misc.go
+++ /dev/null
@@ -1,131 +0,0 @@
-// A facebook graph api client in go.
-// https://github.com/huandu/facebook/
-//
-// Copyright 2012 - 2015, Huan Du
-// Licensed under the MIT license
-// https://github.com/huandu/facebook/blob/master/LICENSE
-
-package facebook
-
-import (
- "bytes"
- "io"
- "unicode"
- "unicode/utf8"
-)
-
-func camelCaseToUnderScore(str string) string {
- if len(str) == 0 {
- return ""
- }
-
- buf := &bytes.Buffer{}
- var prev, r0, r1 rune
- var size int
-
- r0 = '_'
-
- for len(str) > 0 {
- prev = r0
- r0, size = utf8.DecodeRuneInString(str)
- str = str[size:]
-
- switch {
- case r0 == utf8.RuneError:
- buf.WriteByte(byte(str[0]))
-
- case unicode.IsUpper(r0):
- if prev != '_' {
- buf.WriteRune('_')
- }
-
- buf.WriteRune(unicode.ToLower(r0))
-
- if len(str) == 0 {
- break
- }
-
- r0, size = utf8.DecodeRuneInString(str)
- str = str[size:]
-
- if !unicode.IsUpper(r0) {
- buf.WriteRune(r0)
- break
- }
-
- // find next non-upper-case character and insert `_` properly.
- // it's designed to convert `HTTPServer` to `http_server`.
- // if there are more than 2 adjacent upper case characters in a word,
- // treat them as an abbreviation plus a normal word.
- for len(str) > 0 {
- r1 = r0
- r0, size = utf8.DecodeRuneInString(str)
- str = str[size:]
-
- if r0 == utf8.RuneError {
- buf.WriteRune(unicode.ToLower(r1))
- buf.WriteByte(byte(str[0]))
- break
- }
-
- if !unicode.IsUpper(r0) {
- if r0 == '_' || r0 == ' ' || r0 == '-' {
- r0 = '_'
-
- buf.WriteRune(unicode.ToLower(r1))
- } else {
- buf.WriteRune('_')
- buf.WriteRune(unicode.ToLower(r1))
- buf.WriteRune(r0)
- }
-
- break
- }
-
- buf.WriteRune(unicode.ToLower(r1))
- }
-
- if len(str) == 0 || r0 == '_' {
- buf.WriteRune(unicode.ToLower(r0))
- break
- }
-
- default:
- if r0 == ' ' || r0 == '-' {
- r0 = '_'
- }
-
- buf.WriteRune(r0)
- }
- }
-
- return buf.String()
-}
-
-// Returns error string.
-func (e *Error) Error() string {
- return e.Message
-}
-
-// Creates a new binary data holder.
-func Data(filename string, source io.Reader) *binaryData {
- return &binaryData{
- Filename: filename,
- Source: source,
- }
-}
-
-// Creates a binary file holder.
-func File(filename, path string) *binaryFile {
- return &binaryFile{
- Filename: filename,
- }
-}
-
-// Creates a binary file holder and specific a different path for reading.
-func FileAlias(filename, path string) *binaryFile {
- return &binaryFile{
- Filename: filename,
- Path: path,
- }
-}
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/paging_result.go b/Godeps/_workspace/src/github.com/huandu/facebook/paging_result.go
deleted file mode 100644
index f1eb9b7f1..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/paging_result.go
+++ /dev/null
@@ -1,146 +0,0 @@
-// A facebook graph api client in go.
-// https://github.com/huandu/facebook/
-//
-// Copyright 2012 - 2015, Huan Du
-// Licensed under the MIT license
-// https://github.com/huandu/facebook/blob/master/LICENSE
-
-package facebook
-
-import (
- "bytes"
- "fmt"
- "net/http"
-)
-
-type pagingData struct {
- Data []Result `facebook:",required"`
- Paging *pagingNavigator
-}
-
-type pagingNavigator struct {
- Previous string
- Next string
-}
-
-func newPagingResult(session *Session, res Result) (*PagingResult, error) {
- // quick check whether Result is a paging response.
- if _, ok := res["data"]; !ok {
- return nil, fmt.Errorf("current Result is not a paging response.")
- }
-
- pr := &PagingResult{
- session: session,
- }
- paging := &pr.paging
- err := res.Decode(paging)
-
- if err != nil {
- return nil, err
- }
-
- if paging.Paging != nil {
- pr.previous = paging.Paging.Previous
- pr.next = paging.Paging.Next
- }
-
- return pr, nil
-}
-
-// Get current data.
-func (pr *PagingResult) Data() []Result {
- return pr.paging.Data
-}
-
-// Decodes the current full result to a struct. See Result#Decode.
-func (pr *PagingResult) Decode(v interface{}) (err error) {
- res := Result{
- "data": pr.Data(),
- }
- return res.Decode(v)
-}
-
-// Read previous page.
-func (pr *PagingResult) Previous() (noMore bool, err error) {
- if !pr.HasPrevious() {
- noMore = true
- return
- }
-
- return pr.navigate(&pr.previous)
-}
-
-// Read next page.
-func (pr *PagingResult) Next() (noMore bool, err error) {
- if !pr.HasNext() {
- noMore = true
- return
- }
-
- return pr.navigate(&pr.next)
-}
-
-// Check whether there is previous page.
-func (pr *PagingResult) HasPrevious() bool {
- return pr.previous != ""
-}
-
-// Check whether there is next page.
-func (pr *PagingResult) HasNext() bool {
- return pr.next != ""
-}
-
-func (pr *PagingResult) navigate(url *string) (noMore bool, err error) {
- var pagingUrl string
-
- // add session information in paging url.
- params := Params{}
- pr.session.prepareParams(params)
-
- if len(params) == 0 {
- pagingUrl = *url
- } else {
- buf := &bytes.Buffer{}
- buf.WriteString(*url)
- buf.WriteRune('&')
- params.Encode(buf)
-
- pagingUrl = buf.String()
- }
-
- var request *http.Request
- var res Result
-
- request, err = http.NewRequest("GET", pagingUrl, nil)
-
- if err != nil {
- return
- }
-
- res, err = pr.session.Request(request)
-
- if err != nil {
- return
- }
-
- if pr.paging.Paging != nil {
- pr.paging.Paging.Next = ""
- pr.paging.Paging.Previous = ""
- }
- paging := &pr.paging
- err = res.Decode(paging)
-
- if err != nil {
- return
- }
-
- if paging.Paging == nil || len(paging.Data) == 0 {
- *url = ""
- noMore = true
- } else {
- pr.previous = paging.Paging.Previous
- pr.next = paging.Paging.Next
- }
-
- return
-}
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/params.go b/Godeps/_workspace/src/github.com/huandu/facebook/params.go
deleted file mode 100644
index bcce18a3a..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/params.go
+++ /dev/null
@@ -1,227 +0,0 @@
-// A facebook graph api client in go.
-// https://github.com/huandu/facebook/
-//
-// Copyright 2012 - 2015, Huan Du
-// Licensed under the MIT license
-// https://github.com/huandu/facebook/blob/master/LICENSE
-
-package facebook
-
-import (
- "encoding/json"
- "io"
- "mime/multipart"
- "net/url"
- "os"
- "reflect"
- "runtime"
-)
-
-// Makes a new Params instance by given data.
-// Data must be a struct or a map with string keys.
-// MakeParams will change all struct field name to lower case name with underscore.
-// e.g. "FooBar" will be changed to "foo_bar".
-//
-// Returns nil if data cannot be used to make a Params instance.
-func MakeParams(data interface{}) (params Params) {
- if p, ok := data.(Params); ok {
- return p
- }
-
- defer func() {
- if r := recover(); r != nil {
- if _, ok := r.(runtime.Error); ok {
- panic(r)
- }
-
- params = nil
- }
- }()
-
- params = makeParams(reflect.ValueOf(data))
- return
-}
-
-func makeParams(value reflect.Value) (params Params) {
- for value.Kind() == reflect.Ptr || value.Kind() == reflect.Interface {
- value = value.Elem()
- }
-
- // only map with string keys can be converted to Params
- if value.Kind() == reflect.Map && value.Type().Key().Kind() == reflect.String {
- params = Params{}
-
- for _, key := range value.MapKeys() {
- params[key.String()] = value.MapIndex(key).Interface()
- }
-
- return
- }
-
- if value.Kind() != reflect.Struct {
- return
- }
-
- params = Params{}
- num := value.NumField()
-
- for i := 0; i < num; i++ {
- name := camelCaseToUnderScore(value.Type().Field(i).Name)
- field := value.Field(i)
-
- for field.Kind() == reflect.Ptr {
- field = field.Elem()
- }
-
- switch field.Kind() {
- case reflect.Chan, reflect.Func, reflect.UnsafePointer, reflect.Invalid:
- // these types won't be marshalled in json.
- params = nil
- return
-
- default:
- params[name] = field.Interface()
- }
- }
-
- return
-}
-
-// Encodes params to query string.
-// If map value is not a string, Encode uses json.Marshal() to convert value to string.
-//
-// Encode will panic if Params contains values that cannot be marshalled to json string.
-func (params Params) Encode(writer io.Writer) (mime string, err error) {
- if params == nil || len(params) == 0 {
- mime = _MIME_FORM_URLENCODED
- return
- }
-
- // check whether params contains any binary data.
- hasBinary := false
-
- for _, v := range params {
- typ := reflect.TypeOf(v)
-
- if typ == typeOfPointerToBinaryData || typ == typeOfPointerToBinaryFile {
- hasBinary = true
- break
- }
- }
-
- if hasBinary {
- return params.encodeMultipartForm(writer)
- }
-
- return params.encodeFormUrlEncoded(writer)
-}
-
-func (params Params) encodeFormUrlEncoded(writer io.Writer) (mime string, err error) {
- var jsonStr []byte
- written := false
-
- for k, v := range params {
- if written {
- io.WriteString(writer, "&")
- }
-
- io.WriteString(writer, url.QueryEscape(k))
- io.WriteString(writer, "=")
-
- if reflect.TypeOf(v).Kind() == reflect.String {
- io.WriteString(writer, url.QueryEscape(reflect.ValueOf(v).String()))
- } else {
- jsonStr, err = json.Marshal(v)
-
- if err != nil {
- return
- }
-
- io.WriteString(writer, url.QueryEscape(string(jsonStr)))
- }
-
- written = true
- }
-
- mime = _MIME_FORM_URLENCODED
- return
-}
-
-func (params Params) encodeMultipartForm(writer io.Writer) (mime string, err error) {
- w := multipart.NewWriter(writer)
- defer func() {
- w.Close()
- mime = w.FormDataContentType()
- }()
-
- for k, v := range params {
- switch value := v.(type) {
- case *binaryData:
- var dst io.Writer
- dst, err = w.CreateFormFile(k, value.Filename)
-
- if err != nil {
- return
- }
-
- _, err = io.Copy(dst, value.Source)
-
- if err != nil {
- return
- }
-
- case *binaryFile:
- var dst io.Writer
- var file *os.File
- var path string
-
- dst, err = w.CreateFormFile(k, value.Filename)
-
- if err != nil {
- return
- }
-
- if value.Path == "" {
- path = value.Filename
- } else {
- path = value.Path
- }
-
- file, err = os.Open(path)
-
- if err != nil {
- return
- }
-
- _, err = io.Copy(dst, file)
-
- if err != nil {
- return
- }
-
- default:
- var dst io.Writer
- var jsonStr []byte
-
- dst, err = w.CreateFormField(k)
-
- if reflect.TypeOf(v).Kind() == reflect.String {
- io.WriteString(dst, reflect.ValueOf(v).String())
- } else {
- jsonStr, err = json.Marshal(v)
-
- if err != nil {
- return
- }
-
- _, err = dst.Write(jsonStr)
-
- if err != nil {
- return
- }
- }
- }
- }
-
- return
-}
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/result.go b/Godeps/_workspace/src/github.com/huandu/facebook/result.go
deleted file mode 100644
index fd760be4e..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/result.go
+++ /dev/null
@@ -1,1097 +0,0 @@
-// A facebook graph api client in go.
-// https://github.com/huandu/facebook/
-//
-// Copyright 2012 - 2015, Huan Du
-// Licensed under the MIT license
-// https://github.com/huandu/facebook/blob/master/LICENSE
-
-package facebook
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "net/http"
- "reflect"
- "runtime"
- "strconv"
- "strings"
- "time"
-)
-
-// MakeResult makes a Result from facebook Graph API response.
-func MakeResult(jsonBytes []byte) (Result, error) {
- res := Result{}
- err := makeResult(jsonBytes, &res)
-
- if err != nil {
- return nil, err
- }
-
- // facebook may return an error
- return res, res.Err()
-}
-
-func makeResult(jsonBytes []byte, res interface{}) error {
- if bytes.Equal(jsonBytes, facebookSuccessJsonBytes) {
- return nil
- }
-
- jsonReader := bytes.NewReader(jsonBytes)
- dec := json.NewDecoder(jsonReader)
-
- // issue #19
- // app_scoped user_id in a post-Facebook graph 2.0 would exceeds 2^53.
- // use Number instead of float64 to avoid precision lost.
- dec.UseNumber()
-
- err := dec.Decode(res)
-
- if err != nil {
- typ := reflect.TypeOf(res)
-
- if typ != nil {
- // if res is a slice, jsonBytes may be a facebook error.
- // try to decode it as Error.
- kind := typ.Kind()
-
- if kind == reflect.Ptr {
- typ = typ.Elem()
- kind = typ.Kind()
- }
-
- if kind == reflect.Array || kind == reflect.Slice {
- var errRes Result
- err = makeResult(jsonBytes, &errRes)
-
- if err != nil {
- return err
- }
-
- err = errRes.Err()
-
- if err == nil {
- err = fmt.Errorf("cannot format facebook response. expect an array but get an object.")
- }
-
- return err
- }
- }
-
- return fmt.Errorf("cannot format facebook response. %v", err)
- }
-
- return nil
-}
-
-// Get gets a field from Result.
-//
-// Field can be a dot separated string.
-// If field name is "a.b.c", it will try to return value of res["a"]["b"]["c"].
-//
-// To access array items, use index value in field.
-// For instance, field "a.0.c" means to read res["a"][0]["c"].
-//
-// It doesn't work with Result which has a key contains dot. Use GetField in this case.
-//
-// Returns nil if field doesn't exist.
-func (res Result) Get(field string) interface{} {
- if field == "" {
- return res
- }
-
- f := strings.Split(field, ".")
- return res.get(f)
-}
-
-// GetField gets a field from Result.
-//
-// Arguments are treated as keys to access value in Result.
-// If arguments are "a","b","c", it will try to return value of res["a"]["b"]["c"].
-//
-// To access array items, use index value as a string.
-// For instance, args of "a", "0", "c" means to read res["a"][0]["c"].
-//
-// Returns nil if field doesn't exist.
-func (res Result) GetField(fields ...string) interface{} {
- if len(fields) == 0 {
- return res
- }
-
- return res.get(fields)
-}
-
-func (res Result) get(fields []string) interface{} {
- v, ok := res[fields[0]]
-
- if !ok || v == nil {
- return nil
- }
-
- if len(fields) == 1 {
- return v
- }
-
- value := getValueField(reflect.ValueOf(v), fields[1:])
-
- if !value.IsValid() {
- return nil
- }
-
- return value.Interface()
-}
-
-func getValueField(value reflect.Value, fields []string) reflect.Value {
- valueType := value.Type()
- kind := valueType.Kind()
- field := fields[0]
-
- switch kind {
- case reflect.Array, reflect.Slice:
- // field must be a number.
- n, err := strconv.ParseUint(field, 10, 0)
-
- if err != nil {
- return reflect.Value{}
- }
-
- if n >= uint64(value.Len()) {
- return reflect.Value{}
- }
-
- // work around a reflect package pitfall.
- value = reflect.ValueOf(value.Index(int(n)).Interface())
-
- case reflect.Map:
- v := value.MapIndex(reflect.ValueOf(field))
-
- if !v.IsValid() {
- return v
- }
-
- // get real value type.
- value = reflect.ValueOf(v.Interface())
-
- default:
- return reflect.Value{}
- }
-
- if len(fields) == 1 {
- return value
- }
-
- return getValueField(value, fields[1:])
-}
-
-// Decode decodes full result to a struct.
-// It only decodes fields defined in the struct.
-//
-// As all facebook response fields are lower case strings,
-// Decode will convert all camel-case field names to lower case string.
-// e.g. field name "FooBar" will be converted to "foo_bar".
-// The side effect is that if a struct has 2 fields with only capital
-// differences, decoder will map these fields to a same result value.
-//
-// If a field is missing in the result, Decode keeps it unchanged by default.
-//
-// Decode can read struct field tag value to change default behavior.
-//
-// Examples:
-//
-// type Foo struct {
-// // "id" must exist in response. note the leading comma.
-// Id string `facebook:",required"`
-//
-// // use "name" as field name in response.
-// TheName string `facebook:"name"`
-// }
-//
-// To change default behavior, set a struct tag `facebook:",required"` to fields
-// should not be missing.
-//
-// Returns error if v is not a struct or any required v field name absents in res.
-func (res Result) Decode(v interface{}) (err error) {
- defer func() {
- if r := recover(); r != nil {
- if _, ok := r.(runtime.Error); ok {
- panic(r)
- }
-
- err = r.(error)
- }
- }()
-
- err = res.decode(reflect.ValueOf(v), "")
- return
-}
-
-// DecodeField decodes a field of result to any type, including struct.
-// Field name format is defined in Result.Get().
-//
-// More details about decoding struct see Result.Decode().
-func (res Result) DecodeField(field string, v interface{}) error {
- f := res.Get(field)
-
- if f == nil {
- return fmt.Errorf("field '%v' doesn't exist in result.", field)
- }
-
- return decodeField(reflect.ValueOf(f), reflect.ValueOf(v), field)
-}
-
-// Err returns an error if Result is a Graph API error.
-//
-// The returned error can be converted to Error by type assertion.
-// err := res.Err()
-// if err != nil {
-// if e, ok := err.(*Error); ok {
-// // read more details in e.Message, e.Code and e.Type
-// }
-// }
-//
-// For more information about Graph API Errors, see
-// https://developers.facebook.com/docs/reference/api/errors/
-func (res Result) Err() error {
- var err Error
- e := res.DecodeField("error", &err)
-
- // no "error" in result. result is not an error.
- if e != nil {
- return nil
- }
-
- // code may be missing in error.
- // assign a non-zero value to it.
- if err.Code == 0 {
- err.Code = ERROR_CODE_UNKNOWN
- }
-
- return &err
-}
-
-// Paging creates a PagingResult for this Result and
-// returns error if the Result cannot be used for paging.
-//
-// Facebook uses following JSON structure to response paging information.
-// If "data" doesn't present in Result, Paging will return error.
-// {
-// "data": [...],
-// "paging": {
-// "previous": "https://graph.facebook.com/...",
-// "next": "https://graph.facebook.com/..."
-// }
-// }
-func (res Result) Paging(session *Session) (*PagingResult, error) {
- return newPagingResult(session, res)
-}
-
-// Batch creates a BatchResult for this result and
-// returns error if the Result is not a batch api response.
-//
-// See BatchApi document for a sample usage.
-func (res Result) Batch() (*BatchResult, error) {
- return newBatchResult(res)
-}
-
-// DebugInfo creates a DebugInfo for this result if this result
-// has "__debug__" key.
-func (res Result) DebugInfo() *DebugInfo {
- var info Result
- err := res.DecodeField(debugInfoKey, &info)
-
- if err != nil {
- return nil
- }
-
- debugInfo := &DebugInfo{}
- info.DecodeField("messages", &debugInfo.Messages)
-
- if proto, ok := info[debugProtoKey]; ok {
- if v, ok := proto.(string); ok {
- debugInfo.Proto = v
- }
- }
-
- if header, ok := info[debugHeaderKey]; ok {
- if v, ok := header.(http.Header); ok {
- debugInfo.Header = v
-
- debugInfo.FacebookApiVersion = v.Get(facebookApiVersionHeader)
- debugInfo.FacebookDebug = v.Get(facebookDebugHeader)
- debugInfo.FacebookRev = v.Get(facebookRevHeader)
- }
- }
-
- return debugInfo
-}
-
-func (res Result) decode(v reflect.Value, fullName string) error {
- for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
- v = v.Elem()
- }
-
- if v.Kind() != reflect.Struct {
- return fmt.Errorf("output value must be a struct.")
- }
-
- if !v.CanSet() {
- return fmt.Errorf("output value cannot be set.")
- }
-
- if fullName != "" {
- fullName += "."
- }
-
- var field reflect.Value
- var name, fbTag string
- var val interface{}
- var ok, required bool
- var err error
-
- vType := v.Type()
- num := vType.NumField()
-
- for i := 0; i < num; i++ {
- name = ""
- required = false
- field = v.Field(i)
- fbTag = vType.Field(i).Tag.Get("facebook")
-
- // parse struct field tag
- if fbTag != "" {
- index := strings.IndexRune(fbTag, ',')
-
- if index == -1 {
- name = fbTag
- } else {
- name = fbTag[:index]
-
- if fbTag[index:] == ",required" {
- required = true
- }
- }
- }
-
- if name == "" {
- name = camelCaseToUnderScore(v.Type().Field(i).Name)
- }
-
- val, ok = res[name]
-
- if !ok {
- // check whether the field is required. if so, report error.
- if required {
- return fmt.Errorf("cannot find field '%v%v' in result.", fullName, name)
- }
-
- continue
- }
-
- if err = decodeField(reflect.ValueOf(val), field, fmt.Sprintf("%v%v", fullName, name)); err != nil {
- return err
- }
- }
-
- return nil
-}
-
-func decodeField(val reflect.Value, field reflect.Value, fullName string) error {
- if field.Kind() == reflect.Ptr {
- // reset Ptr field if val is nil.
- if !val.IsValid() {
- if !field.IsNil() && field.CanSet() {
- field.Set(reflect.Zero(field.Type()))
- }
-
- return nil
- }
-
- if field.IsNil() {
- field.Set(reflect.New(field.Type().Elem()))
- }
-
- field = field.Elem()
- }
-
- if !field.CanSet() {
- return fmt.Errorf("field '%v' cannot be decoded. make sure the output value is able to be set.", fullName)
- }
-
- if !val.IsValid() {
- return fmt.Errorf("field '%v' is not a pointer. cannot assign nil to it.", fullName)
- }
-
- kind := field.Kind()
- valType := val.Type()
-
- switch kind {
- case reflect.Bool:
- if valType.Kind() == reflect.Bool {
- field.SetBool(val.Bool())
- } else {
- return fmt.Errorf("field '%v' is not a bool in result.", fullName)
- }
-
- case reflect.Int8:
- switch valType.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n := val.Int()
-
- if n < -128 || n > 127 {
- return fmt.Errorf("field '%v' value exceeds the range of int8.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- n := val.Uint()
-
- if n > 127 {
- return fmt.Errorf("field '%v' value exceeds the range of int8.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.Float32, reflect.Float64:
- n := val.Float()
-
- if n < -128 || n > 127 {
- return fmt.Errorf("field '%v' value exceeds the range of int8.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.String:
- // only json.Number is allowed to be used as number.
- if val.Type() != typeOfJSONNumber {
- return fmt.Errorf("field '%v' value is string, not a number.", fullName)
- }
-
- n, err := strconv.ParseInt(val.String(), 10, 8)
-
- if err != nil {
- return fmt.Errorf("field '%v' value is not a valid int8.", fullName)
- }
-
- field.SetInt(n)
-
- default:
- return fmt.Errorf("field '%v' is not an integer in result.", fullName)
- }
-
- case reflect.Int16:
- switch valType.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n := val.Int()
-
- if n < -32768 || n > 32767 {
- return fmt.Errorf("field '%v' value exceeds the range of int16.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- n := val.Uint()
-
- if n > 32767 {
- return fmt.Errorf("field '%v' value exceeds the range of int16.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.Float32, reflect.Float64:
- n := val.Float()
-
- if n < -32768 || n > 32767 {
- return fmt.Errorf("field '%v' value exceeds the range of int16.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.String:
- // only json.Number is allowed to be used as number.
- if val.Type() != typeOfJSONNumber {
- return fmt.Errorf("field '%v' value is string, not a number.", fullName)
- }
-
- n, err := strconv.ParseInt(val.String(), 10, 16)
-
- if err != nil {
- return fmt.Errorf("field '%v' value is not a valid int16.", fullName)
- }
-
- field.SetInt(n)
-
- default:
- return fmt.Errorf("field '%v' is not an integer in result.", fullName)
- }
-
- case reflect.Int32:
- switch valType.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n := val.Int()
-
- if n < -2147483648 || n > 2147483647 {
- return fmt.Errorf("field '%v' value exceeds the range of int32.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- n := val.Uint()
-
- if n > 2147483647 {
- return fmt.Errorf("field '%v' value exceeds the range of int32.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.Float32, reflect.Float64:
- n := val.Float()
-
- if n < -2147483648 || n > 2147483647 {
- return fmt.Errorf("field '%v' value exceeds the range of int32.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.String:
- // only json.Number is allowed to be used as number.
- if val.Type() != typeOfJSONNumber {
- return fmt.Errorf("field '%v' value is string, not a number.", fullName)
- }
-
- n, err := strconv.ParseInt(val.String(), 10, 32)
-
- if err != nil {
- return fmt.Errorf("field '%v' value is not a valid int32.", fullName)
- }
-
- field.SetInt(n)
-
- default:
- return fmt.Errorf("field '%v' is not an integer in result.", fullName)
- }
-
- case reflect.Int64:
- switch valType.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n := val.Int()
- field.SetInt(n)
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- n := val.Uint()
-
- if n > 9223372036854775807 {
- return fmt.Errorf("field '%v' value exceeds the range of int64.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.Float32, reflect.Float64:
- n := val.Float()
-
- if n < -9223372036854775808 || n > 9223372036854775807 {
- return fmt.Errorf("field '%v' value exceeds the range of int64.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.String:
- // only json.Number is allowed to be used as number.
- if val.Type() != typeOfJSONNumber {
- return fmt.Errorf("field '%v' value is string, not a number.", fullName)
- }
-
- n, err := strconv.ParseInt(val.String(), 10, 64)
-
- if err != nil {
- return fmt.Errorf("field '%v' value is not a valid int64.", fullName)
- }
-
- field.SetInt(n)
-
- default:
- return fmt.Errorf("field '%v' is not an integer in result.", fullName)
- }
-
- case reflect.Int:
- bits := field.Type().Bits()
-
- var min, max int64
-
- if bits == 32 {
- min = -2147483648
- max = 2147483647
- } else if bits == 64 {
- min = -9223372036854775808
- max = 9223372036854775807
- }
-
- switch valType.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n := val.Int()
-
- if n < min || n > max {
- return fmt.Errorf("field '%v' value exceeds the range of int.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- n := val.Uint()
-
- if n > uint64(max) {
- return fmt.Errorf("field '%v' value exceeds the range of int.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.Float32, reflect.Float64:
- n := val.Float()
-
- if n < float64(min) || n > float64(max) {
- return fmt.Errorf("field '%v' value exceeds the range of int.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.String:
- // only json.Number is allowed to be used as number.
- if val.Type() != typeOfJSONNumber {
- return fmt.Errorf("field '%v' value is string, not a number.", fullName)
- }
-
- n, err := strconv.ParseInt(val.String(), 10, bits)
-
- if err != nil {
- return fmt.Errorf("field '%v' value is not a valid int%v.", fullName, bits)
- }
-
- field.SetInt(n)
-
- default:
- return fmt.Errorf("field '%v' is not an integer in result.", fullName)
- }
-
- case reflect.Uint8:
- switch valType.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n := val.Int()
-
- if n < 0 || n > 0xFF {
- return fmt.Errorf("field '%v' value exceeds the range of uint8.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- n := val.Uint()
-
- if n > 0xFF {
- return fmt.Errorf("field '%v' value exceeds the range of uint8.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.Float32, reflect.Float64:
- n := val.Float()
-
- if n < 0 || n > 0xFF {
- return fmt.Errorf("field '%v' value exceeds the range of uint8.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.String:
- // only json.Number is allowed to be used as number.
- if val.Type() != typeOfJSONNumber {
- return fmt.Errorf("field '%v' value is string, not a number.", fullName)
- }
-
- n, err := strconv.ParseUint(val.String(), 10, 8)
-
- if err != nil {
- return fmt.Errorf("field '%v' value is not a valid uint8.", fullName)
- }
-
- field.SetUint(n)
-
- default:
- return fmt.Errorf("field '%v' is not an integer in result.", fullName)
- }
-
- case reflect.Uint16:
- switch valType.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n := val.Int()
-
- if n < 0 || n > 0xFFFF {
- return fmt.Errorf("field '%v' value exceeds the range of uint16.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- n := val.Uint()
-
- if n > 0xFFFF {
- return fmt.Errorf("field '%v' value exceeds the range of uint16.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.Float32, reflect.Float64:
- n := val.Float()
-
- if n < 0 || n > 0xFFFF {
- return fmt.Errorf("field '%v' value exceeds the range of uint16.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.String:
- // only json.Number is allowed to be used as number.
- if val.Type() != typeOfJSONNumber {
- return fmt.Errorf("field '%v' value is string, not a number.", fullName)
- }
-
- n, err := strconv.ParseUint(val.String(), 10, 16)
-
- if err != nil {
- return fmt.Errorf("field '%v' value is not a valid uint16.", fullName)
- }
-
- field.SetUint(n)
-
- default:
- return fmt.Errorf("field '%v' is not an integer in result.", fullName)
- }
-
- case reflect.Uint32:
- switch valType.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n := val.Int()
-
- if n < 0 || n > 0xFFFFFFFF {
- return fmt.Errorf("field '%v' value exceeds the range of uint32.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- n := val.Uint()
-
- if n > 0xFFFFFFFF {
- return fmt.Errorf("field '%v' value exceeds the range of uint32.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.Float32, reflect.Float64:
- n := val.Float()
-
- if n < 0 || n > 0xFFFFFFFF {
- return fmt.Errorf("field '%v' value exceeds the range of uint32.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.String:
- // only json.Number is allowed to be used as number.
- if val.Type() != typeOfJSONNumber {
- return fmt.Errorf("field '%v' value is string, not a number.", fullName)
- }
-
- n, err := strconv.ParseUint(val.String(), 10, 32)
-
- if err != nil {
- return fmt.Errorf("field '%v' value is not a valid uint32.", fullName)
- }
-
- field.SetUint(n)
-
- default:
- return fmt.Errorf("field '%v' is not an integer in result.", fullName)
- }
-
- case reflect.Uint64:
- switch valType.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n := val.Int()
-
- if n < 0 {
- return fmt.Errorf("field '%v' value exceeds the range of uint64.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- n := val.Uint()
- field.SetUint(n)
-
- case reflect.Float32, reflect.Float64:
- n := val.Float()
-
- if n < 0 || n > 0xFFFFFFFFFFFFFFFF {
- return fmt.Errorf("field '%v' value exceeds the range of uint64.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.String:
- // only json.Number is allowed to be used as number.
- if val.Type() != typeOfJSONNumber {
- return fmt.Errorf("field '%v' value is string, not a number.", fullName)
- }
-
- n, err := strconv.ParseUint(val.String(), 10, 64)
-
- if err != nil {
- return fmt.Errorf("field '%v' value is not a valid uint64.", fullName)
- }
-
- field.SetUint(n)
-
- default:
- return fmt.Errorf("field '%v' is not an integer in result.", fullName)
- }
-
- case reflect.Uint:
- bits := field.Type().Bits()
-
- var max uint64
-
- if bits == 32 {
- max = 0xFFFFFFFF
- } else if bits == 64 {
- max = 0xFFFFFFFFFFFFFFFF
- }
-
- switch valType.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n := val.Int()
-
- if n < 0 || uint64(n) > max {
- return fmt.Errorf("field '%v' value exceeds the range of uint.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- n := val.Uint()
-
- if n > max {
- return fmt.Errorf("field '%v' value exceeds the range of uint.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.Float32, reflect.Float64:
- n := val.Float()
-
- if n < 0 || n > float64(max) {
- return fmt.Errorf("field '%v' value exceeds the range of uint.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.String:
- // only json.Number is allowed to be used as number.
- if val.Type() != typeOfJSONNumber {
- return fmt.Errorf("field '%v' value is string, not a number.", fullName)
- }
-
- n, err := strconv.ParseUint(val.String(), 10, bits)
-
- if err != nil {
- return fmt.Errorf("field '%v' value is not a valid uint%v.", fullName, bits)
- }
-
- field.SetUint(n)
-
- default:
- return fmt.Errorf("field '%v' is not an integer in result.", fullName)
- }
-
- case reflect.Float32, reflect.Float64:
- switch valType.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n := val.Int()
- field.SetFloat(float64(n))
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- n := val.Uint()
- field.SetFloat(float64(n))
-
- case reflect.Float32, reflect.Float64:
- n := val.Float()
- field.SetFloat(n)
-
- case reflect.String:
- // only json.Number is allowed to be used as number.
- if val.Type() != typeOfJSONNumber {
- return fmt.Errorf("field '%v' value is string, not a number.", fullName)
- }
-
- n, err := strconv.ParseFloat(val.String(), 64)
-
- if err != nil {
- return fmt.Errorf("field '%v' is not a valid float64.", fullName)
- }
-
- field.SetFloat(n)
-
- default:
- return fmt.Errorf("field '%v' is not a float in result.", fullName)
- }
-
- case reflect.String:
- if valType.Kind() != reflect.String {
- return fmt.Errorf("field '%v' is not a string in result.", fullName)
- }
-
- field.SetString(val.String())
-
- case reflect.Struct:
- if field.Type().ConvertibleTo(typeOfTime) {
- if valType.Kind() != reflect.String {
- return fmt.Errorf("field '%v' is not a string in result.", fullName)
- }
-
- t, err := time.Parse("2006-01-02T15:04:05-0700", val.String())
-
- if err != nil {
- return fmt.Errorf("field '%v' was unable to parse the time string '%s'.", fullName, val.String())
- }
-
- matchedType := reflect.ValueOf(t).Convert(field.Type())
- field.Set(matchedType)
- return nil
- }
-
- if valType.Kind() != reflect.Map || valType.Key().Kind() != reflect.String {
- return fmt.Errorf("field '%v' is not a json object in result.", fullName)
- }
-
- // safe convert val to Result. type assertion doesn't work in this case.
- var r Result
- reflect.ValueOf(&r).Elem().Set(val)
-
- if err := r.decode(field, fullName); err != nil {
- return err
- }
-
- case reflect.Map:
- if valType.Kind() != reflect.Map || valType.Key().Kind() != reflect.String {
- return fmt.Errorf("field '%v' is not a json object in result.", fullName)
- }
-
- // map key must be string
- if field.Type().Key().Kind() != reflect.String {
- return fmt.Errorf("field '%v' in struct is a map with non-string key type. it's not allowed.", fullName)
- }
-
- var needAddr bool
- valueType := field.Type().Elem()
-
- // shortcut for map[string]interface{}.
- if valueType.Kind() == reflect.Interface {
- field.Set(val)
- break
- }
-
- if field.IsNil() {
- field.Set(reflect.MakeMap(field.Type()))
- }
-
- if valueType.Kind() == reflect.Ptr {
- valueType = valueType.Elem()
- needAddr = true
- }
-
- for _, key := range val.MapKeys() {
- // val.MapIndex(key) returns a Value with wrong type.
- // use following trick to get correct Value.
- value := reflect.ValueOf(val.MapIndex(key).Interface())
- newValue := reflect.New(valueType)
-
- if err := decodeField(value, newValue, fmt.Sprintf("%v.%v", fullName, key)); err != nil {
- return err
- }
-
- if needAddr {
- field.SetMapIndex(key, newValue)
- } else {
- field.SetMapIndex(key, newValue.Elem())
- }
- }
-
- case reflect.Slice, reflect.Array:
- if valType.Kind() != reflect.Slice && valType.Kind() != reflect.Array {
- return fmt.Errorf("field '%v' is not a json array in result.", fullName)
- }
-
- valLen := val.Len()
-
- if kind == reflect.Array {
- if field.Len() < valLen {
- return fmt.Errorf("cannot copy all field '%v' values to struct. expected len is %v. actual len is %v.",
- fullName, field.Len(), valLen)
- }
- }
-
- var slc reflect.Value
- var needAddr bool
-
- valueType := field.Type().Elem()
-
- // shortcut for array of interface
- if valueType.Kind() == reflect.Interface {
- if kind == reflect.Array {
- for i := 0; i < valLen; i++ {
- field.Index(i).Set(val.Index(i))
- }
- } else { // kind is slice
- field.Set(val)
- }
-
- break
- }
-
- if kind == reflect.Array {
- slc = field.Slice(0, valLen)
- } else {
- // kind is slice
- slc = reflect.MakeSlice(field.Type(), valLen, valLen)
- field.Set(slc)
- }
-
- if valueType.Kind() == reflect.Ptr {
- needAddr = true
- valueType = valueType.Elem()
- }
-
- for i := 0; i < valLen; i++ {
- // val.Index(i) returns a Value with wrong type.
- // use following trick to get correct Value.
- valIndexValue := reflect.ValueOf(val.Index(i).Interface())
- newValue := reflect.New(valueType)
-
- if err := decodeField(valIndexValue, newValue, fmt.Sprintf("%v.%v", fullName, i)); err != nil {
- return err
- }
-
- if needAddr {
- slc.Index(i).Set(newValue)
- } else {
- slc.Index(i).Set(newValue.Elem())
- }
- }
-
- default:
- return fmt.Errorf("field '%v' in struct uses unsupported type '%v'.", fullName, kind)
- }
-
- return nil
-}
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/session.go b/Godeps/_workspace/src/github.com/huandu/facebook/session.go
deleted file mode 100644
index 95b4ad8d2..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/session.go
+++ /dev/null
@@ -1,667 +0,0 @@
-// A facebook graph api client in go.
-// https://github.com/huandu/facebook/
-//
-// Copyright 2012 - 2015, Huan Du
-// Licensed under the MIT license
-// https://github.com/huandu/facebook/blob/master/LICENSE
-
-package facebook
-
-import (
- "bytes"
- "crypto/hmac"
- "crypto/sha256"
- "encoding/base64"
- "encoding/hex"
- "fmt"
- "io"
- "net/http"
- "net/url"
- "strings"
-)
-
-// Makes a facebook graph api call.
-//
-// If session access token is set, "access_token" in params will be set to the token value.
-//
-// Returns facebook graph api call result.
-// If facebook returns error in response, returns error details in res and set err.
-func (session *Session) Api(path string, method Method, params Params) (Result, error) {
- return session.graph(path, method, params)
-}
-
-// Get is a short hand of Api(path, GET, params).
-func (session *Session) Get(path string, params Params) (Result, error) {
- return session.Api(path, GET, params)
-}
-
-// Post is a short hand of Api(path, POST, params).
-func (session *Session) Post(path string, params Params) (Result, error) {
- return session.Api(path, POST, params)
-}
-
-// Delete is a short hand of Api(path, DELETE, params).
-func (session *Session) Delete(path string, params Params) (Result, error) {
- return session.Api(path, DELETE, params)
-}
-
-// Put is a short hand of Api(path, PUT, params).
-func (session *Session) Put(path string, params Params) (Result, error) {
- return session.Api(path, PUT, params)
-}
-
-// Makes a batch call. Each params represent a single facebook graph api call.
-//
-// BatchApi supports most kinds of batch calls defines in facebook batch api document,
-// except uploading binary data. Use Batch to upload binary data.
-//
-// If session access token is set, the token will be used in batch api call.
-//
-// Returns an array of batch call result on success.
-//
-// Facebook document: https://developers.facebook.com/docs/graph-api/making-multiple-requests
-func (session *Session) BatchApi(params ...Params) ([]Result, error) {
- return session.Batch(nil, params...)
-}
-
-// Makes a batch facebook graph api call.
-// Batch is designed for more advanced usage including uploading binary files.
-//
-// If session access token is set, "access_token" in batchParams will be set to the token value.
-//
-// Facebook document: https://developers.facebook.com/docs/graph-api/making-multiple-requests
-func (session *Session) Batch(batchParams Params, params ...Params) ([]Result, error) {
- return session.graphBatch(batchParams, params...)
-}
-
-// Makes a FQL query.
-// Returns a slice of Result. If there is no query result, the result is nil.
-//
-// Facebook document: https://developers.facebook.com/docs/technical-guides/fql#query
-func (session *Session) FQL(query string) ([]Result, error) {
- res, err := session.graphFQL(Params{
- "q": query,
- })
-
- if err != nil {
- return nil, err
- }
-
- // query result is stored in "data" field.
- var data []Result
- err = res.DecodeField("data", &data)
-
- if err != nil {
- return nil, err
- }
-
- return data, nil
-}
-
-// Makes a multi FQL query.
-// Returns a parsed Result. The key is the multi query key, and the value is the query result.
-//
-// Here is a multi-query sample.
-//
-// res, _ := session.MultiFQL(Params{
-// "query1": "SELECT name FROM user WHERE uid = me()",
-// "query2": "SELECT uid1, uid2 FROM friend WHERE uid1 = me()",
-// })
-//
-// // Get query results from response.
-// var query1, query2 []Result
-// res.DecodeField("query1", &query1)
-// res.DecodeField("query2", &query2)
-//
-// Facebook document: https://developers.facebook.com/docs/technical-guides/fql#multi
-func (session *Session) MultiFQL(queries Params) (Result, error) {
- res, err := session.graphFQL(Params{
- "q": queries,
- })
-
- if err != nil {
- return res, err
- }
-
- // query result is stored in "data" field.
- var data []Result
- err = res.DecodeField("data", &data)
-
- if err != nil {
- return nil, err
- }
-
- if data == nil {
- return nil, fmt.Errorf("multi-fql result is not found.")
- }
-
- // Multi-fql data structure is:
- // {
- // "data": [
- // {
- // "name": "query1",
- // "fql_result_set": [
- // {...}, {...}, ...
- // ]
- // },
- // {
- // "name": "query2",
- // "fql_result_set": [
- // {...}, {...}, ...
- // ]
- // },
- // ...
- // ]
- // }
- //
- // Parse the structure to following go map.
- // {
- // "query1": [
- // // Come from field "fql_result_set".
- // {...}, {...}, ...
- // ],
- // "query2": [
- // {...}, {...}, ...
- // ],
- // ...
- // }
- var name string
- var apiResponse interface{}
- var ok bool
- result := Result{}
-
- for k, v := range data {
- err = v.DecodeField("name", &name)
-
- if err != nil {
- return nil, fmt.Errorf("missing required field 'name' in multi-query data.%v. %v", k, err)
- }
-
- apiResponse, ok = v["fql_result_set"]
-
- if !ok {
- return nil, fmt.Errorf("missing required field 'fql_result_set' in multi-query data.%v.", k)
- }
-
- result[name] = apiResponse
- }
-
- return result, nil
-}
-
-// Makes an arbitrary HTTP request.
-// It expects server responses a facebook Graph API response.
-// request, _ := http.NewRequest("https://graph.facebook.com/538744468", "GET", nil)
-// res, err := session.Request(request)
-// fmt.Println(res["gender"]) // get "male"
-func (session *Session) Request(request *http.Request) (res Result, err error) {
- var response *http.Response
- var data []byte
-
- response, data, err = session.sendRequest(request)
-
- if err != nil {
- return
- }
-
- res, err = MakeResult(data)
- session.addDebugInfo(res, response)
-
- if res != nil {
- err = res.Err()
- }
-
- return
-}
-
-// Gets current user id from access token.
-//
-// Returns error if access token is not set or invalid.
-//
-// It's a standard way to validate a facebook access token.
-func (session *Session) User() (id string, err error) {
- if session.id != "" {
- id = session.id
- return
- }
-
- if session.accessToken == "" {
- err = fmt.Errorf("access token is not set.")
- return
- }
-
- var result Result
- result, err = session.Api("/me", GET, Params{"fields": "id"})
-
- if err != nil {
- return
- }
-
- err = result.DecodeField("id", &id)
-
- if err != nil {
- return
- }
-
- return
-}
-
-// Validates Session access token.
-// Returns nil if access token is valid.
-func (session *Session) Validate() (err error) {
- if session.accessToken == "" {
- err = fmt.Errorf("access token is not set.")
- return
- }
-
- var result Result
- result, err = session.Api("/me", GET, Params{"fields": "id"})
-
- if err != nil {
- return
- }
-
- if f := result.Get("id"); f == nil {
- err = fmt.Errorf("invalid access token.")
- return
- }
-
- return
-}
-
-// Inspect Session access token.
-// Returns JSON array containing data about the inspected token.
-// See https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.2#checktoken
-func (session *Session) Inspect() (result Result, err error) {
- if session.accessToken == "" {
- err = fmt.Errorf("access token is not set.")
- return
- }
-
- if session.app == nil {
- err = fmt.Errorf("cannot inspect access token without binding an app.")
- return
- }
-
- appAccessToken := session.app.AppAccessToken()
-
- if appAccessToken == "" {
- err = fmt.Errorf("app access token is not set.")
- return
- }
-
- result, err = session.Api("/debug_token", GET, Params{
- "input_token": session.accessToken,
- "access_token": appAccessToken,
- })
-
- if err != nil {
- return
- }
-
- // facebook stores everything, including error, inside result["data"].
- // make sure that result["data"] exists and doesn't contain error.
- if _, ok := result["data"]; !ok {
- err = fmt.Errorf("facebook inspect api returns unexpected result.")
- return
- }
-
- var data Result
- result.DecodeField("data", &data)
- result = data
- err = result.Err()
- return
-}
-
-// Gets current access token.
-func (session *Session) AccessToken() string {
- return session.accessToken
-}
-
-// Sets a new access token.
-func (session *Session) SetAccessToken(token string) {
- if token != session.accessToken {
- session.id = ""
- session.accessToken = token
- session.appsecretProof = ""
- }
-}
-
-// Check appsecret proof is enabled or not.
-func (session *Session) AppsecretProof() string {
- if !session.enableAppsecretProof {
- return ""
- }
-
- if session.accessToken == "" || session.app == nil {
- return ""
- }
-
- if session.appsecretProof == "" {
- hash := hmac.New(sha256.New, []byte(session.app.AppSecret))
- hash.Write([]byte(session.accessToken))
- session.appsecretProof = hex.EncodeToString(hash.Sum(nil))
- }
-
- return session.appsecretProof
-}
-
-// Enable or disable appsecret proof status.
-// Returns error if there is no App associasted with this Session.
-func (session *Session) EnableAppsecretProof(enabled bool) error {
- if session.app == nil {
- return fmt.Errorf("cannot change appsecret proof status without an associated App.")
- }
-
- if session.enableAppsecretProof != enabled {
- session.enableAppsecretProof = enabled
-
- // reset pre-calculated proof here to give caller a way to do so in some rare case,
- // e.g. associated app's secret is changed.
- session.appsecretProof = ""
- }
-
- return nil
-}
-
-// Gets associated App.
-func (session *Session) App() *App {
- return session.app
-}
-
-// Debug returns current debug mode.
-func (session *Session) Debug() DebugMode {
- if session.debug != DEBUG_OFF {
- return session.debug
- }
-
- return Debug
-}
-
-// SetDebug updates per session debug mode and returns old mode.
-// If per session debug mode is DEBUG_OFF, session will use global
-// Debug mode.
-func (session *Session) SetDebug(debug DebugMode) DebugMode {
- old := session.debug
- session.debug = debug
- return old
-}
-
-func (session *Session) graph(path string, method Method, params Params) (res Result, err error) {
- var graphUrl string
-
- if params == nil {
- params = Params{}
- }
-
- // always format as json.
- params["format"] = "json"
-
- // overwrite method as we always use post
- params["method"] = method
-
- // get graph api url.
- if session.isVideoPost(path, method) {
- graphUrl = session.getUrl("graph_video", path, nil)
- } else {
- graphUrl = session.getUrl("graph", path, nil)
- }
-
- var response *http.Response
- response, err = session.sendPostRequest(graphUrl, params, &res)
- session.addDebugInfo(res, response)
-
- if res != nil {
- err = res.Err()
- }
-
- return
-}
-
-func (session *Session) graphBatch(batchParams Params, params ...Params) ([]Result, error) {
- if batchParams == nil {
- batchParams = Params{}
- }
-
- batchParams["batch"] = params
-
- var res []Result
- graphUrl := session.getUrl("graph", "", nil)
- _, err := session.sendPostRequest(graphUrl, batchParams, &res)
- return res, err
-}
-
-func (session *Session) graphFQL(params Params) (res Result, err error) {
- if params == nil {
- params = Params{}
- }
-
- session.prepareParams(params)
-
- // encode url.
- buf := &bytes.Buffer{}
- buf.WriteString(domainMap["graph"])
- buf.WriteString("fql?")
- _, err = params.Encode(buf)
-
- if err != nil {
- return nil, fmt.Errorf("cannot encode params. %v", err)
- }
-
- // it seems facebook disallow POST to /fql. always use GET for FQL.
- var response *http.Response
- response, err = session.sendGetRequest(buf.String(), &res)
- session.addDebugInfo(res, response)
-
- if res != nil {
- err = res.Err()
- }
-
- return
-}
-
-func (session *Session) prepareParams(params Params) {
- if _, ok := params["access_token"]; !ok && session.accessToken != "" {
- params["access_token"] = session.accessToken
- }
-
- if session.enableAppsecretProof && session.accessToken != "" && session.app != nil {
- params["appsecret_proof"] = session.AppsecretProof()
- }
-
- debug := session.Debug()
-
- if debug != DEBUG_OFF {
- params["debug"] = debug
- }
-}
-
-func (session *Session) sendGetRequest(uri string, res interface{}) (*http.Response, error) {
- request, err := http.NewRequest("GET", uri, nil)
-
- if err != nil {
- return nil, err
- }
-
- response, data, err := session.sendRequest(request)
-
- if err != nil {
- return response, err
- }
-
- err = makeResult(data, res)
- return response, err
-}
-
-func (session *Session) sendPostRequest(uri string, params Params, res interface{}) (*http.Response, error) {
- session.prepareParams(params)
-
- buf := &bytes.Buffer{}
- mime, err := params.Encode(buf)
-
- if err != nil {
- return nil, fmt.Errorf("cannot encode POST params. %v", err)
- }
-
- var request *http.Request
-
- request, err = http.NewRequest("POST", uri, buf)
-
- if err != nil {
- return nil, err
- }
-
- request.Header.Set("Content-Type", mime)
- response, data, err := session.sendRequest(request)
-
- if err != nil {
- return response, err
- }
-
- err = makeResult(data, res)
- return response, err
-}
-
-func (session *Session) sendOauthRequest(uri string, params Params) (Result, error) {
- urlStr := session.getUrl("graph", uri, nil)
- buf := &bytes.Buffer{}
- mime, err := params.Encode(buf)
-
- if err != nil {
- return nil, fmt.Errorf("cannot encode POST params. %v", err)
- }
-
- var request *http.Request
-
- request, err = http.NewRequest("POST", urlStr, buf)
-
- if err != nil {
- return nil, err
- }
-
- request.Header.Set("Content-Type", mime)
- _, data, err := session.sendRequest(request)
-
- if err != nil {
- return nil, err
- }
-
- if len(data) == 0 {
- return nil, fmt.Errorf("empty response from facebook")
- }
-
- // facebook may return a query string.
- if 'a' <= data[0] && data[0] <= 'z' {
- query, err := url.ParseQuery(string(data))
-
- if err != nil {
- return nil, err
- }
-
- // convert a query to Result.
- res := Result{}
-
- for k := range query {
- res[k] = query.Get(k)
- }
-
- return res, nil
- }
-
- res, err := MakeResult(data)
- return res, err
-}
-
-func (session *Session) sendRequest(request *http.Request) (response *http.Response, data []byte, err error) {
- if session.HttpClient == nil {
- response, err = http.DefaultClient.Do(request)
- } else {
- response, err = session.HttpClient.Do(request)
- }
-
- if err != nil {
- err = fmt.Errorf("cannot reach facebook server. %v", err)
- return
- }
-
- buf := &bytes.Buffer{}
- _, err = io.Copy(buf, response.Body)
- response.Body.Close()
-
- if err != nil {
- err = fmt.Errorf("cannot read facebook response. %v", err)
- }
-
- data = buf.Bytes()
- return
-}
-
-func (session *Session) isVideoPost(path string, method Method) bool {
- return method == POST && regexpIsVideoPost.MatchString(path)
-}
-
-func (session *Session) getUrl(name, path string, params Params) string {
- offset := 0
-
- if path != "" && path[0] == '/' {
- offset = 1
- }
-
- buf := &bytes.Buffer{}
- buf.WriteString(domainMap[name])
-
- // facebook versioning.
- if session.Version == "" {
- if Version != "" {
- buf.WriteString(Version)
- buf.WriteRune('/')
- }
- } else {
- buf.WriteString(session.Version)
- buf.WriteRune('/')
- }
-
- buf.WriteString(string(path[offset:]))
-
- if params != nil {
- buf.WriteRune('?')
- params.Encode(buf)
- }
-
- return buf.String()
-}
-
-func (session *Session) addDebugInfo(res Result, response *http.Response) Result {
- if session.Debug() == DEBUG_OFF || res == nil || response == nil {
- return res
- }
-
- debugInfo := make(map[string]interface{})
-
- // save debug information in result directly.
- res.DecodeField("__debug__", &debugInfo)
- debugInfo[debugProtoKey] = response.Proto
- debugInfo[debugHeaderKey] = response.Header
-
- res["__debug__"] = debugInfo
- return res
-}
-
-func decodeBase64URLEncodingString(data string) ([]byte, error) {
- buf := bytes.NewBufferString(data)
-
- // go's URLEncoding implementation requires base64 padding.
- if m := len(data) % 4; m != 0 {
- buf.WriteString(strings.Repeat("=", 4-m))
- }
-
- reader := base64.NewDecoder(base64.URLEncoding, buf)
- output := &bytes.Buffer{}
- _, err := io.Copy(output, reader)
-
- if err != nil {
- return nil, err
- }
-
- return output.Bytes(), nil
-}
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/type.go b/Godeps/_workspace/src/github.com/huandu/facebook/type.go
deleted file mode 100644
index d09865415..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/type.go
+++ /dev/null
@@ -1,127 +0,0 @@
-// A facebook graph api client in go.
-// https://github.com/huandu/facebook/
-//
-// Copyright 2012 - 2015, Huan Du
-// Licensed under the MIT license
-// https://github.com/huandu/facebook/blob/master/LICENSE
-
-package facebook
-
-import (
- "io"
- "net/http"
-)
-
-// Holds facebook application information.
-type App struct {
- // Facebook app id
- AppId string
-
- // Facebook app secret
- AppSecret string
-
- // Facebook app redirect URI in the app's configuration.
- RedirectUri string
-
- // Enable appsecret proof in every API call to facebook.
- // Facebook document: https://developers.facebook.com/docs/graph-api/securing-requests
- EnableAppsecretProof bool
-}
-
-// An interface to send http request.
-// This interface is designed to be compatible with type `*http.Client`.
-type HttpClient interface {
- Do(req *http.Request) (resp *http.Response, err error)
- Get(url string) (resp *http.Response, err error)
- Post(url string, bodyType string, body io.Reader) (resp *http.Response, err error)
-}
-
-// Holds a facebook session with an access token.
-// Session should be created by App.Session or App.SessionFromSignedRequest.
-type Session struct {
- HttpClient HttpClient
- Version string // facebook versioning.
-
- accessToken string // facebook access token. can be empty.
- app *App
- id string
-
- enableAppsecretProof bool // add "appsecret_proof" parameter in every facebook API call.
- appsecretProof string // pre-calculated "appsecret_proof" value.
-
- debug DebugMode // using facebook debugging api in every request.
-}
-
-// API HTTP method.
-// Can be GET, POST or DELETE.
-type Method string
-
-// Graph API debug mode.
-// See https://developers.facebook.com/docs/graph-api/using-graph-api/v2.3#graphapidebugmode
-type DebugMode string
-
-// API params.
-//
-// For general uses, just use Params as a ordinary map.
-//
-// For advanced uses, use MakeParams to create Params from any struct.
-type Params map[string]interface{}
-
-// Facebook API call result.
-type Result map[string]interface{}
-
-// Represents facebook API call result with paging information.
-type PagingResult struct {
- session *Session
- paging pagingData
- previous string
- next string
-}
-
-// Represents facebook batch API call result.
-// See https://developers.facebook.com/docs/graph-api/making-multiple-requests/#multiple_methods.
-type BatchResult struct {
- StatusCode int // HTTP status code.
- Header http.Header // HTTP response headers.
- Body string // Raw HTTP response body string.
- Result Result // Facebook api result parsed from body.
-}
-
-// Facebook API error.
-type Error struct {
- Message string
- Type string
- Code int
- ErrorSubcode int // subcode for authentication related errors.
-}
-
-// Binary data.
-type binaryData struct {
- Filename string // filename used in multipart form writer.
- Source io.Reader // file data source.
-}
-
-// Binary file.
-type binaryFile struct {
- Filename string // filename used in multipart form writer.
- Path string // path to file. must be readable.
-}
-
-// DebugInfo is the debug information returned by facebook when debug mode is enabled.
-type DebugInfo struct {
- Messages []DebugMessage // debug messages. it can be nil if there is no message.
- Header http.Header // all HTTP headers for this response.
- Proto string // HTTP protocol name for this response.
-
- // Facebook debug HTTP headers.
- FacebookApiVersion string // the actual graph API version provided by facebook-api-version HTTP header.
- FacebookDebug string // the X-FB-Debug HTTP header.
- FacebookRev string // the x-fb-rev HTTP header.
-}
-
-// DebugMessage is one debug message in "__debug__" of graph API response.
-type DebugMessage struct {
- Type string
- Message string
- Link string
-}