I am having problems to implement notifications using firebase. The click event does not work. I am using the HTTP 1 version sending the bearer token.
{
"message": {
"token": "8888****usertoken****8888",
"notification": {
"title": "Background Message Title",
"body": "Background message body"
},
"webpush": {
"fcm_options": {
"link": "https://dummypage.com"
}
}
}
}
I have also tried click_action, action, and many other variations that just did not work.
I am using version 8.0.0
According to the documentation found on this link https://firebase.google.com/docs/cloud-messaging/js/send-multiple, I should be able to implement it using fcm_options.
I tried a workaround implementing messaging.onBackgroundMessage, but when I implement this method and use self.registration.showNotification, the notification is displayed twice. one triggered by the browse and the other by this code.
Registering self.addEventListener('notificationclick' only seems to work when I implement onBackgroundMessage.
I followed the documentation, but it is driving me crazy.
This is my service worker code:
importScripts('https://www.gstatic.com/firebasejs/8.0.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.0.0/firebase-messaging.js');
var firebaseConfig = {
apiKey: "xxxxxx",
authDomain: "xxxxxxxx.firebaseapp.com",
databaseURL: "https://xxxxxx.firebaseio.com",
projectId: "xxx-xxx",
storageBucket: "xxx-xxx.appspot.com",
messagingSenderId: "222222222",
appId: "1:2222:web:22222"
};
console.log("fire base messaging")
firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();
messaging.onBackgroundMessage(function (payload) {
console.log("onBackgroundMessage", payload)
var dataFromServer = payload.notification;
var notificationTitle = dataFromServer.title;
var notificationOptions = {
body: dataFromServer.body,
image: dataFromServer.image,
data: {
url: "https://google.com"
}
};
return self.registration.showNotification(notificationTitle,
notificationOptions);
});
////Code for adding event on click of notification
self.addEventListener('notificationclick', function (event) {
console.log("notificationclick", event)
var urlToRedirect = event.notification.data.url;
event.notification.close();
event.waitUntil(self.clients.openWindow(urlToRedirect));
});
Turns out I was passing an entire URL to webpush.fcm_options.link = "https://google.com", all I had to do was to pass only the relative path like webpush.fcm_options.link = "/mypage".
So the request to send would be like this:
{
"message": {
"token": "8888****usertoken****8888",
"notification": {
"title": "Background Message Title",
"body": "Background message body"
},
"webpush": {
"fcm_options": {
"link": "/mypage"
}
}
}
}
I don't see in the docs say it is only the relative path. It even states that HTTPS is required. I spent a few hours on this one, I hope it helps somebody else.
https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages#WebpushFcmOptions
I was having the same issue. I added a notificationclick event handler. You can use the data param in the notification event to open a new tab or focus an already opened one.
The code you already have is fine, now adding the listener looks like this:
// messaging.onBackgroundMessage(...);
function handleClick (event) {
event.notification.close();
// Open the url you set on notification.data
clients.openWindow(event.notification.data.url)
}
self.addEventListener('notificationclick', handleClick);
This resources might be helpful
similar question on SO
showNotification
notificationclick
Notifications are working using legacy API but unfortunately clicking the notification still does nothing. This is my code for sending the notification.
var notification = {
'title': title,
'body': body,
'icon': 'hourglass.png',
'click_action': router.resolve(route).href
}
var payload = {
'notification': notification,
// 'webpush': {
// 'fcm_options': {
// 'link': '/' + router.resolve(route).href
// }
// }
}
if(registrationIds.length == 1) {
payload['to'] = registrationIds[0]
} else if( registrationIds.length > 1){
payload['registration_ids'] = registrationIds
}
return new Promise((resolve, reject) => {
if (registrationIds.length) {
fetch('https://fcm.googleapis.com/fcm/send', {
'method': 'POST',
'headers': {
'Authorization': 'key=' + key,
'Content-Type': 'application/json'
},
'body': JSON.stringify(payload)
}).then(function(response) {
resolve(true)
}).catch(function(error) {
console.error('sendNotification error', error);
reject(false)
})
}
else {
console.log('This timer has no registered clients.')
reject(false)
}
})
Edit: I think most of my confusion stemmed from finding examples with the V1 API and mixing them up with the legacy API. I needed click_action instead of the fcm_options.link in the payload. I updated my code and is now working as intended.
Related
I'm creating a feedback bot that will send out direct messages to individuals as soon as an event on their calendar ends. For this, i've developed most of the code using appscript. I got the calendar api trigger working and i can get the same functionality working using /slash commands, but what i want is to automate this process, in that, the bot will automatically send out the message on the calendar trigger.
I'm not sure how to get this to work as i didn't find any examples or documentation to do the same. I read somewhere that google chat api doesn't allow proactively sending messages directly to users, but i have seen examples of it working.
When i try to send the message using the appscript chat api sdk, it doesn't send any message, although the flow runs successfully as i can see from the logs.
When i try using google chat rest api i'm facing errors when trying to send out a message.
The error for rest api, the error i'm seeing is :
12:10:32 PM Error
Exception: Request failed for https://chat.googleapis.com returned code 400. Truncated server response: {
"error": {
"code": 400,
"message": "Message cannot have cards for requests carrying human credentials.",
"status": "INVALID_ARGUMEN... (use muteHttpExceptions option to examine full response)
showFeedbackMessageRest # feedback.gs:105
pubsub_subscribe # feedback.gs:42
the code for the pub/sub subscriber is :
function pubsub_subscribe(e){
var service = getService();
if (!service.hasAccess()) {
var authorizationUrl = service.getAuthorizationUrl();
console.log('Authorize PubSub Service First : !!!!!!!!!!!!!!!!');
console.log(authorizationUrl);
showFeedbackMessageRest(e, {'auth_url' : authorizationUrl});
}else{
console.log('PubSub has Access!')
var project_id = get_property('PROJECT_ID');
// var topic = get_property('TOPIC');
var subscriber = get_property('SUBSCRIBER');
var url = `https://pubsub.googleapis.com/v1/projects/${project_id}/subscriptions/${subscriber}:pull`
var body = {
returnImmediately: true,
maxMessages: 1
}
var response = UrlFetchApp.fetch(url, {
method: "POST",
contentType: 'application/json',
muteHttpExceptions: true,
payload: JSON.stringify(body),
headers: {
Authorization: 'Bearer ' + getService().getAccessToken()
}
});
var result = JSON.parse(response.getContentText());
console.log(JSON.stringify(result));
console.log(Object.keys(result).length);
if (Object.keys(result).length > 0){
var decoded = Utilities.base64Decode(result.receivedMessages[0].message.data);
var event_details = JSON.parse(Utilities.newBlob(decoded).getDataAsString());
var popup_obj = {
'summary' : event_details.EventTitle
};
console.log(popup_obj);
return showFeedbackMessageRest(e, popup_obj);
}else{
console.log('No Recent Messages!');
}
}
}
and the code to send the message using chat rest api is :
function showFeedbackMessageRest(e, event) {
var chat_service = getChatService()
var message = {};
if (!chat_service.hasAccess()) {
var authorizationUrl = chat_service.getAuthorizationUrl();
console.log('Authorize Chat Service First : !!!!!!!!!!!!!!!!');
console.log(authorizationUrl);
}else{
console.log('Chat App Has Access!');
if (event.hasOwnProperty('summary')){
message = {
"text" : `Provide Feedback For : ${event.summary}`
};
}else{
message = {
"cards_v2": [{
"card_id": "feedbackMessage",
"card": {
"header": {
"title": `Provide Feedback For : ${event.summary}`,
"subtitle": `This meeting just ended, provide feedback for the organizers to organize meetings more effectively.`,
"imageUrl": "https://raw.githubusercontent.com/google/material-design-icons/master/png/social/poll/materialicons/24dp/2x/baseline_poll_black_24dp.png",
"imageType": "CIRCLE"
},
"sections": [
{
"widgets": [
{
"buttonList": {
"buttons": [
{
"text": "Give Feedback",
"onClick": {
"action": {
"function": "promptQuestion",
"interaction": "OPEN_DIALOG"
}
}
}
]
}
}
]
}
]
}
}]
};
}
}
var url = 'https://chat.googleapis.com/v1/' + `${user_dm_space_name}` + '/messages';
UrlFetchApp.fetch(url, {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + chat_service.getAccessToken() },
contentType: 'application/json',
payload: JSON.stringify(message),
});
}
I even tried to send a simple text message as according to the error, the cards are not allowed to be sent, but i'm getting this error :
12:30:36 PM Error
Exception: Request failed for https://chat.googleapis.com returned code 403. Truncated server response: {
"error": {
"code": 403,
"message": "This API is not accessible for external HTTP caller.",
"status": "PERMISSION_DENIED"
}
}
(use muteHttpExceptions option to examine full response)
showFeedbackMessageRest # feedback.gs:105
pubsub_subscribe # feedback.gs:42
I'm trying the Wikipedia client login flow depicted in the API:Login docs, but something wrong happens:
1) I correctly get a token raised with the HTTP GET https://en.wikipedia.org/w/api.php?action=query&meta=tokens&type=login&format=json
and I get a valid logintoken string.
2.1) I then try the clientlogin like:
HTTP POST /w/api.php?action=clientlogin&format=json&lgname=xxxx&lgtoken=xxxx%2B%5C
and the POST BODY was
{
"lgpassword" : "xxxxx",
"lgtoken" : "xxxxx"
}
But I get an error:
{
"error": {
"code": "notoken",
"info": "The \"token\" parameter must be set."
},
"servedby": "mw1228"
}
If I try to change lgtoken to token I get the same result.
2.2) I have then tried the old method i.e. action=login and passing the body, but it does not work, since it gives me back another login token: HTTP POST https://en.wikipedia.org/w/api.php?action=login&format=json&lgname=xxxx
and the same POST BODY
I then get
{
"warnings": {}
},
"login": {
"result": "NeedToken",
"token": "xxxxx+\\"
}
where the docs here states that
NeedToken if the lgtoken parameter was not provided or no session was active (e.g. your cookie handling is broken).
but I have passed the lgtoken in the json body as showed.
I'm using Node.js and the built-in http module, that is supposed to pass and keep session Cookies in the right way (with other api it works ok).
I have found a similar issue on a the LrMediaWiki client here.
[UPDATE]
This is my current implementation:
Wikipedia.prototype.loginUser = function (username, password) {
var self = this;
return new Promise((resolve, reject) => {
var cookies = self.cookies({});
var headers = {
'Cookie': cookies.join(';'),
'Accept': '*/*',
'User-Agent': self.browser.userAgent()
};
// fetch login token
self.api.RequestGetP('/w/api.php', headers, {
action: 'query',
meta: 'tokens',
type: 'login',
format: 'json'
})
.then(response => { // success
if (response.query && response.query.tokens && response.query.tokens['logintoken']) {
self.login.logintoken = response.query.tokens['logintoken'];
self.logger.info("Wikipedia.login token:%s", self.login);
return self.api.RequestPostP('/w/api.php', headers, {
action: 'login',
format: 'json',
lgname: username
},
{
lgpassword: password,
lgtoken: self.login.logintoken
});
} else {
var error = new Error('no logintoken');
return reject(error);
}
})
.then(response => { // success
return resolve(response);
})
.catch(error => { // error
self.logger.error("Wikipedia.login error%s\n%#", error.message, error.stack);
return reject(error);
});
});
}//loginUser
where this.api is a simple wrapper of the Node.js http, the source code is available here and the api signatures are like:
Promise:API.RequestGetP(url,headers,querystring)
Promise:API.RequestPostP(url,headers,querystring,body)
If the currently accepted answer isn't working for someone, the following method will definitely work. I've used the axios library to send requests. Any library can be used but the key lies in formatting the body and headers correctly.
let url = "https://test.wikipedia.org/w/api.php";
let params = {
action: "query",
meta: "tokens",
type: "login",
format: "json"
};
axios.get(url, { params: params }).then(resp => {
let loginToken = resp.data.query.tokens.logintoken
let cookie = resp.headers["set-cookie"].join(';');
let body = {
action: 'login',
lgname: 'user_name',
lgpassword: 'password',
lgtoken: loginToken,
format: 'json'
}
let bodyData = new URLSearchParams(body).toString();
axios.post(url, bodyData, {
headers: {
Cookie: cookie,
}
}).then(resp => {
// You're now logged in!
// You'll have to add the following cookie in the headers again for any further requests that you might make
let cookie = resp.headers["set-cookie"].join(';')
console.log(resp.data)
})
})
And you should be seeing a response like
{
login: { result: 'Success', lguserid: 0000000, lgusername: 'Username' }
}
The second post request was where I got stuck for several hours, trying to figure out what was wrong. You need to send the data in an encoded form by using an API like URLSearchParams, or by just typing up the body as a string manually yourself.
I think from what you are saying you have lgtoken and lgname in the URL you are using, and then lgpassword and lgtoken (again!) in a JSON-encoded POST body.
This is not how the Mediawiki API works.
You submit it all as POST parameters. JSON is never involved, except when you ask for the result to come back in that format. I can't help you fix your code as you don't provide it, but that's what you need to do. (If you edit your question with your code, I'll do my best to help you.)
After seeing your code, I'll presume (without knowing the detail of your code) that you want something like this:
return self.api.RequestPostP('/w/api.php', headers, {
action: 'login',
format: 'json',
lgname: username,
lgpassword: password,
lgtoken: self.login.logintoken
});
I am new to Google Chrome Push notifications and I was just reading some questions and answers here, on stackoverflow and I have ended with this easy push notification javascript.
navigator.serviceWorker.register('sw.js');
function notify() {
Notification.requestPermission(function(result) {
if (result === 'granted') {
navigator.serviceWorker.ready.then(function(registration) {
registration.showNotification('test notification', {
body: 'Hey I am test!',
icon: 'image.png',
});
});
}
});
}
Its just simple notification, but I need open a new window with other webpage after click on notification.
I know it is possible, but I cant find examples using "serviceWorker" syntax.
Please help. Thanks.
I am guessing you are in a Service Worker context, because that's where Push Notifications are received. So you have the self object to add a event listener to, that will react to a click on the notification.
(Place this code in your sw.js file, which is your Service Worker script.)
self.addEventListener('notificationclick', function(event) {
let url = 'https://example.com/some-path/';
event.notification.close(); // Android needs explicit close.
event.waitUntil(
clients.matchAll({type: 'window'}).then( windowClients => {
// Check if there is already a window/tab open with the target URL
for (var i = 0; i < windowClients.length; i++) {
var client = windowClients[i];
// If so, just focus it.
if (client.url === url && 'focus' in client) {
return client.focus();
}
}
// If not, then open the target URL in a new window/tab.
if (clients.openWindow) {
return clients.openWindow(url);
}
})
);
});
If you want to open website with dynamic URL received from FCM push notification or any other web push notification then
BELOW IS AN EXAMPLE OF SERVICE WORKER USED FOR FCM PUSH NOTIFICATION
messaging.setBackgroundMessageHandler(function(payload) {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
// Customize notification here
var notificationTitle = payload.data.title; //or payload.notification or whatever your payload is
var notificationOptions = {
body: payload.data.body,
icon: payload.data.icon,
data: { url:payload.data.click_action }, //the url which we gonna use later
actions: [{action: "open_url", title: "Read Now"}]
};
return self.registration.showNotification(notificationTitle,
notificationOptions);
});
and handle click event with below code
self.addEventListener('notificationclick', function(event) {
switch(event.action){
case 'open_url':
clients.openWindow(event.notification.data.url); //which we got from above
break;
case 'any_other_action':
clients.openWindow("https://www.example.com");
break;
}
}
, false);
Hope it helps!
(This code refers to firebase messaging) I was also searching for a soluting and the answer was very easy, but there was no doc saying it clearly. You need to put "click_action" = "your url" inside the notification json. Here is an example:
notification: {
title: "Come",
icon: '../../../../assets/logo.png',
vibrate: [300,100,400,100,400,100,400],
body: "some text",
click_action : "your link"
}
Hope it helps.
{
"notification": {
"title": "Hey there",
"body": "Subscribe to might ghost hack youtube channel",
"click_action" : "http://localhost:4200"
},
"to":"YOUR_TOKEN"
}
This worked for me
"#angular/fire": "^6.1.5",
"firebase": "^7.0 || ^8.0"
I am trying to comment and rate a comment via API but the resource is always
canRate: false and canReply: false
I
I've tried through google javascript client and http get request, but nothing seems to be working.
$http.get('https://www.googleapis.com/youtube/v3/commentThreads', {
params: {
key: API_KEY,
part: 'snippet',
textFormat: 'plainText',
videoId: VIDEO_ID,
order: 'relevance'
}
}).success(function(response) {
$scope.comments = response.items;
$log.debug($scope.comments);
//var author = item.snippet.topLevelComment.snippet.authorDisplayName;
//var comment = item.snippet.topLevelComment.snippet.textDisplay;
//var nextToken = results.nextPageToken;
//var totalRep = item.snippet.totalReplyCount;
//var parent = item.snippet.topLevelComment.id;
})
.error(function(error) {
$log.error(error);
})
This is what I'm using, I can list them perfectly (even using v3/comments) but can't reply neither rate a comment, this is what I'm using
gapi.client.load('youtube', 'v3', function () {
$scope.selectedComment.snippet.viewerRating = 'like';
var request = gapi.client.youtube.commentThreads.update({
part: "snippet",
body: $scope.selectedComment
});
request.execute(function(response) {
$log.debug(response);
});
});
At the body part I've also tried this
body: {
id: $scope.selectedCommentId,
'snippet': {
'viewerRating': 'like'
}
}
But I get this error
404 The specified comment thread could not be found. Check the value
of the id property in
the request body to ensure that it is correct
You can replay the comment
POST https://www.googleapis.com/youtube/v3/comments?part=snippet&access_token={YOUR_API_KEY}
body
{
"snippet": {
"parentId": "parentCommentID",
"textOriginal": "yoursComment"
}
}
You can get more info here
https://developers.google.com/youtube/v3/docs/comments/insert#examples
I have reproduced my case with this jsbin http://emberjs.jsbin.com/xeninaceze/edit?js,output
Github API allows me to get the list of events by author:
API Link - api.github.com/users/:user/events
I can access to the commit message filtering the events “PushEvent”, and it s perfectly fine because i cam stream my latest commit message.
var gitactivitiesPromise = function() {
return new Ember.RSVP.Promise(function (resolve) {
Ember.$.ajax(eventsAct, {
success: function(events) {
var result = [];
events.filter(function(event) {
return event.type == 'PushEvent';
}).forEach(function(item){
item.payload.commits.map(function(commit){
result.push(store.createRecord('commit', {
message: commit.message,
}));
});
});
resolve(result);
},
error: function(reason) {
reject(reason);
}
});
});
};
The problem is that i want to stream beside the msg also his own url link. html_url
I need to know how i can tackle it? since the commit url links are not in the in the API Link
api.github.com/users/:user/events
But they are in the following api
api.github.com/repos/:user/repo/commits/branch
This makes bit more complicate to access to the latest commits url link html_url
This is a good example of what i am trying to do
http://zmoazeni.github.io/gitspective/#
It streams in the push events the latest commits message with links
It seems to me that all the relevant data is already there:
{
"id": "3414229549",
"type": "PushEvent",
"actor": {
...
"login": "paulirish"
},
"repo": {
...
"name": "GoogleChrome/devtools-docs"
},
"payload": {
...
"commits": [
{
...
"message": "fish shell. really liking it.",
"sha": "1f9740c9dd07f166cb4b92ad053b17dbc014145b"
},
...
You can access the author URL as actor and the repository as repo. With this it's easy to construct the relevant links:
...
.forEach(function(item) {
var repoUrl = 'https://github.com/' + item.repo.name;
var authorUrl = 'https://github.com/' + item.actor.login;
item.payload.commits.map(function(commit) {
result.push(store.createRecord('commit', {
authorUrl: authorUrl,
repositoryUrl: repoUrl,
commitUrl: repoUrl + '/commit/' + commit.sha,
message: commit.message
}));
});
})
...
Updated JSBin: http://emberjs.jsbin.com/feyedujulu/1/edit?js,output