Saving a profile image fetched from Facebook while using the Paperclip gem - ruby-on-rails

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

Related

Rails Paperclip copy set of images from model A to model B

Currently I have a model A (ItemRequest) that has many images.
Once this item request has been approved, it creates a model B (Item) that also has many images.
I'm using paperclip to handle image upload to S3, and what I would like is that after the approve process has been completed, copy the images from model A to model B, duplicating them.
Following some similar questions (but none using models with many images) I've written the following in my ItemRequest model approve method.
if images.length > 0
item.images = images.map { |img| img.dup }
end
And this apparently creates a new set of Image models, but when trying to access the url, it does not open any image and S3 returns 403.
I've checked and no image is created in S3. I can access other images so the S3 is properly configured.
Any ideas on how to solve this?
def resolve! user_id
if status != RESOLVED
ActiveRecord::Base.transaction do
self.resolved_by_id = user_id
self.resolved_date = DateTime.now
self.status = RESOLVED
save!
catalog_item = Item.create(
name: item_name,
oem_name: oem_name,
description: description,
category_id: category_id,
make: make,
part_number: part_number,
uom: uom,
cost_in_cents: cost_in_cents,
weight_in_grams: weight_in_grams
)
if images.length > 0
catalog_item.images = images.map { |img| img.dup }
catalog_item.save
end
end
end
true
end
Something is worth mentioning that doesn't simplify things, is that my Image model is polymorphic.
I've managed to write a solution but not happy with it yet.
Add this to the Image model
def file_remote_url=(url_value)
self.file = URI.parse url_value
#file_remote_url = url_value
end
And then
catalog_item.images = images.map { |img|
new_image = Image.new()
new_image.file_remote_url = img.url
new_image
}
catalog_item.save
Also, this solution does not work locally if uploading to the dev machine.
After a few days of trying different approaches, here is what solved the issue for me:
catalog_item.images = images.map do |img|
new_image = Image.new
new_image.imageable_type = 'CatalogItem'
new_image.imageable_id = catalog_item.id
new_image.file = img.file
new_image
end
This will create a copy of the image instead of changing the reference only. As far as I understood, if you're using S3 and paperclip, it won't simply copy the image using the S3 api but rather make a copy and upload it again, which might be a bit inefficient, but that is a whole other unrelated issue.

Rails - Upload picture to Facebook using URL

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.

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)

Resources