Rails - Upload picture to Facebook using URL - ruby-on-rails

I'm using Koala for Facebook API and Paperclip for Amazon S3.
I already finished the code for S3 Upload, but having problem for Facebook's upload.
Here's my simplified code:
#user = User.find(params[:id])
#graph = Koala::Facebook::API.new(session[:access_token])
file = open(#user.photo.url(:origin)).read
# ALBUM_ID is constant, its value is the Facebook's album ID
#graph.put_picture(file, { }, ALBUM_ID)
I keep getting this error on last line:
ArgumentError
string contains null byte
I think the way I set file is wrong but I can't find other way to do it.
Thanks before.

While uploading picture on facebook using URL, you just need to send picture url directly (you don't need to send binary data).
# REMOVE THIS LINE
file = open(#user.photo.url(:origin)).read
Update API call as:
# ALBUM_ID is constant, its value is the Facebook's album ID
#graph.put_picture(#user.photo.url(:origin), {}, ALBUM_ID)
Some other ways to use put_picture method:
# put_picture(file, content_type, {:message => "Message"}, 01234560)
# put_picture(params[:file], {:message => "Message"})
# # with URLs, there's no optional content type field
# put_picture(picture_url, {:message => "Message"}, my_page_id)
Source: Koala gem.

Related

How do I handle an external API callback with Ruby on Rails?

I'm in need of some guidance. I'm using the 6px.io API to resize images. The conversion can take a couple of seconds and 6px sends me a post callback when the image has been sent/stored in our S3 bucket. After the callback, when the image is resized and saved we'd like to download the file to the user's browser from our S3 bucket.
If the resized image is already in our S3 bucket and does not need to be processed by 6px we use send_data to download the file to the user. Unfortunately I can't use send_data on the callback controller action to initiate download of the file to the user. How is this done in Rails?
User story:
Click medium resize of image menu item of dropdown.
Rails controller action builds JSON with post callback url and sends to 6px.
6px returns JSON with input and output information plus the status (complete/fail).
File starts to download to user's computer/browser ***This is what I need help with.
Example code (this is for work, can't post the real code):
class FakeExampleController < ApplicationController
def convert_image
# code ommitted
#fake_example = FakeExample.find_by(:id)
image_conversion(params)
end
def callback
# width, height, type variable code ommitted
if params['status'] == 'complete'
converted_file = FakeConvertedImage.create!(filename: #new_file_name, attachment_id: #fake_example.id, format: type, width: width, height: height)
send_converted_file( :url => "OUR_S3_BUCKET", :filename => "#{converted_file.filename}", :type => "#{type}", :disposition => 'attachment' ) #This does not work to download file to user's browser.
else
raise
"Image Conversion Failed"
end
end
def image_conversion(params)
callback_url = fake_example_url.gsub(/localhost:3000/, '********.ngrok.com')
image_converter = ImageConverter.new(params) #This is a wrapper I made for the 6px-ruby gem
image_converter
.convert_type(#fakeexample.mime_type_for_6px(params[:mimetype])
.resize_images
.save("OUR_S3_BUCKET_URL", callback_url)
end
def send_converted_file(opts={})
other_opts = opts.select{ |opt,v| /(filename|type|disposition)/ === opt }
response = { url: opts.fetch(:url), :opts => other_opts }
send_data( open(URI.encode(response[:url].to_s)).read, response[:opts] )
end
end
I don't get/have any errors. I just need advice on how to download the file saved in our S3 to the user.

Facebook - Tag user in photo, keep getting OAuthException - Unknown Error?

I'm making a Facebook app in Rails using Koala gem.
My app needs to upload a picture to a Page's Album and tag the User who submitted it.
I keep getting this error when I want to tag the photo:
Koala::Facebook::ServerError in PhotosController#update
type: OAuthException, code: 1, message: An unknown error has occurred. [HTTP 500]
My app already have publish_actions permission set, so it's not permission issue.
Here's my code:
# token, photo_id, and user_id is confirmed to be not the problem
#graph = Koala::Facebook::API.new(token)
#graph.put_connections(photo_id, "tags",
{
tag_uid: user_id
}
)
If I'm using User's Token, the photo is tagged successfully but still goes to that Error page. If with Page's Token, nothing is tagged and goes to Error.
Any hint or solution?
Thanks
My solution to upload photo:
def post_to_facebook
conf = YAML.load_file File.join(Rails.root,'public','fb.yaml')
oauth = Koala::Facebook::OAuth.new(conf['app'], conf['key'], "http://yoursite.com/social_networks/callback_facebook?id=#{params[:id]}")
redirect_to oauth.url_for_oauth_code(:permissions => 'publish_stream,photo_upload,manage_pages')
end
def callback_facebook
news = News.find(params[:id])
conf = YAML.load_file File.join(Rails.root,'public','fb.yaml')
oauth = Koala::Facebook::OAuth.new(conf['app'], conf['key'], "http://yoursite.com/social_networks/callback_facebook?id=#{params[:id]}")
token = oauth.get_access_token(params[:code])
page = FbGraph::Page.new(page_id).fetch(:access_token => token, :fields => :access_token)
mes = "text_mes"
img_url = "http://yoursite.com#{news.news_image_url}"
page.photo!(:message => mes, :url => img_url)
redirect_to 'https://www.facebook.com/your_page'
end
Where page_id is id of facebook's page where photo will be upload
I have found two possible reasons:
The fact that Facebook doesn't allow us to tag non-friend. Since my token is Page's token, it doesn't have friend.
Maybe Page can't tag anyone.
Even if the user "Liked" the page, it doesn't allow to be tagged.
I changed the token to a User's token and the tagging works fine (as long as it tags a friend of that User).
I will leave this question open for anyone to add proper answer.

Get large images from Page Feed? using Koala Gem & Rails 3.2

Does anyone know how to pull different size images from the Page Feed?
I was trying to use the Type hash that works great for friends and profile pictures.
#page-feed = #graph.get_connections("somepage", "feed", {"type" => "large"})
but for some reason I'm always getting the same picture size for all posts.
Thanks !
Reading the code here: https://github.com/arsduo/koala/blob/81e66f459df840d9d5e122c0d498e2fb9d146655/lib/koala/api/graph_api.rb (line 178, def get_picture) you can see that the method accepts options hash:
Gem source:
# Fetches a photo.
# (Facebook returns the src of the photo as a response header; this method parses that properly,
# unlike using get_connections("photo").)
#
# #param options options for Facebook (see #get_object).
# To get a different size photo, pass :type => size (small, normal, large, square).
# #param block (see Koala::Facebook::API#api)
#
# #note to delete photos or videos, use delete_object(id)
#
# #return the URL to the image
def get_picture(object, args = {}, options = {}, &block)
# Gets a picture object, returning the URL (which Facebook sends as a header)
resolved_result = graph_call("#{object}/picture", args, "get", options.merge(:http_component => :headers)) do |result|
result ? result["Location"] : nil
end
block ? block.call(resolved_result) : resolved_result
end
So you can call it like .get_picture(id, type: :large). Like this:
graph = Koala::Facebook::API.new(token)
profile = graph.get_object('me')
graph.get_picture(profile['id'], type: :large)
Just in case anyone else comes across this, this is what I had to do in order to retrieve the large images. Note that I'm only grabbing the first post in the feed.
In my controller:
#fb_post = #facebook.get_connections(page_id, 'posts').first
#photo = #facebook.get_connections(#fb_post['id'], 'attachments').first
Then, to grab the proper link in the view inside of an img tag, I used:
#photo["media"]["image"]["src"]
For anyone still struggling with this, I was able to use the 'full_picture' field in my Koala object to retrieve a full-resolution URLs of the images:
fields = ['id','picture','full_picture']
graphObj = Koala::Facebook::API.new(accessToken)
hashes = graphObj.get_connection(groupId, 'feed', { limit: 10, fields: fields })
hashes.each do |hash|
mash = Hashie::Mash.new(hash)
fullPicture = mash.full_picture
end

How to post facebook wall with uploaded image/video attachment using koala gem?

I am doing a rails project that involved using Koala gem to call facebook graph API.
Is it possible to post to facebook wall with picture/video attachment (not picture link) via graph API?
I'm able to to put picture using this command
graph = Koala::Facebook::API.new(access_token)
graph.put_picture(params["picture_path"]) #where params["picture_path] is ActionDispatch::Http::UploadedFile object
but this only upload to album
I failed doing this:
graph = Koala::Facebook::API.new(access_token)
graph.put_wall_post("hello", {"picture" => params["picture_path"]} ) #where params["picture_path] is ActionDispatch::Http::UploadedFile object
Error:
undefined method `local_path' for #<ActionDispatch::Http::UploadedFile:0x00000106100a70>
Help ?
Here an example with an image generated with rmagick:
First create an image:
#clown = Magick::ImageList.new("public/images/framed_clown.jpg")
Then put in an album (you must use StringIO) and to_blob:
#clown_id = StringIO.open(#clown.to_blob) do |strio|
response = #graph.put_picture(strio, "image/jpeg")
response['id']
end
Now #clown_id contains the ID of the image, to get the URL:
#picture_url = #graph.get_picture(#clown_id)
Finally we can post to the wall? Well, remember that you need publish_stream permissions:
FACEBOOK_SCOPE = 'user_likes,user_photos,user_photo_video_tags,publish_stream'
So we can say:
begin
#graph.put_wall_post("This a test", {"picture" => #picture_url})
rescue => e
if(e.fb_error_type == "OAuthException")
# Already Posted
end
end
Because is better to put a control for duplicated status message....
Enjoy!!!!!
This worked for me:
graph.put_picture(params["picture_path"], {:message => "Message"})
(Taken from: https://github.com/arsduo/koala/wiki/Uploading-Photos-and-Videos)

Saving a profile image fetched from Facebook while using the Paperclip gem

I'm trying to figure out how to let a user upload a photo from their computer or fetch it from Facebook.
I already have a form for uploading an image and saving it using the Paperclip plugin. That works fine.
I've also already set up Facebook authentication and am using the Koala gem to access the Facebook graph API.
I've already wrote this method:
def fetch_fb_picture
unless current_user.authentications.blank?
#graph = Koala::Facebook::GraphAPI.new(current_user.authentications.find_by_provider("facebook").token)
#picture = #graph.get_picture("#{current_user.authentications.find_by_provider('facebook').username}")
current_user.profile.photo = #picture
end
end
I believe the Koala gem returns the url of the image. However, since I'm using the paperclip gem, my profile accepts these attributes:
t.string "photo_file_name"
t.string "photo_content_type"
t.integer "photo_file_size"
How do I, therefore, properly save the facebook image into the database?
You can do something like:
r = open("http://graph.facebook.com/#{#user.facebook_id}/picture")
image_data = r.read
file_size = r.length
mime_type = "image/jpeg" #fb photos always are jpg
#write data to database, or save as temp file and upload to S3
I wouldnt suggest doing it this way, as the Faceboook graph will always return you the image of the user, as they are always publicly available. You just need to call /picture after their ID or username. You could have a boolean to see if it is a facebook user, and just use the ID to display the image. This will also ensure you have the most recent Facebook photo.
if #user.facebook_image?
image_tag "http://graph.facebook.com/#{#user.facebook_id}/picture"
else
image_tag #user.photo.url(:thumb)
end
I was searching about geting a FB profile pic and saving it with rails to s3, I found a way based on the previous answer (using rmagick):
r = open("http://graph.facebook.com/"+params[:FacebookId]+"/picture?width=142&height=142")
bytes = r.read
img = Magick::Image.from_blob(bytes).first
fmt = img.format
data=StringIO.new(bytes)
data.class.class_eval { attr_accessor :original_filename, :content_type }
data.original_filename = Time.now.to_i.to_s+"."+fmt
data.content_type='image.jpeg'
user.profilepic = data
user.save

Resources