Giter VIP home page Giter VIP logo

facebook's Introduction

A Facebook Graph API SDK In Golang

Build Status

This is a Go package 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.

See full document for API details.

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 response it.

Usage

Quick Tutorial

Here is a sample to read my Facebook username by uid.

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 map[string]interface{}. It may not be easy and safe to read fields in res directly. This package provides serveral helpful methods which can decode res to any Go type including a custom Go struct.

// 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

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

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.

// 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.

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...

{
    "foo_bar": "player"
}

One can use following struct.

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.

// 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

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

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

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.

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 to understand facebook versioning strategy.

// 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 to know more about it.

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 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.

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.

TODO

  1. Real-time update subscriptions.

Get It

Use go get github.com/huandu/facebook to get and install it.

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.

facebook's People

Contributors

huandu avatar jpibarra1130 avatar kjk avatar nrolans avatar dinedal avatar lazyshot avatar jkozera avatar maxekman avatar mehdime avatar rogerso avatar yhbyun avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.