I am currently using the google-api-ruby-client to upload videos to Youtube API V3, but I can't find a way of getting the Youtube ID that is created by a resumable upload. The code I am trying to use is along the lines of:
media = Google::APIClient::UploadIO.new(file_path, 'application/octet-stream')
yt_response = #client.execute!({
:api_method => #youtube.videos.insert,
:parameters => {
:part => 'snippet,status',
'uploadType' => 'resumable'
},
:body_object => file_details,
:media => media
})
return JSON.parse(yt_response.response.body)
But unfortunately for resumable uploads, yt_response.response.body is blank. If I change the 'uploadType' to 'multipart' then body is a JSON blob that contains the Youtube ID. The response for a resumable upload though is only the resumable session URI for the upload with an empty body. How do I go from that URI into the Youtube ID I just created?
Synthesizing the info from How to engage a Resumable upload to Google Drive using google-api-ruby client? and the existing multipart upload sample leads to
videos_insert_response = client.execute!(
:api_method => youtube.videos.insert,
:body_object => body,
:media => Google::APIClient::UploadIO.new(opts[:file], 'video/*'),
:parameters => {
'uploadType' => 'resumable',
:part => body.keys.join(',')
}
)
videos_insert_response.resumable_upload.send_all(client)
puts "'#{videos_insert_response.data.snippet.title}' (video id: #{videos_insert_response.data.id}) was successfully uploaded."
That worked for me.
I am doing resumable uploads in chunks using 0.7.1 version of the API and I had to to this to get the ID...
result = videos_insert_response.resumable_upload.send_all(client)
video = JSON.parse(result.response.body)
puts "Video id '#{video['id']}' was successfully uploaded."
Related
I'm struggling to find a good example of the full set of requests necessary to send an email through the Gmail API containing an attachment larger than 10mb.
I've seen https://developers.google.com/gmail/api/v1/reference/users/messages/send and https://developers.google.com/gmail/api/guides/uploads#resumable, but there's nothing that ties it all together.
We're using the ruby client, but we're unable to complete this flow. With the following code, we get the following error trying to make the second request: Google::APIClient::ClientError: Recipient address required
The full body of the response is the following:
{"error"=>{"errors"=>[{"domain"=>"global", "reason"=>"invalidArgument", "message"=>"Recipient address required"}], "code"=>400, "message"=>"Recipient address required"}}
Here's the code used to generate the request:
raw = Base64.urlsafe_encode64 message_string
result1 = api_client.execute!(
:api_method => gmail_api.users.messages.to_h['gmail.users.messages.send'],
:parameters => {
:uploadType => 'resumable',
:userId => 'me'
},
:headers => {
'Content-Type' => 'application/json',
'X-Upload-Content-Type' => 'message/rfc822',
'X-Upload-Content-Length' => raw.bytesize.to_s
}
)
upload_id = result1.headers['x-guploader-uploadid']
result2 = api_client.execute!(
:api_method => gmail_api.users.messages.to_h['upload.gmail.users.messages.send'],
:body_object => {
:raw => raw
},
:parameters => {
:uploadType => 'resumable',
:upload_id => upload_id,
:userId => 'me'
},
:headers => {
'Content-Type' => message.content_type,
'Content-Length' => raw.bytesize.to_s
}
)
So the issue (thank you to #tholle) was that when sending attachments greater than 5mb and less than 35mb (but also works on messages without attachments), you do NOT base64 encode the body of the request, and use multipart as the uploadType. Unfortunately the docs don't mention this at all, and the error messages don't indicate that either.
Here's a working example that was able to send a 20mb attachment. Hopefully this will help anyone else who has wasted countless hours trying to figure this one out!
result = api_client.execute!(
:api_method => gmail_api.users.messages.to_h['gmail.users.messages.send'],
:body => rfc822_message_string,
:parameters => {
:uploadType => 'multipart',
:userId => 'me'
},
:headers => {
'Content-Type' => 'message/rfc822',
}
)
I am working on a JavaScript client and I finally found a way to send email using resumable method. (Thank you #Tholle and #jwg2s). Although this is in JavaScript client it should work about the same in other client too.
This is what I did:
// MIME Mail Message data. Copied form above #Tholle 's message.
let mail = [
'Content-Type: multipart/mixed; boundary="foo_bar_baz"\r\n',
"MIME-Version: 1.0\r\n",
"to: to#gmail.com\r\n",
"from: from#gmail.com\r\n",
"subject: i am subject\r\n\r\n",
"--foo_bar_baz\r\n",
'Content-Type: text/plain; charset="UTF-8"\r\n',
"MIME-Version: 1.0\r\n",
"Content-Transfer-Encoding: 7bit\r\n\r\n",
"The actual message text goes here\r\n",
"--foo_bar_baz\r\n",
"Content-Type: application/json; name=package.json\r\n",
"Content-Transfer-Encoding: base64\r\n",
"Content-Disposition: attachment; filename=package.json\r\n\r\n",
"<base64 file data. data according to content type>",
"\r\n",
"--foo_bar_baz--",
].join("");
// get resumable upload link.
let resumableURL = "";
gapi.client
.request({
path: "/upload/gmail/v1/users/me/messages/send?uploadType=resumable",
headers: {
"X-Upload-Content-Type": "message/rfc822",
},
method: "post",
})
.then(
(res) => {
resumableURL = res.headers.location;
console.log(res);
},
(err) => console.log(err)
);
// send email
gapi.client
.request({
path: resumableURL,
headers: {
"Content-Type": "message/rfc822",
},
method: "post",
body: mail,
})
.then(
(res) => {
console.log(res);
},
(err) => console.log(err)
);
To convert gapi.client.request to Fetch API call you just need to add Authorization: Bearer <access_token> to header field. I have tried using Fetch API but response were blocked due to cors error so api client like Postman should be used.
To do more with resumable upload method check documentation: Upload Attachment
I am trying to create some simple Ruby code to add emails using the Campaign Monitor API. Below is my code.
require 'httparty'
require 'json'
def request
url = 'https://api.createsend.com/api/v3.1/subscribers/MYLISTID.json'
auth = {:username => 'MYAPIKEY', :password => 'x'}
response = HTTParty.post(url,
:basic_auth => auth, :body => {
'EmailAddress' => 'mike#hotmail.com',
'Name' => 'Test',
'Resubscribe' => true,
'RestartSubscriptionBasedAutoresponders' => true
})
puts response
puts response.code
end
request
I can connect with the API. However, when I try to add the email I am getting the following response.
{"Code"=>400, "Message"=>"Failed to deserialize your request.
Please check the documentation and try again.
Fields in error: subscriber"}
400
When I change the request to get instead of put
my response is:
{"Code"=>1, "Message"=>"Invalid Email Address"}
I can't understand what I am doing wrong as I have followed the documentation on the Campaign Monitor API
It looks like you have everything setup correctly, you just need to turn the body of the post into a json string.
response = HTTParty.post(url,
:basic_auth => auth, :body => {
'EmailAddress' => 'mike#hotmail.com',
'Name' => 'Test',
'Resubscribe' => true,
'RestartSubscriptionBasedAutoresponders' => true
}.to_json)
I'd like to point out that a Campaign Monitor API gem also exists that will do all of that work for you.
Campaign Monitor API Gem
I keep getting an error everytime I try to change the souncloud avatar by uploading, I'm guessing something is wrong with my api wrapper layout? I get a
"`handle_response': HTTP status: 500 Internal Server Error (SoundCloud::ResponseError)"
"HTTP status: 403 Forbidden (SoundCloud::ResponseError)
from /Users/.../.rvm/gems/ruby-2.2.0/gems/soundcloud-0.3.2/lib/soundcloud/client.rb:32:in `post'"
My code:
require 'soundcloud'
user = Soundcloud.new(:client_id => '...',
:client_secret => '...',
:username => '...',
:password => '...')
avatar_data = File.path("/path/to/file/-1.jpg")
user.post('/me').avatar_data
I also tried:
testuser.post('/me/#{avatar_data}')
the goal is to have one Google (YouTube) account for the web app. Users of the web app will be able to upload videos via this account to the one YouTube channel. After many hours im in the ends. I've found plenty of samples how to implement for Google user <-> web app interaction, but I don't need such comprehensive solution.
I'm trying over OAuth 2.0 (as recommended) and with Google API Ruby Client (https://github.com/google/google-api-ruby-client)
So far I have authorized the Google account (which will have that YouTube channel) with the web app, all necessary scopes included, offline access too and I have mechanism for refreshing access token. So I have access token, refresh token, client id and client secret.
But I don't know how to send a simple authorized request. The result below returns me "Daily Limit for Unauthenticated Use Exceeded." after a while so something wrong - i guess im missing part with client id and client secret.
So the question is: How to send simply authorized request via OAuth 2.0 with Google API Ruby Client, when we work with only one user and we have all necessary ids, secrets and tokens?
Thanks for any help or suggestion.
# Faraday connection
conn = Faraday.new(:url => 'https://accounts.google.com',:ssl => {:verify => false}) do |faraday|
faraday.request :url_encoded
faraday.response :logger
faraday.adapter Faraday.default_adapter
end
# Refresh token
result = conn.post '/o/oauth2/token', {
'refresh_token' => "1/1lDIvifN******************dk9Akuc9ELVKM0",
'client_id' => "61********506.apps.googleusercontent.com",
'client_secret' => "********************g_dLfKmi",
'grant_type' => 'refresh_token'}
#output = ActiveSupport::JSON.decode result.body
#access_token = #output['access_token']
#token_type = #output['token_type']
# Google Client
client = Google::APIClient.new
# YouTube API v3
api = client.discovered_api('youtube', 'v3')
# Retrieve list of playlists (not working)
#result = client.execute(
:api_method => api.playlists.list,
:parameters => {'part' => 'snippet', 'mine' => 'true'},
:authorization => {'token_type' => #token_type, 'access_token' => #access_token}
)
Ok, so I though the :authorization param in the execute request will add HTTP header Authorization: token_type access_token itself, but not and it was a problem.
So this works:
#result = client.execute(
:api_method => api.playlists.list,
:parameters => {'part' => 'snippet', 'mine' => 'true'},
:authorization => {:token_type => #token_type, :access_token => #access_token},
:headers => {:authorization => #token_type + ' ' + #access_token}
)
i am using omniauth to authenticate a user via twitter. omniauth provides access tokens. now i want to send the get or post request to twitter. i dont want to use any gems. i want to do with net::http.
even in twitter api documentation ! I am not able to find a good tutorial for this
can any one help? thanks
Here it is exactly what you need, so, since you've got the token and the secret from omniauth, now you are going to use it:
def prepare_access_token(oauth_token, oauth_token_secret)
consumer = OAuth::Consumer.new("APIKey", "APISecret", { :site => "https://api.twitter.com", :request_token_path => '/oauth/request_token', :access_token_path => '/oauth/access_token', :authorize_path => '/oauth/authorize', :scheme => :header })
token_hash = { :oauth_token => oauth_token, :oauth_token_secret => oauth_token_secret }
access_token = OAuth::AccessToken.from_hash(consumer, token_hash )
access_token
end
Then you, for example, post a tweet:
msg = {'status' => 'Hey look I can tweet via OAuth!'}
access_token = prepare_access_token(token, secret)
response = access_token.post('https://api.twitter.com/1/statuses/update.json', msg, { 'Accept' => 'application/xml' })
Read the article presented on the link for more informations.