Can't see the video uploaded through youtube-api - node.js

The code doesn't give any errors but on the youtube page there is nothing. The token is ok and I can see the log saying it has finished but on youtube nothing.
How much time it take to display the video on youtube?
const Youtube = require("youtube-api"),
fs = require("fs"),
readJson = require("r-json"),
Logger = require("bug-killer"),
prettyBytes = require("pretty-bytes");
// I downloaded the file from OAuth2 -> Download JSON
const CREDENTIALS = readJson(`${__dirname}/credentials.json`);
// Authenticate
let oauth = Youtube.authenticate({
type: "oauth",
client_id: CREDENTIALS.web.client_id,
client_secret: CREDENTIALS.web.client_secret,
redirect_url: CREDENTIALS.web.redirect_uris[0]
});
//the token obtained with getToken.js script
var tokens = readJson(`${__dirname}/tokens.json`);
//set the token
oauth.setCredentials(tokens);
var req = Youtube.videos.insert({
resource: {
snippet: {
title: "Testing",
description: "Test video upload via YouTube API"
},
status: {
privacyStatus: "public"
}
},
part: "snippet,status",
media: {
body: fs.createReadStream("video.mp4")
}
}, (err, data) => {
console.log("Done.");
process.exit();
});
setInterval(function() {
Logger.log(`${prettyBytes(req.req.connection._bytesDispatched)} bytes uploaded.`);
}, 250);

Resolved, you have to enable the youtube Api v3 for your google app. Stupid issue.

Related

How to fetch videos and documents from remote URL and send it to users from Discord bot without saving?

