// Gets basic info about an account on Facebook func FacebookGetUserInfo(id string, params FacebookParams) FacebookAccount { var account FacebookAccount if id != "" { var buffer bytes.Buffer buffer.WriteString(fbGraphApiBaseUrl) buffer.WriteString(id) buffer.WriteString("?") // convert struct to querystring params (for now, only pass the access_token, the other stuff doesn't matter for our use here) userInfoParams := FacebookParams{AccessToken: params.AccessToken} v, err := query.Values(userInfoParams) if err != nil { return account } buffer.WriteString(v.Encode()) userInfoUrl := buffer.String() buffer.Reset() // set up the request req, err := http.NewRequest("GET", userInfoUrl, nil) if err != nil { return account } // doo it resp, err := fbHttpClient.Do(req) if err != nil { return account } defer resp.Body.Close() dec := json.NewDecoder(resp.Body) dec.Decode(&account) // close the response now, we don't need it anymore - it should close right after this anyway because of the defer... but these calls are atomic. so just to be safe. // i've had too much trouble with unclosed http requests. i'm happy to be paranoid and safe rather than sorry, because i've been sorry and sore before. resp.Body.Close() } return account }
// Gets the public posts for a given user or page id (or name actually) func FacebookFeed(territoryName string, harvestState config.HarvestState, account string, params FacebookParams) (FacebookParams, config.HarvestState) { // XBox page feed for example... // https://graph.facebook.com/xbox // 16547831022 // Look for access_token override, if not present, use default fbToken from config if params.AccessToken == "" { params.AccessToken = fbToken } // If that happens to be empty, just return. if params.AccessToken == "" { return params, harvestState } var buffer bytes.Buffer buffer.WriteString(fbGraphApiBaseUrl) buffer.WriteString(account) buffer.WriteString("/feed?") // convert struct to querystring params v, err := query.Values(params) if err != nil { return params, harvestState } buffer.WriteString(v.Encode()) feedUrl := buffer.String() buffer.Reset() // set up the request req, err := http.NewRequest("GET", feedUrl, nil) if err != nil { return params, harvestState } // doo it resp, err := fbHttpClient.Do(req) if err != nil { return params, harvestState } defer resp.Body.Close() // now to parse response, store and contine along. data := struct { Posts []FacebookPost `json:"data"` Paging struct { Previous string `json:"previous"` Next string `json:"next"` } `json:"paging"` }{} dec := json.NewDecoder(resp.Body) dec.Decode(&data) //log.Println(data) // close the response now, we don't need it anymore - otherwise it'll stay open while we write to the database. best to close it. resp.Body.Close() // parse the querystring of "next" so we can get the "until" value for params if data.Paging.Next != "" { u, err := url.Parse(data.Paging.Next) if err == nil { m, _ := url.ParseQuery(u.RawQuery) if _, ok := m["until"]; ok { params.Until = m["until"][0] } else { // By setting this empty, we'll know not to loop again. This is up to date and should be the last request for this harvest. params.Until = "" } } else { // log.Println(err) } } // Only attempt to store if we have some results. if len(data.Posts) > 0 { // Save, then return updated params and harvest state for next round (if there is another one) harvestState.ItemsHarvested, harvestState.LastId, harvestState.LastTime = FacebookPostsOut(data.Posts, territoryName, params) } return params, harvestState }