Cloud Functions for Firebase and third party api - node.js

My problem is to make use of an API along with Firebase Functions, the API in question is Coinbase, I use the API with node, if I test in the terminal with the node command it works, however when I use it with Firebase Functions Does not work at all, I've been trying to solve the problem for almost a week now.
The code is as follows>
var functions = require('firebase-functions');
var Client = require('coinbase').Client;
var client = new Client({
"apiKey": "xxxxxxxxxxxx",
"apiSecret": "xxxxxxxxxxxxxxxxxxxxxxx"
});
exports.helloWorld = functions.https.onRequest((request, response) => {
this.client.getAccounts({}, function(err, accounts) {
if(accounts){
response.send(accounts);
}else{
response.send(err);
}
});
});
The error: https://us-central1-investimentos-b7406.cloudfunctions.net/helloWorld
The Coinbase API: https://developers.coinbase.com/docs/wallet/guides/bitcoin-wallet

There's a warning in the docs:
Firebase projects on the Spark plan can make only outbound requests to
Google APIs. Requests to third-party APIs fail with an error. For more
information about upgrading your project, see Pricing.
So you'll need to upgrade to a paid plan to use external APIs.

Related

How to make a post using WATSON and Node js?

I want to make a POST (add a new task) through chatting with Watson.
I have the POST function which works very well, I tested it on Postman. And I have the Watson nodes created.
Here is my endpoint from the POST in Node js:
MainRouter.post('/welcome', (req, res) => {
TaskPost.postTask(req.body).then(message => {
return res.json(message);
}).catch((error) => {
return res.status(404).json(error);
});
});
Here is my conversation with Watson (is working very well):
I also included this in the main.js and changed the password and url:
const AssistantV2 = require('ibm-watson/assistant/v2');
const { IamAuthenticator } = require('ibm-watson/auth');
const assistant = new AssistantV2({
authenticator: new IamAuthenticator({ apikey: '<apikey>' }),
serviceUrl: 'https://api.us-south.assistant.watson.cloud.ibm.com',
version: '2018-09-19'
});
How do I make this connection ? What do I have to include?
I would recommend the official Node.js SDK for the IBM Watson services. It includes support for Watson Assistant and is easy to use.
If you still want to use the V2 API directly, then take a look at how the SDK utilizes the API. As alternative, the API docs for Watson Assistant have code snippets for Node.js.
The basic flow is that you authenticate, then establish a session, and finally send messages with the user input to Watson Assistant.
To get to your dialog node with the task, the user (or your code) would need to send the right intents and entities for navigating from the root node to that specific subnode.

Firebase test auth cloud functions locally