I am developing a discord bot in Node.js using Discord.js.
I want to send videos/ docs content from the URL to the users via the Discord bot.
So far, This is the output
When the user downloads the video, it works perfectly but to the user it doesn't look like a playable media but an error
url = "https://docs.evostream.com/sample_content/assets/bun33s.mp4"
body = await load(url)
console.log(body)
const exampleEmbed = new EmbedBuilder()
.setTitle(filename)
interaction.followUp({
embeds: [exampleEmbed],
files: [body]
//using request module
function load(uri) {
return new Promise((resolve, reject) => {
const options = {
method: "GET",
uri: uri,
encoding: null,
'Content-Type': 'video/mp4'
};
const body = request(options)
resolve(body)
})
}
Tried using embed objects
const exampleEmbed = {
title: 'Video title',
video: {
url: 'https://docs.evostream.com/sample_content/assets/bun33s.mp4',
},
};
interaction.followUp({ embeds: [exampleEmbed] });
Output:
I want the attachment to look like this

Getting "Content length 0 too small" when trying to upload to vimeo using tus

I am trying to upload a video file to vimeo using their resumable upload protocol, but end up getting
Failed because: Error: tus: unexpected response while creating upload, originated from request (method: POST, url: https://1515143405.cloud.vimeo.com/upload?ticket_id=42606237…62378%26signature%3D19062b29129850403638ca88040debe1e21cc646, response code: 400, response text: Content length 0 too small
this error whenever I initiate the upload.
const vimeoFileUpload = async(e) => {
const fileContent = e.target.files[0];
const fileSize = fileContent.size;
const reader = new FileReader();
reader.onload = r => {console.log(r.target.result)};
let uploadLink;
await fetch(`${backendUri}/fetchUploadLink`, {
method: 'POST',
body: JSON.stringify({fileSize}),
headers: {"Content-Type": "application/json"}
}).then((res) => res.json())
.then((result) => {
uploadLink=result.uploadLink
});
let uploader = new tus.Upload(fileContent, {
uploadUrl: uploadLink,
endpoint:uploadLink,
retryDelays: [0, 1000, 3000, 5000],
metadata: {
filename: "sample",
filetype: fileContent.type
},
uploadSize: fileSize,
onError: function(error) {
console.log("Failed because: " + error);
},
onProgress: function(bytesUploaded, bytesTotal) {
let percentage = (bytesUploaded / bytesTotal * 100).toFixed(2);
console.log(bytesUploaded, bytesTotal, percentage + "%");
},
onSuccess: function() {
console.log(
"Download %s from %s",
uploader.file.name,
uploader.url
);
}
});
uploader.start();
}
This is the code for the upload function.
I also tried setting Content-Length as a custom header in the tus config but it claimed it was a forbidden header and didn't let me modify it
Any thoughts or advice on the matter will be much appreciated.
The initial request to create the video is most likely malformed or invalid. For tus upload, the Vimeo API will return an upload_link on the files.tus.vimeo.com domain (or similar). Make sure the initial POST /me/videos request specifies upload.approach=tus.
Before attempting the actual file upload, you'll want to verify that the API returns upload.approach=tus.
The Vimeo API's tus docs are found here: https://developer.vimeo.com/api/upload/videos#resumable-approach

How to use the node google client api to get user profile with already fetched token?

Getting a user profile info through curl
curl -i https://www.googleapis.com/userinfo/v2/me -H "Authorization: Bearer a-google-account-access-token"
Getting a user profile info through node https get request
const https = require('https');
function getUserData(accessToken) {
var options = {
hostname: 'www.googleapis.com',
port: 443,
path: '/userinfo/v2/me',
method: 'GET',
json: true,
headers:{
Authorization: 'Bearer ' + accessToken
}
};
console.log(options);
var getReq = https.request(options, function(res) {
console.log("\nstatus code: ", res.statusCode);
res.on('data', function(response) {
try {
var resObj = JSON.parse(response);
console.log("response: ", resObj);
} catch (err) {
console.log(err);
}
});
});
getReq.end();
getReq.on('error', function(err) {
console.log(err);
});
}
var token = "a-google-account-access-token";
getUserData(token)
How can I use this google node api client library to get the user profile info provided that I already have the access token? I can use the code above to get the profile but I thought it's probably better off to use the google api library to do it, but I can't figure out how to do that using this node google api client library.
A temporary access token can be acquired through playing this playground
You can retrieve the user profile using the google node API client library. In this case, please retrieve the access token and refresh token as the scope of https://www.googleapis.com/auth/userinfo.profile. The sample script is as follows. When you use this sample, please set your ACCESS TOKEN.
Sample script :
var google = require('googleapis').google;
var OAuth2 = google.auth.OAuth2;
var oauth2Client = new OAuth2();
oauth2Client.setCredentials({access_token: 'ACCESS TOKEN HERE'});
var oauth2 = google.oauth2({
auth: oauth2Client,
version: 'v2'
});
oauth2.userinfo.get(
function(err, res) {
if (err) {
console.log(err);
} else {
console.log(res);
}
});
Result :
{
id: '#####',
name: '#####',
given_name: '#####',
family_name: '#####',
link: '#####',
picture: '#####',
gender: '#####',
locale: '#####'
}
If I misunderstand your question, I'm sorry.
2021 Solution
This answer may divert from the originally asked question but I think it will be useful for some people who are getting google user information in the backend by generating AuthUrl and sending it to the client side and then receiving the data response in the call back URL after the user gives permission from the client side.
Some global declarations
import { google } from "googleapis";
const Oauth2Client = new google.auth.OAuth2(
googleCredentials.CLIENT_ID,
googleCredentials.CLIENT_SECRET,
googleCredentials.REDIRECT_URI
);
Generate the Auth URL with the scopes
const SCOPE = [
'https://www.googleapis.com/auth/userinfo.profile', // get user info
'https://www.googleapis.com/auth/userinfo.email', // get user email ID and if its verified or not
];
const auth_url = Oauth2Client.generateAuthUrl({
access_type: "offline",
scope: SCOPE,
prompt: "consent",
state: "GOOGLE_LOGIN",
});
return res.json({ url: auth_url }); // send the Auth URL to the front end
Get the user data in the callback
let code = req.query.code; // get the code from req, need to get access_token for the user
let { tokens } = await Oauth2Client.getToken(code); // get tokens
let oauth2Client = new google.auth.OAuth2(); // create new auth client
oauth2Client.setCredentials({access_token: tokens.access_token}); // use the new auth client with the access_token
let oauth2 = google.oauth2({
auth: oauth2Client,
version: 'v2'
});
let { data } = await oauth2.userinfo.get(); // get user info
console.log(data);
Feel free to discuss in the comments if there's any confusion or error
You can also decode the id_token that's in the response from oAuth2Client.getToken().
Remember that you need to have necessary scopes enabled for your app for the response to have this id_token. For an example, let's say we just need the user's email. So we'll use,
https://www.googleapis.com/auth/userinfo.email
To decode the token,
const response = await oAuth2Client.getToken(code);
const userInfo = JSON.parse(Buffer.from(response.tokens.id_token.split('.')[1], 'base64').toString());
console.log(userInfo);
This will output,
{
"iss": "https://accounts.google.com",
"azp": "1234987819200.apps.googleusercontent.com",
"aud": "1234987819200.apps.googleusercontent.com",
"sub": "10769150350006150715113082367",
"at_hash": "HK6E_P6Dh8Y93mRNtsDB1Q",
"hd": "example.com",
"email": "jsmith#example.com",
"email_verified": "true",
"iat": 1353601026,
"exp": 1353604926,
"nonce": "0394852-3190485-2490358"
}
This token simply is a JWT object which can be decoded eaisily. You can check this documentation and see even Google recommends this. The advantage of this method is that you don't have to make an extra request to Google APIs to get user's info.
Based on this anser: https://stackoverflow.com/a/46780714/140164
Here is another shorter way to achieve the same results.
const { google } = require('googleapis');
const oauth2Client = new google.auth.OAuth2()
const tokenInfo = await oauth2Client.getTokenInfo(*YourAccessToken*);
console.log(tokenInfo);

Send mail via Google Apps Gmail using service account domain wide delegation in nodejs

I've been reading tutorials and seeing examples for 2 days already, with no success.
I want to send an email using Google Apps Gmail account in NodeJS environment, however, i get 400 response from Google API:
{[Error: Bad Request]
code: 400,
errors:
[{
domain: 'global',
reason: 'failedPrecondition',
message: 'Bad Request'
}]
}
Here's what I've done so far:
Created a project in Google Cloud Platform
Created a service account
Enabled Domain Wide Delegation for the service account
Downloaded the key for the service account in JSON format
API Manager > Credentials i have created OAuth 2.0 client ID
Enabled Gmail API for the project
In Google Apps Admin console:
In Security > Advanced Settings > Manage API client access i have added the Client ID from step 4 above
I have added all possible scopes for the Client ID
Here's the code that tries to send an email:
const google = require('googleapis');
const googleKey = require('./google-services.json');
const jwtClient = new google.auth.JWT(googleKey.client_email, null, googleKey.private_key, ['https://www.googleapis.com/auth/gmail.send'], null);
jwtClient.authorize((err, tokens) => {
if (err) {
console.err(err);
return;
}
console.log('Google auth success')
var gmail = google.gmail({version: 'v1', auth: jwtClient})
var raw = <build base64 string according to RFC 2822 specification>
var sendMessage = gmail.users.messages.send({
auth: jwtClient,
userId: 'user#domain.com',
message: {
raw: raw
}
}, (err, res) => {
if (err) {
console.error(err);
} else {
console.log(res);
}
});
I can see the Google auth success message and the request is sent with properly initialized token:
headers:
{ Authorization: 'Bearer ya29.CjLjAtVjGNJ8fcBnMSS8AEXAvIm4TbyNTc6g_S99HTxRVmzKpWrAv9ioTI4BsLKXW7uojQ',
'User-Agent': 'google-api-nodejs-client/0.9.8',
host: 'www.googleapis.com',
accept: 'application/json',
'content-type': 'application/json',
'content-length': 2 }
But still, the response is 400
So I was half-step close to the solution, the problem was that while creating const jwtClient = new google.auth.JWT(googleKey.client_email, null, googleKey.private_key, ['https://www.googleapis.com/auth/gmail.send'], null); i did not mention the account to be impersonated.
The correct initialization should be:
const jwtClient = new google.auth.JWT(googleKey.client_email, null, googleKey.private_key, ['https://www.googleapis.com/auth/gmail.send'], 'user#domain.com');
To summarize, the correct steps are:
Created a project in Google Cloud Platform
Created a service account
Enabled Domain Wide Delegation for the service account
Downloaded the key for the service account in JSON format
API Manager > Credentials i have created OAuth 2.0 Client ID
Enabled Gmail API for the project
In Google Apps Admin console:
In Security > Advanced Settings > Manage API client access i have added the Client ID from step 4 above
I have added all possible scopes for the Client ID
This is the code that sends mails:
const google = require('googleapis');
const googleKey = require('./google-services.json');
const jwtClient = new google.auth.JWT(googleKey.client_email, null, googleKey.private_key, ['https://www.googleapis.com/auth/gmail.send'], '<user to impersonate>');
jwtClient.authorize((err, tokens) => {
if (err) {
console.err(err);
return;
}
console.log('Google auth success')
var gmail = google.gmail({version: 'v1'})
var raw = <build base64 string according to RFC 2822 specification>
var sendMessage = gmail.users.messages.send({
auth: jwtClient,
userId: '<user to impersonate>',
resource: {
raw: raw
}
}, (err, res) => {
if (err) {
console.error(err);
} else {
console.log(res);
}
});
Hope that would be helpful for others
Thanks very much #agoldis. Both the summary steps and the code were very helpful.
It helped me pick up on a few things I needed to fix on both the GoogleWorkspace and the ApplicationCode end of the communication path. Below is my c# implementation for anyone who needs it.
private static void Try4()
{
try {
//file included in project with properties: CopyToOutputDirectory = CopyAlways
var credential = GoogleCredential.FromFile("MyPrj-MyServiceAccount-Credentials.json")
.CreateScoped(new[] { GmailService.Scope.GmailSend })
.CreateWithUser("WhoIAmImpersonating#bla.com")
.UnderlyingCredential as ServiceAccountCredential;
var service = new GmailService(new BaseClientService.Initializer() { HttpClientInitializer = credential });
var nl = Environment.NewLine;
string plainText = "From: WhoIAmImpersonating#bla.com"
+ nl + "To: myfriend#gmail.com,"
+ nl + "Subject: This is the Subject"
+ nl + "Content-Type: text/html; charset=us-ascii"
+ nl
+ nl + "This is the message text.";
var newMsg = new Message() { Raw = Base64UrlEncode(plainText) };
service.Users.Messages.Send(newMsg, "WhoIAmImpersonating#bla.com").Execute();
Console.WriteLine("Message Sent OK");
}
catch (Exception ex) {
Console.WriteLine("Message failed");
}
}
private static string Base64UrlEncode(string input)
{
var inputBytes = System.Text.Encoding.UTF8.GetBytes(input);
return Convert.ToBase64String(inputBytes)
.Replace('+', '-')
.Replace('/', '_')
.Replace("=", "" );
}

Refresh_token using oauth.io

Hi I am student of Computer Science and doing some experiments on oauth.io. but i am facing problem to get refresh_token after getting code successfully. After getting the code i am writing the follwing line of code but its giving me Internal server error..
The code is
$.ajax("https://oauth.io/auth/access_token", {
type: "post",
data: {
code: result.code,
key: '5WeOrrR3tP6RyShR1',
secret: '2_q3tb_D_qgDwSGpt' },
success: function (data) {
console.log("result", data);
}
});
Which url used to get refresh_token? please someone help me.
thanks
there was a bug recently in the js sdk when you set the response type server-side (to get the code & refresh_token), so you may have to redownload oauth.js if you use a static version.
I guess your jquery code is server side (because of the nodejs tag and the use of a code), but i had an error "no transport" that i fixed with a new XMLHttpRequest. Here is my full test:
var jsdom = require('jsdom').jsdom;
var win = jsdom().createWindow();
var $ = require('jquery')(win);
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
$.support.cors = true;
$.ajaxSettings.xhr = function () {
return new XMLHttpRequest;
}
$.ajax("https://oauth.io/auth/access_token", {
type: "post",
data: {
code: process.argv[2],
key: 'xxxxxxxxxxxx',
secret: 'yyyyyyyyyyyy' },
success: function (data) {
console.log("result", data);
},
error: function() {
console.error(arguments);
}
});
and my result looks like:
{ access_token: 'xxxxxxxxxxx',
request:
{ url: '{{instance_url}}',
required: [ 'instance_url' ],
headers: { Authorization: 'Bearer {{token}}' } },
refresh_token: 'yyyyyyyyyyyyy',
id: 'https://login.salesforce.com/id/00Db0000000ZbGGEA0/005b0000000SSGXAA4',
instance_url: 'https://eu2.salesforce.com',
signature: 'zzzzzzzzzzzzz',
state: 'random_string',
provider: 'salesforce' }

Resources