How to get image URL without downloading? - javascript

There is a way to download, like below:
const image = await storage.child('img/'+usrname+'.jpg').getDownloadURL();
this.setState({image});
But What I want?
I want to get image as directly, like below:
https://firebase.google.com/storage/img/#david.jpg
https://firebase.google.com/storage/img/#jack.jpg
https://firebase.google.com/storage/img/#harry.jpg
Why I want like above.
because I have a list of users with name, phone and username, there I saved the image of every user by his/her username(username.jpg).
Now when I list the users I used a loop, like below:
users = [];
for(let i=0; i<usersData.length; i++){
const user = {
name: usersData[i].name,
phone: usersData[i].phone,
image: 'https://firebase.google.com/storage/img/'+usersData[i].username
}
users.push(user);
}
Note:
Dont be confused about url (https://firebase.google.com/storage/) ,I just gave an example.

I don't think Firebase gives us direct link as this
https://firebase.google.com/storage/img/#david.jpg
https://firebase.google.com/storage/img/#jack.jpg
Because it does not include any project specific data (Like your storage bucket name, your project ID, token for authentication and so) in this form of URL. And if you think you will find that it increases the security to your files in the storage, as no-one can make a random guess to get the access to your storage data .
In your case you might have to go somewhat in this direction.
Here, we are first iterating through the userData list to aggregate all the promises using Promise.all after that in the then we get the list of resolved promises inside which our url for the image exists.
In last we set various property on our user object and push it to the users array.
users = [];
userPromise = Promise.all(
userData.map(data =>
firebase.storage()
.refFromURL('gs://<your bucket here>/img')
.child( data.username+'.jpg' ).getDownloadURL()
)
)
.then(ImgUrls =>{
ImgUrls.map((ImgUrl,i) => {
console.log(ImgUrl)
const user ={
name:userData[i],
phone: usersData[i].phone,
image: ImgUrl
}
console.log(user);
users.push(user);
});
});
console.log(users);

Related

How can I map a JavaScript array to save every element to a database and return the saved item?

I am working on an application that allows users to send an email to a list of contacts. Here is how the function that I am having trouble with works:
The email content is saved to the database.
The array of contacts is mapped. For every contact...
...The contact is saved to the database.
...An email is sent to the contact with a URL containing the email id and their contact id that the database generated.
...The saved recipient should be but is not currently returned.
The array of saved contacts which are currently just empty objects :( is returned to the front end.
An empty object is returned for every contact instead of the actual contact, which is weird because I can console.log() the object within the map, and the contact's information is being sent in the email, so it definitely exists at some point.
Here is the code:
const postOne = async (req, res) => {
const db = req.app.get("db");
const { adviceRequest, recipients } = req.body;
// ( Validation goes here )
try {
// Save the request.
let [savedRequest] = await db.requests.postOne([
adviceRequest,
req.session.user.id,
]);
// For every recipient...
let savedRecipients = recipients.map(async (person) => {
// ...Save them to the database.
let [savedRecipient] = await db.responses.postOne([
savedRequest.request_id,
person.email,
person.name,
req.session.user.id,
]);
// At this point, console.log(savedRecipient) shows the actual recipient, so it works.
// ...Send them an email.
await sendMail(savedRecipient, savedRequest);
// ...Then add the saved recipient to the array that .map() generates.
return savedRecipient;
});
// Send the request and the array of people back.
return res.status(200).json([savedRequest, savedRecipients]);
} catch (err) {
return res.status(500).json(err);
}
},
The thing is, the array that the .map() returns is an array of empty objects. I do not know why. Inside the .map(), savedRecipient is defined as it should be, and the information there is successfully being used to send the required information via email. But what is returned to the front end is an array of empty objects--one for each contact.
If someone could tell me what I am doing wrong, I would appreciate it!
You can try for loop to use async and await.
let savedRecipients = recipients.map(async (person) =>
Property savedRecipients here is an array of promises. Try to resolve this promises, like this:
const savedRecipientsData = await Promise.all(savedRecipients);

retrieve all customers email address stripe node.js

I have this function that tries to retrieve all the customer's emails in stripe:
const customers = await stripe.customers.list({
});
var customerEmail = customers.data[0].email;
console.log(customerEmail)
I am trying to return all the email addresses of the users from stripe. the problem is, when I log it, it only returns the first one, due to teh fact that I have data[0]. I need all of them, but i can't put it in a loop because what am i looping through. is there any way to do this properly?
The data property you are indexing is an array you can iterate through[1].
const customers = await stripe.customers.list({});
customers.data.forEach(customer => {
console.log(customer.email);
});
[1] https://stripe.com/docs/api/customers/list

Saving a field from firestore that is an array

I am currently working on a mobile app on React and I am having trouble understanding how to save a field from fire store that is an array.
Since I can't post images my database structure is all strings such as username, first name, etc but I have a field called follow list that is an array.
What I want to do is save the usernames from the following list into an array to later search fire store for the username's in the array, this is basically what I want to do so I can render my app's social Feed. I do know that I can probably create another subcollection and write something familiar to what I did to search for users but that was a QuerySnapShot which was overall documents not a specific one and I also know firebase creates an ID for arrays and it increases as the array gets bigger.
I do not want to end up making two more subcollections one for followers and following which I think not ideal right? My current approach is this
export const fetchUserFollowing = async (username) => {
const ref = firebase.firestore().collection('users').doc(username)
let results = []
ref
.get()
.then( doc => {
let data = doc.data()
results = data
})
.catch((err) => {
return 'an error has occurred ', err
})
}
From what I understand is that a DocumentSnapShot .get() function returns an object but what I want is to store follow list into results and then return that but I am not sure how to manipulate the object return to just give me follow List which is an array
https://rnfirebase.io/docs/v5.x.x/firestore/reference/DocumentSnapshot
link to docs

delete incoming write event after calculations in firebase functions

I have an app that uses firebase, the whole stack pretty much, functions, database, storage, auth, messaging, the whole 9. I want to keep the client end very lightweight. So if a user comments on a post and "tags" another user, let's say using the typical "#username" style tagging, I moved all of the heavy lifting to the firebase functions. That way the client doesn't have to figure out the user ID based on the username, and do everything else. It is setup using triggers, so when the above scenario happens I write to a "table" called "create_notifications" with some data like
{
type: "comment",
post_id: postID,
from: user.getUid(),
comment_id: newCommentKey,
to: taggedUser
}
Where the taggedUser is the username, the postID is the active post, the newCommentKey is retrieved from .push() on the comments db reference, and the user.getUid() is from the firebase auth class.
Now in my firebase functions I have a "onWrite" trigger for that specific table that gets all of the relevant information and sends out a notification to the poster of the post with all the relevant details. All of that is complete, what I am trying to figure out is... how do I delete the incoming event, that way I don't need any sort of cron jobs to clear out this table. I can just grab the event, do my needed calculations and data gathering, send the message, then delete the incoming event so it never even really exists in the database except for the small amount of time it took to gather the data.
A simplified sample of the firebase functions trigger is...
exports.createNotification = functions.database.ref("/create_notifications/{notification_id}").onWrite(event => {
const from = event.data.val().from;
const toName = event.data.val().to;
const notificationType = event.data.val().type;
const post_id = event.data.val().post_id;
var comment_id, commentReference;
if(notificationType == "comment") {
comment_id = event.data.val().comment_id;
}
const toUser = admin.database().ref(`users`).orderByChild("username").equalTo(toName).once('value');
const fromUser = admin.database().ref(`/users/${from}`).once('value');
const referencePost = admin.database().ref(`posts/${post_id}`).once('value');
return Promise.all([toUser, fromUser, referencePost]).then(results => {
const toUserRef = results[0];
const fromUserRef = results[1];
const postRef = results[2];
var newNotification = {
type: notificationType,
post_id: post_id,
from: from,
sent: false,
create_on: Date.now()
}
if(notificationType == "comment") {
newNotification.comment_id = comment_id;
}
return admin.database().ref(`/user_notifications/${toUserRef.key}`).push().set(newNotification).then(() => {
//NEED TO DELETE THE INCOMING "event" HERE TO KEEP DB CLEAN
});
})
}
So in that function in the final "return" of it, after it writes the finalized data to the "/user_notifications" table, I need to delete the event that started the whole thing. Does anyone know how to do that? Thank you.
First off, use .onCreate instead of .onWrite. You only need to read each child when they are first written, so this will avoid undesirable side effects. See the documentation here for more information on the available triggers.
event.data.ref() holds the reference where the event occurred. You can call remove() on the reference to delete it:
return event.data.ref().remove()
The simplest way to achieve this is through calling the remove() function offered by the admin sdk,
you could get the reference to the notification_id through the event, i.e event.params.notification_id then remove it when need be with admin.database().ref('pass in the path').remove(); and you are good to go.
For newer versions of Firebase, use:
return change.after.ref.remove()

#ionic change the data key in firebase

I'm trying to update/add data on firebase. I used the Facebook login and I want to use the UserID as a key for the new data aded.
(check pict below)
The userID that I want to use it:
I want to replace that key with the userID:
fblogin(){
this.facebook.login(['email'])
.then(res=> {
const fc = firebase.auth.FacebookAuthProvider.credential(res.authResponse.accessToken);
firebase.auth().signInWithCredential(fc)
.then(fs => {
this.facebook.api('me?fields=id,name,email,first_name,picture.width(720).height(720).as(picture_large)', []).then(profile => {
this.newuser = {name: profile['first_name'] ,email: profile['email'],picture: profile['picture_large']['data']['url'],phone:''}
this.navCtrl.push(HomePage);
console.log(fs.uid);
this.db.list('/users/'+ fs.uid).update(this.newuser);
});
I got this error in compilation:
supplied parameters do not matchany signature of call target
In this line: this.db.list('/users/'+ fs.uid).update(this.newuser);
Any help?
The FB error looks correct. You cant update on the uid as the user has been saved with a unique FB id
You do not show the code that created the users record in the database, but what i think you want to do is set and object when you first save the users record. However this could be an issue because the user could be saved before the return of the uid. I cant tell with your code snippet. Regardless, I will write the code that i think will work if the users/ record is created at the time that of registration.
The service
async signupUser(email: string, password: string) {
try {
const result = await this.afA.auth.createUserWithEmailAndPassword(email, password);
return result;
} catch (err) {
console.log('error', err);
}
}
So this initially creates a user without facebook, The key here is that the users FB uid was created and is held in the returned result
The component
this.authData.signupUser(email,password).then(userData => {
console.log(userData) // <- this is result
}
Then we create a record in FB with the uid returned
this.db.object(`users/${userData.uid}/`).set(data);
.set(data) is whatever data you want to save in the users/uid namespace.
So basically you need to create that user table with its uid namespace when the user first registers. Then you can update the user with the uid returned from the facebook fs.uid
With your current code you could find the user based on the email ( because the email should be unique to all users) and then update ...
with lodash is it just
let foundUser = find(this.db.list('users'),{ 'email' : fs.email }
// and then update based on the object key
this.db.list('/users/'+ Object.keys(foundUser)).update(this.newuser);
i fixed the problem by using:
this.db.object('/users/'+ fs.uid).update(this.newuser);
instead of :
this.db.list('/users/'+ fs.uid).update(this.newuser);
And it works correctly !
Thanks all for help.

Categories

Resources