I've got a react component that allows users to unsubscribe from an email, and there's a hash being passed along with the unsubscribe link so we know what mail item the request is associated with. Unfortunately the hash sometimes has some URL-specific characters in it, like + and /. Right now I'm doing something like this to get the data from the hash to pass to the unsubscribe service:
const query = new URLSearchParams(useLocation().search);
const campaignId = query.get('campaign') ?? '';
the problem is that when I pass the campaign in to the unsubscribe, and (for example) the campaig hash has a + in it, that gets converted to a space.
Is there a better way to get this string, or a way to "un-encode" it?
I ended up doing something fairly inelegant-- but it works. I used the decodeURIComponent() as suggested by #ofri in the comments above, but the spaces were not being converted back to +. So this is what I came up with:
const query = new URLSearchParams(useLocation().search);
const campaignId = query.get('campaignId') ?? '';
// then when we create the axios payload:
campaignId : decodeURIComponent(campaignId.replace(/ /g, '+'))
Related
I am trying to read data from firebase that is saved by childByAutoId(). I can successfully read the top half, but the reads what the childByAutoId() is. for example.
and in my firebase functions is
the logger -- uid is BoSwank... is correct, however on the line below for
logger -- workerId is -MBauxL.... is incorrect. That is the value of the childByAutoID() and it should be hkKplzF...
How I am trying to read this data is below.
exports.observeNotifications = functions.database.ref('/notifications/{cardUID}/{workerId}').onCreate((snapshot, context) => {
var uid = context.params.cardUID;
var workerId = context.params.workerId;
console.log('LOGGER --- uid is ' + uid);
console.log('LOGGER --- workerId is ' + workerId)
})
I thought changing
/notifications/{cardUID}/{workerId} to /notifications/{cardUID}/{cardUID/workerId}
and then changing
var workerId = context.params.workerId;
to
var workerId = context.params.cardUID.workerId;
would do the trick but it does not.
With Cloud Functions database triggers, the wildcards in the path only match the names of nodes. They never match the values of any children. What you are seeing right now is the expected behavior, and there's no way to change it.
If you want the value of children under the location that was matched in the path, you're going to have to reach into it using the snapshot parameter that was passed to the function. It is a DataSnapshot object, and contains all of the values of all of the children under the location that was matched in the path.
In your case, the value of workerId is going to be found like this:
const workerId = snapshot.val().workerId
I suggest reading over the documentation for more complete information about how database triggers work.
Problem
I want to push a new path as an addition to the URI where search queries are set.
Example:
Current location: https://example.com/foo?bar=123&foobar=123
When I call history.push('newPath') I will end up with https://example.com/newPath. What I want to get, however, is https://example.com/foo/newPath.
One solution would be to call history.push('foo/newPath') or if I would save the current path and add the wanted path (newPath) on top, but I was hoping that history.push might have a way to handle this?
I want to push a new path as an addition to the URI where search
queries are set.
To change/append the path you can use URL which won't affect your query parameters.
// maybe from window.location.href?
const href = 'https://example.com/foo?bar=123&foobar=12'
let url = new URL(href)
url.pathname = url.pathname + '/newPath'
console.log(url) // https://example.com/foo/newPath?bar=123&foobar=12
Problem
In a social media app I am making with react native and firebase, I am trying to grab the number of comments a post has using the snapshot function of a variable I have saved on my servers, then I am going to add one to this variable when a user adds a new comment. My code to do so is right here:
firebase.database().ref('posts').child(this.state.passKey).update({
comments: firebase.database().ref('posts/'+this.state.passKey).child('comments').snapshot.val() + 1
})
When I actually run this code, I get an error saying:
Reference.child failed: First argument was an invalid path = "undefined".
Paths must be non-empty strings and can't contain ".","#","$","[", or "["
At first I thought this might be that the "this.state.passKey" wasn't actually passing the key, but putting in a key I copied from the server didn't fix the problem.
My Server
-
To get the comments of particular post you should do like this
let postId='someId'
postRef=`/posts/${postId}`
firebase.database().ref(postRef).once("value", dataSnapshot => {
comment=dataSnapshot.val().comments
});
It looks like you're expecting this bit of code to query the database:
firebase.database().ref('posts/'+this.state.passKey).child('comments').snapshot.val() + 1
Unfortunately, it doesn't work that way. There's no snapshot property on a database Reference object returned by child() or ref().
Instead, you'll need to query the database at that reference, then when you're called back with its value, you can apply it elsewhere.
var ref = firebase.database().ref('posts/'+this.state.passKey+'/comments')
ref.once('value', function(snapshot) {
// use the snapshot here
})
I am trying to log in to a website like for this example csgolounge which requires the steam login authentication using nodejs.
Even thought I have tried a few things none of them came even close to working, so there is no point of me including the code here.
I was wondering if there is any way of doing this.
EDIT: I think I write my question incorrectly as I want the node application to login to csgolounge using steam and NOT have a website that is 'like' csgolounge with the login option.
To answer your question, yes. There is a way of doing this.
The first thing you'll need to do is get a steam api key which you can do by heading over here. Then as steam says:
Just download an OpenID library for your language and platform of choice and use http://steamcommunity.com/openid as the provider. The returned Claimed ID will contain the user's 64-bit SteamID. The Claimed ID format is: http://steamcommunity.com/openid/id/
If you're set on using Node.JS I suggest checking out node-jsonwebtoken or passport-openidconnect. If you choose to go with passport, someone has already developed a "strategy" for including steam. Check that out here.
I have the same issue, i dont know if it helps you, but i wrote some methods to get user steamID, then u can use it to get user info with this method. I did it only having info how to do it with PHP - thats why i wanted to rewrite it on js.
1) method to build link
const http_build_query = (obj) => {
let str = ""
for (const key in obj) {
const value = obj[key];
str += `${key}=${value}&`;
}
return str;
}
2) method which returns you link where you shoud go to login with steam (you also can use in in )
const genUrl = (urlToReturnTo) => {
const params = {
'openid.ns' : 'http://specs.openid.net/auth/2.0',
'openid.mode' : 'checkid_setup',
'openid.return_to' : urlToReturnTo,
'openid.realm' : 'http://localhost:8080',
'openid.identity' : 'http://specs.openid.net/auth/2.0/identifier_select',
'openid.claimed_id' : 'http://specs.openid.net/auth/2.0/identifier_select',
};
const url = `${STEAM_LOGIN}?${http_build_query(params)}`
return url;
};
Also in method genUrl you need to pass as a param url where you want to be redirected after login. If login is successful you will be redirected to your url and will have some params in url it will look like "http://yoururl?here_is_params"
and you need to get some how [here_is_params] from url i used this:
const search = location.search.substring(1);
const urlObj = JSON.parse('{"' + decodeURI(search).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}')
So after that you will have an object with query params
3) Now all you need its to get steamID from this object:
const getUserId = (response) =>
{
const str = response["openid.claimed_id"];
const res = decodeURIComponent(str)
const propsArr = res.split("\/");
console.log(propsArr);
return propsArr[propsArr.length-1];
}
const userId = getUserId(urlObj)
4) Now you have userId and all you need its to send request with fetch or axios. it will return you an JSON OBJ with user data
http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key={apiKey}&steamids=${userId}
I'm looking for a good way to build urlStream using RxJS that takes multiple parameters.
var searchStream = new Rx.ReplaySubject(1);
var pageStream = new Rx.ReplaySubject(1);
var urlStream = new Rx.Observable.create((observer) => {
//What goes here?
//Should output something like http://apiurl.com?page=page&search=search
});
My instinct is to use Rx.Observable.merge(searchStream, pageStream); but after you do that you don't know which one is which parameter.
With the searchStream subject it allows me to use the subject multiple places in application to searchStream.onNext("my search") and have it trigger a refersh of the data. I've seen plenty of examples that use one url parameter but have yet to see an example that using multiple input streams.
How about:
var searchStream = ...
var pageStream = ...
var urlStream = Rx.Observable.combineLatest(searchStream, pageStream, (search, page) => {
return baseUrl + `?search=${search}&page=${page}`;
})
.shareReplay(1);
I would suggest that you not use Subjects directly when creating streams. Likely whatever is triggering the parameter change could just as easily be wrapped in an Observable instead.
For instance your search would likely be attached to some text box whose change event could be wrapped in a fromEvent
//This would create a stream that waits until the user has stopped
//typing for half a second before sending a request to update.
var searchStream = Rx.Observable.fromEvent($textbox, 'keyup')
.map(e => e.target.value)
.debounce(500);