예제 #1
0
// 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
}
예제 #2
0
// 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
}