How can I registrate users in my my google actions webhook? - javascript

I am trying to allow users to register by voice when they use my Google action. How can I do it?
I have tried to use Account linking with Google Sign-In using the Client ID, but I do not know how to collect the user data in my webhook.
Looking for information I found that:
app.intent("Show User Profile", conv => {
const payload = conv.user.profile.payload;
if (payload) {
const userId = payload.aud;
const name = payload.name;
const givenName = payload.given_name;
const familyName = payload.family_name;
const email = payload.email;
const emailVerified = payload.email_verified;
const picture = payload.picture;
.....
But I have implemented my intents in the following way and I can't use the conv parameter:
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
async function welcome(agent) {
agent.add(`Welcome`);
...
}
. . .
let intentMap = new Map();
intentMap.set('Default Welcome Intent', welcome);
agent.handleRequest(intentMap);
});
I need to get the user information as the case above but using my variable agent instead of conv
Thanks all of you

In your second code snippet, you seem to be using the dialogflow-fulfillment library. You cannot use this library to do Google Sign-In. You will need to switch over to the actions-on-google library, which has the pattern in the first snippet.

Related

How to do 'signTransaction' after authenticated by 'signPersonalMessage' by WalletConnect of '#walletconnect/react-native-dapp'?

I am developing a react native mobile app where user can connect their existing wallet(rainbow, metamask and many more) to app.
I have already done the authentication part, like user can successfully connect their app wallet to app by this code.
import { useWalletConnect } from '#walletconnect/react-native-dapp';
const connector = useWalletConnect();
await connector.connect();
const message = `App name is XYZ - ${new Date().toUTCString()}`;
const hexMsg = convertUtf8ToHex(message);
const address = connector.accounts[0];
await setItemToStorage('address', address);
const msgParams = [hexMsg, address];
connector.signPersonalMessage(msgParams).then(async result => {
let data = {
message,
signature: result,
};
Now every thing is working as expected.
And then I have to transfer my wallet amount to other address, and to achieve this I know I have to get permission from wallet app,
To achieve this I am trying to do like
let txObj = {
gas: Web3js.utils.toHex(100000),
to: receiver_address!,
data: data,
from: userWallet,
};
console.log('Start transaction...');
const singTrasaction = await connector.signTransaction(txObj);
The connector.signTransaction(txObj) open the wallet app but not prompted me to confirm.
I am just confused and nothing get help me.
Please help me anyone I am getting stuck on this since a week.

Firebase Funtions push notifications

I'm new to firebase and there is something I can't do. I want to send a notification to the phone with firebase functions. I want to receive notifications on the phone when someone follows me. My Firebase collection is as in the photo. I want to access the Followers array and send its information with notification. The codes I could write are as follows. What do I need to add?
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
exports.sendPushNotification = functions.firestore.document('/users/{uid}').onCreate((snap, context) => {
var values = snap.data();
var token = values.fcmTokens;
var payload = {
notification: {
title: values.title,
body: values.message
}
}
return admin.messaging().sendToDevice(token, payload);
});
First, onCreate() function is triggered when a document is created. I assume followers array will be updated everytime someone follows a user? In that case you should be using onUpdate() that'll trigger the function when the document is updated. You can just check if length of followers array has changed in the update, if yes then send the notification as shown below:
exports.sendPushNotification = functions.firestore
.document('users/{userId}')
.onUpdate((change, context) => {
const newValue = change.after.data();
const previousValue = change.before.data();
if (newValue.followers.length > previousValue.followers.length) {
// followers count increased, send notification
const token = newValue.fcmTokens;
const payload = {
notification: {
title: "New Follower",
body: "Someone followed you"
}
}
await admin.messaging().sendToDevice(token, payload);
}
return null;
});
Here, we send notification only if the followers field has changed since this function will trigger whenever any field in this user document is updated.
If you want to specify who followed the user, then you'll have to find the new UID added in followers array and query that user's data.
Firestore documents have a max size limit of 1 MB so if a user can have many followers then I'll recommend creating a followers sub-collection. Then you'll be able to use onCreate() on the sub-document path /users/{userId}/followers/{followerId}

How to create account/signer using Phantom Wallet provider?

I am following the inner instructions of a Solana NFT to create the process of listing an NFT for sale.
According to this NFT, https://solscan.io/tx/25g9L7rDCn8ZbZAZoCvyVNe5woZUoK2PVU3VEXftqySa2EYsLUJB2GA42qDwxsezUBRH2A9eJX1iUUD2LCK9Fua9, the first instruction is to create an account.
The instruction shows
NewAccount - E61SDPzHP61C4KwwiSqG4FAHXof852wsaSjh3F4kLbwmicon
Source - H2eud1RCJu8u8vEQ8jJLQ32jM5oKfARGxz5LwEKKfTLuicon
TransferAmount(SOL) - 0.00223416
ProgramOwner - M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7Kicon
New Account seems to be a newly generated account and Source is the wallet which was used when the user connected their wallet to the client.
I am using the this code from the Solana Cookbook for reference
import { clusterApiUrl, Connection, PublicKey, Keypair, Transaction, SystemProgram } from "#solana/web3.js";
import { Token, TOKEN_PROGRAM_ID, AccountLayout } from "#solana/spl-token";
import * as bs58 from "bs58";
(async () => {
// connection
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
// 5YNmS1R9nNSCDzb5a7mMJ1dwK9uHeAAF4CmPEwKgVWr8
const feePayer = Keypair.fromSecretKey(
bs58.decode("588FU4PktJWfGfxtzpAAXywSNt74AvtroVzGfKkVN1LwRuvHwKGr851uH8czM5qm4iqLbs1kKoMKtMJG4ATR7Ld2")
);
// G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY
const alice = Keypair.fromSecretKey(
bs58.decode("4NMwxzmYj2uvHuq8xoqhY8RXg63KSVJM1DXkpbmkUY7YQWuoyQgFnnzn6yo3CMnqZasnNPNuAT2TLwQsCaKkUddp")
);
const mintPubkey = new PublicKey("54dQ8cfHsW1YfKYpmdVZhWpb9iSi6Pac82Nf7sg3bVb");
// generate a new keypair for token account
const tokenAccount = Keypair.generate();
console.log(`token account: ${tokenAccount.publicKey.toBase58()}`);
let tx = new Transaction().add(
// create token account
SystemProgram.createAccount({
fromPubkey: feePayer.publicKey,
newAccountPubkey: tokenAccount.publicKey,
space: AccountLayout.span,
lamports: await Token.getMinBalanceRentForExemptAccount(connection),
programId: TOKEN_PROGRAM_ID,
}),
/**... some other instruction*/
);
console.log(`txhash: ${await connection.sendTransaction(tx, [feePayer, tokenAccount])}`);
})();
From my understanding, in this scenario the feePayer is the user who connected their wallet. (Source from the instructions), tokenAccount is the account that we want to transfer the SOL to (NewAccount from the instructions), and programID is ProgramOwner from the instructions.
When I run this exact code from the Solana Cookbook it works.
When I try using the provider as the feePayer (wallet that was connected in the client) it doesn't work.
I have a function to get my provider
getProvider = () => {
if ("solana" in window) {
const anyWindow = window;
const provider = anyWindow.solana;
if (provider.isPhantom) {
return provider;
}
}
window.open("https://phantom.app/", "_blank");
};
Then I grab my provider with
const provider = this.getProvider();
I replace the original feePayer created with Keypair.fromSecretKey with the provider.
My assumption as to why provider isn't working as one of the signers in await connection.sendTransaction(tx, [provider, tokenAccount]) is because the signer requires a secret key.
So what I try to do instead is sign the transaction myself using some code I've found online on how to sign a transaction.
const blockHash = await connection.getRecentBlockhash()
tx.feePayer = provider.publicKey
tx.recentBlockhash = await blockHash.blockhash
const signed = await provider.signTransaction(tx);
This runs fine and I'm able to see the results when I do console.log(signed);
The problem I'm getting is that there are 2 signatures and one of them is null. One is the signature of the provider and the other is the signature of the tokenAccount.
When I use console.log() to show the public key of the provider and the public key of the tokenAccount and try to match it to the public keys within the signature, I find that the signature of the tokenAccount is the one that is returning null.
So when it's time to run const signature = await connection.sendRawTransaction(signed.serialize()); I get an error from signed.serialize() saying Signature verification failed
What am I doing wrong here?
Can I create a Signer from a user connecting their phantom wallet? If not, how can I sign the transaction so that neither of the signatures come out null?
So I would recommend using the wallet-adapter to connect and send transactions from wallets.
This will make the code above look something like this:
const { publicKey, sendTransaction } = useWallet();
// G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY
const alice = Keypair.fromSecretKey(
bs58.decode("4NMwxzmYj2uvHuq8xoqhY8RXg63KSVJM1DXkpbmkUY7YQWuoyQgFnnzn6yo3CMnqZasnNPNuAT2TLwQsCaKkUddp")
);
const mintPubkey = new PublicKey("54dQ8cfHsW1YfKYpmdVZhWpb9iSi6Pac82Nf7sg3bVb");
// generate a new keypair for token account
const tokenAccount = Keypair.generate();
console.log(`token account: ${tokenAccount.publicKey.toBase58()}`);
let tx = new Transaction().add(
// create token account
SystemProgram.createAccount({
fromPubkey: publicKey,
newAccountPubkey: tokenAccount.publicKey,
space: AccountLayout.span,
lamports: await Token.getMinBalanceRentForExemptAccount(connection),
programId: TOKEN_PROGRAM_ID,
}),
/**... some other instruction*/
);
const signature = await sendTransaction(transaction, connection);
await connection.confirmTransaction(signature, 'processed');
Hi i have similar issue,
There are two signers admin and user,
admin is signing the tx from node and serializing tx.
this i send to frontend
and user signs it.
But as initially the signature is null, so wallet.signTransaction(tx);
gives the Signature verification failed
You have to partially sign with the tokenAccount before sending the transaction.
const blockHash = await connection.getRecentBlockhash()
tx.feePayer = provider.publicKey
tx.recentBlockhash = await blockHash.blockhash
const signed = await provider.signTransaction(tx);
// now sign with the tokenAccount
signed.partialSign(tokenAccount);

Setting collection name in Firebase function

Just starting to use Firebase functions and have the sample working, but confused because the update event doesn't occur if I change the 'messages' collection to a different name, eg 'listings'. I change the word 'messages' in two places, on the 'add' and the 'makeUppercase' line. I get the response OK, it writes the data to the collection, but doesn't fire the event. Must be simple, but can't google it.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.addMessage = functions.https.onRequest(async (req, res) => {
// Grab the location parameter.
const inputcode = req.query.code || 'blank';
// Push the new message into Cloud Firestore using the Firebase Admin SDK.
const writeResult = await admin.firestore().collection('messages').add({inputcode: inputcode});
// Send back a message that we've succesfully written the message
res.json({result: `Message with ID: ${writeResult.id} added.`});
});
exports.makeUppercase = functions.firestore.document('/messages/{documentId}')
.onCreate((snap, context) => {
// Grab the current value of what was written to Cloud Firestore.
const inputcode = snap.data().inputcode;
// Access the parameter `{documentId}` with `context.params`
functions.logger.log('Uppercasing', context.params.documentId, inputcode);
const areacode = inputcode.toUpperCase();
const written = new Date();
return snap.ref.set({written, areacode}, {merge: true});
});
I'm using the local firebase emulator to do this test, by the way.
This is the new version, ony changing 'messages' to 'vvvv' in two places.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.addMessage = functions.https.onRequest(async (req, res) => {
// Grab the location parameter.
const inputcode = req.query.code || 'blank';
// Push the new message into Cloud Firestore using the Firebase Admin SDK.
const writeResult = await admin.firestore().collection('vvvvv').add({inputcode: inputcode});
// Send back a message that we've succesfully written the message
res.json({result: `Message with ID: ${writeResult.id} added.`});
});
exports.makeUppercase = functions.firestore.document('/vvvvv/{documentId}')
.onCreate((snap, context) => {
// Grab the current value of what was written to Cloud Firestore.
const inputcode = snap.data().inputcode;
// Access the parameter `{documentId}` with `context.params`
functions.logger.log('Uppercasing', context.params.documentId, inputcode);
const areacode = inputcode.toUpperCase();
const written = new Date();
return snap.ref.set({written, areacode}, {merge: true});
});
OK. Doug, your suggestion sank in after an hour or so! I've restarted everything and think that I understand. If I change the name in those two places, without restarting, the collection.add function takes place and I can see the record in the new collection, but the onCreate event didn't fire. I had to restart the whole service to restart buth parts. I was getting confused because one part was working and not the other. Thanks for your patience.

How to retrieve data from Firebase using DialogFlow Inline Editor

I am pretty new to DialogFlow. I am wondering how can I retrieve data from Firebase through the Inline Editor of DialogFlow. Hope you can help me!
Thats how you can communicate with firebase from dialogflow
const functions = require('firebase-functions');
const firebaseAdmin = require('firebase-admin');
const DialogflowApp = require('actions-on-google').DialogflowApp;
Initialize Firebase Admin SDK.
firebaseAdmin.initializeApp(functions.config().firebase);
Interaction with firebase Collection users in fulfillment function
let userId = app.getUser().userId;
admin.firestore().collection('users').where('userId', '==', userId).limit(1).get()
.then(snapshot => {
let user = snapshot.docs[0]
if (!user) {
// If user is not in DB, its their first time, Welcome them!
app.ask('Welcome to my app for the first time!');
// Add the user to DB
firebaseAdmin.firestore().collection('users').add({
userId: userId
}).then(ref => {
console.log('Added document with ID: ', ref.id);
});
} else {
// User in DB
app.ask('Welcome back!')
}
});
}
// Map function hanlder to Dialogflow's welcome intent action 'input.welcome'
const actionMap = new Map('input.welcome', start)
app.handleRequest(actionMap);

Categories

Resources