exports.sendWelcomeEmail = functions.auth.user().onCreate((user) => {
console.log(user.uid);
console.log(user.email);
console.log(user.displayName);
});
exports.getUserInfo = functions.https.onCall(async (data, context) => {
// get array of user IDs and returns information (from Users collection)
const userIDs = data.userIDs;
const result = [];
const querySnapData = await admin.firestore().collection("Users").get();
querySnapData.forEach((ele) => {
if (userIDs.indexOf(ele.id) !== -1 && ele.id !== context.auth.uid) {
result.push(ele.data());
}
});
return { res: result };
});
I've got these two functions in my project - one is callable function and the other one is auth trigger functions.
So in my client app, I run
firebase.functions().useFunctionsEmulator('http://localhost:5001');
let getUserInfo = functions.httpsCallable('getUserInfo');
getUserInfo({userIDs: data}).then(res => doSomething);
And to run the cloud functions locally
firebase emulators:start
But it says
functions[sendWelcomeEmail]: function ignored because the auth emulator does not exist or is not running.
So in the client App, getUserInfo works pretty well but can't trigger onCreate.
But I was not able to find any document about auth emulator.
Any link/article/video or answer is appreciated.
The Firebase Emulator Suite currently Cloud Firestore, Realtime Database, Cloud Functions, and Cloud Pub/Sub. It does not yet emulate Firebase Authentication APIs. So any auth calls you make will be executed against the real project that is associated with the emulators.
This also means that your functions.auth.user().onCreate((user) => { Cloud Function will not be triggered in the emulators at the moment. You'll have to deploy it to the servers to test this trigger.
To learn when an auth emulator is available, I recommend keeping an eye on Firebase's release notes, and on the main documentation page for the emulator suite that lists the supported products. You can also follow along more closely on Github, either in the commits, or in this feature request.
firebase recently released the Authentication Emulator, you can check it via the release notes here: https://firebase.google.com/support/releases#october_26_2020, and further guide here: https://firebase.google.com/docs/emulator-suite/connect_auth
So as #Franek van Puffelen wrote above, it is not done yet.
Was able to test auth functions locally like below.
function sendWelcomeEmail(user) {
console.log(user.uid);
console.log(user.email);
console.log(user.displayName);
}
exports.sendWelcomeEmail = functions.auth.user().onCreate((user) => sendWelcomeEmail(user));

How can I deploy a discord.js bot to Cloud Functions?

I want to deploy a Discord bot running on discord.js to Firebase Cloud Functions but I can't get the bot to run in Firebase. If I use nodemon it runs perfectly but if I use firebase deploy it will not start the bot.
Here is my current code:
const functions = require('firebase-functions');
require('dotenv').config();
const token = process.env.TOKEN
const Discord = require('discord.js')
const Client = new Discord.Client();
Client.on('ready', () => {
Client.channels.find(x => x.name === 'main-cannel').send('bot is deployed')
Client.user.setGame(`The Cult | ${Client.guilds.size} servers`)
Console.log('test')
});
Client.login(token);
//is is not working but de basic
//export.App = functions.... {Client}
exports.app = functions.https.onRequest((request, response) => {
response.send("Test");
});
This may not be the best combination of google cloud platform services, since cloud functions where not designed with this in mind. You can just host your Discord bot on a compute engine machine.
If you want to use the dynamic scaling have a look at Discord Microservice Bots where DasWolke describes what microservices are. Hey also included his javascript code to split up the different services for Discord.
What you can do on Google cloud platform specifically, is creating a VM with the Gateway running. This needs to run 24/7 and should be lightweight. You can use an f1-micro (which is free) for this though google recommends a g1-small for the task.
The gateway should filter the events you are looking for (because Discord sends a lot of events and you don't need most) and send the data to cloud function or cloud run (you can send the data via pub/sub). In my experience, a cloud run has much shorter startup times so I went with that.
Inside your function, you receive the data do with it what you want. If you want something in Discord (send a message, manage channels, ...) you can use SnowTransfer for that. SnowTransfer just calls the rest API on discord.
Put client.login(token) into where response.send("Test"); is. This will prompt your bot's code to execute upon an HTTP request.
In https://us-central1-<your project ID>.cloudfunctions.net/app, replace <your project ID> with your project's ID.
If Firebase Hosting gives you the URL example-123.web.app, your project ID is example-123. You can also get your project ID through the console: open the Firebase console, select your project, click the settings icon, go to "Project settings," and its ID is on the second line of the table.
For this to work, you have to move your token straight into the code. You can't use a shell file like .env.
In the end, your code will be:
const functions = require('firebase-functions');
const token = 'whatever the token is';
const Discord = require('discord.js')
const Client = new Discord.Client();
Client.on('ready', () => {
Client.channels.find(x => x.name === 'main-cannel').send('bot is deployed')
Client.user.setGame(`The Cult | ${Client.guilds.size} servers`)
Console.log('test')
});
exports.app = functions.https.onRequest((request, response) => {
response.send("Test"); // Do not delete this! Your request will time out if you do.
Client.login(token);
});
As Gabber235 noted, this is probably not the best Google Cloud Platform service to use for this, and you should probably use Compute Engine.

How to test http request on Dialogflow Fulfillment with the Inline Editor

I am testing Dialogflow Fulfillment with the Inline Editor.
What I am trying to do is a http request using que 'request' library.
Here is the code I am using:
const requesthttp = require('request');
requesthttp('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY', { json: true }, (err, res, body) => {
if (err) { return console.log(err); }
console.log(body.url);
console.log(body.explanation);
});
But It returns me an error of not found.
I also noticed an alert on my Dialogflow with the following message:
"Billing account not configured. External network is not accessible and quotas are severely limited. Configure billing account to remove these restrictions."
So... Probably I can't test this piece of code without configuring a billing account.
My question is... Is there a url that I can use to test this code?
Or the only way for me to test this code is configuring a billing account and paying for it?
Thanks in advance
There are a number of approaches to testing your code.
If you want to continue to use Dialogflow's Inline Editor, you will need to setup Firebase to use a payment plan. However, the Blaze plan is "pay as you go" after a basic level of use. This level of use should be sufficient to cover most testing (and even very light production) uses of the service without imposing a charge. Once your Action has been approved, you're able to receive credits for the Google Cloud Platform, which can be applied to this use in case you go over the minimum level.
You can also use Firebase Cloud Functions, which the Inline Editor is based on, and your own local editor. One advantage of this is that you can serve the function locally, which has many of the same features as deploying it, but doesn't have the URL restriction (it is your own machine, after all). You can use a tool such as ngrok to create a secure tunnel to your your machine during testing. Once you have tested, you can deploy this to Firebase with a paid plan.
You can, of course, choose to use any other hosting method you wish. Google and Dialogflow allow you to run your fulfillment webhook on any server, as long as that server can provide an HTTPS connection using a valid, non-self-signed, certificate. If you're using node.js, you can continue to use these libraries. If you wish to use another language, you will need to be able to parse and return JSON, but otherwise you have no restrictions.
There are a lot of ways to create your own server like using NodeJS client with Express.JS which you can expose to the internet using NGROK as webhook for fulfilment.
Develop a webhook. You can use different client libraries in NodeJS (AoG Client or Dialogflow Client) or in Python (Flask-Assistant or Dialogflow Client) or can create your own just using JSON request/response with Dialogflow and Action-on-Google.
Once the webhook is ready, run it locally and expose to the internet using NGROK.
Start with following code for Actions-on-Google with Express.JS
'use strict';
const {dialogflow} = require('actions-on-google');
const express = require('express');
const bodyParser = require('body-parser');
const app = dialogflow();
app.intent('Default Welcome Intent', conv => {
conv.ask('Hi, Welcome to Assistant by Express JS ');
});
express().use(bodyParser.json(), app).listen(8080);
Since DF uses firebase cloud functions you can use https as in nodejs. But requesting domains outside of the google/firebase universe will require the paid version of firebase.
const https = require('https');
return new Promise((resolve, reject) => {
const hostname = info.hostname;
const pathname = info.pathname;
let data = '';
const request = https.get(`https://${hostname}${pathname}`, (res) => {
res.on('data', (d) => {
data += d;
});
res.on('end', resolve);
});
request.on('error', reject);
});

How can I deploy firebase queue to app engine and have it observe Firebase nodes?

I am trying to send device-to-device notification via FCM which is not so trivial. I use Firebase as the database and by reading the documentation have learned that I need to have an app server to communicate between clients and FCM. Also, I have found that Firebase queue can be used to observe the Firebase nodes and upon any change e.g, ChildAdded, send a notification to other related users on other devices via FCM.
Unfortunately, I can't figure out how to deploy Firebase queue to app engine; as I'm not that experienced with node.js and it seems that Firebase queue documents are all written with node.js.
Any help would be appreciated.
So for someone who is new to node.js it was a bit of confusing cycle to understand whats going on , but I was able to upload a simple job which is pretty much the "sanichat" example of firebase-queue and it seems to be working.
Here's the job for anyone who might be struggling with the same issue:
// chat_message_sanitization.js
var Queue = require('firebase-queue');
var firebase = require('firebase');
firebase.initializeApp({
serviceAccount: 'path to the json file downloaded when setting up google services account',
databaseURL: 'https://***your firebase***.firebaseio.com/'
});
var db = firebase.database();
var
queueRef = db.ref('queue');
var messagesRef = db.ref('queue_messgs');
var options = {
'specId': 'sanitize_message'
};
var sanitizeQueue = new Queue(queueRef, options, function(data, progress, resolve, reject) {
// sanitize input message
data.message = sanitize(data.message);
// pass sanitized message and username along to be fanned out
resolve(data);
});
I have been able to run it locally "node app.js" and deploying using "gcloud app deploy"
Cheers!

Resources