I am trying to show the conversation between the two users even after the users logout and login. I mean when user1 logged out and again logged in, he should see the conversations made with the user2. I am using Ejabberd XMPP server and Strophe Js to retrive the messages.
As I found this strophe.mam.js plugin to do this but raising the error and cant get the messages.
Here is my code:
function onConnect(status)
{
// Functions runs while users trys to login to the XMPP server
var iq = null;
switch (status)
{
case Strophe.Status.CONNECTING:
log('Connecting.');
break;
case Strophe.Status.CONNFAIL:
log('Failed to connect.');
$('#connect').get(0).value = 'connect';
break;
case Strophe.Status.DISCONNECTING:
log('Disconnecting.');
break;
case Strophe.Status.DISCONNECTED:
log('Disconnected.');
$('#connect').get(0).value = 'connect';
break;
case Strophe.Status.CONNECTED:
log('Connected.');
connection.addHandler(onMessage, null, 'message', null, null, null);
connection.addHandler(onPresence, null, 'presence', null, null, null);
iq = $iq({type: 'get'}).c('query', {xmlns: 'jabber:iq:roster'});
connection.sendIQ(iq, onRoster);
break;
default:
break;
}
}
function onMessage(msg) {
debugger;
var fromJid = msg.getAttribute("from"),
bareFromJid = Strophe.getBareJidFromJid(fromJid),
type = msg.getAttribute("type"),
elems = msg.getElementsByTagName("body");
if (type == "chat" && elems.length > 0) {
var body = elems[0],
message = Strophe.getText(body);
showMessage(bareFromJid + ": " + message);
connection.mam.query("yashwanth#localhost", {
"with": bareFromJid,
onMessage: function(message) {
console.log("Message from " + bareFromJid,
": " + message);
return true;
},
onComplete: function(response) {
console.log("Got all the messages");
}
});
}
return true;
}
function send() {
// Handles with sending the message
var to = $('#to-jid').get(0).value,
myBareJid = Strophe.getBareJidFromJid(connection.jid);
message = $('#message').get(0).value,
reply = $msg({to: to, type: 'chat'})
.c("body")
.t(message);
connection.send(reply.tree());
showMessage(myBareJid + ": " + message);
}
$(document).ready(function () {
connection = new Strophe.Connection(BOSH_SERVICE);
messagebox = $("#messages");
messagebox.val("");
logbox = $("#log-messages");
logbox.val("");
rosterbox = $("#roster");
rosterbox.val("");
connection.rawInput = function (data) { log('RECV: ' + data); };
connection.rawOutput = function (data) { log('SEND: ' + data); };
Strophe.log = function (level, msg) { log('LOG: ' + msg); };
login();
$('#send').bind('click', send);
});
So whenever the user receives the message there will be something in the console. But it returns me this error in my logs
RECV: <body xmlns='http://jabber.org/protocol/httpbind'><iq xmlns='jabber:client'
from='yashwanth#localhost' to='yashwanth#localhost/22064184271436881211352579'
id='yashwanth#localhost' type='error'><query xmlns='urn:xmpp:mam:0'><x xmlns='jabber:x:data'><field
var='FORM_TYPE'><value>urn:xmpp:mam:0</value></field><field var='with'>
<value>shabda#localhost</value></field></x><set xmlns='http://jabber.org/protocol/rsm'/></query>
<error code='400' type='modify'><bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/></error>
</iq></body>
Please help me out with this
Your MAM query is not correctly formatted.
You are missing the attribute type="submit" on the x element with xmlns jabber:x:data feature. Type is mandatory in XEP-0004 Data Forms
You IQ should be:
<iq type='set' id='juliet1'>
<query xmlns='urn:xmpp:mam:0'>
<x xmlns='jabber:x:data' type='submit'>
<field var='FORM_TYPE' type='hidden'>
<value>urn:xmpp:mam:0</value>
</field>
<field var='with'>
<value>shabda#localhost</value>
</field>
</x>
<set xmlns='http://jabber.org/protocol/rsm'/>
</query>
</iq>
See Example 6 in XEP-0313 Message Archive Management.
The MAM strophe plugin had a bug. We prepared a fix here: https://github.com/processone/strophejs-plugins/commit/5a7857e2ab625c0521c68719d7e220f00c32c593
And submitted this pull request: https://github.com/strophe/strophejs-plugins/pull/65
I had a problem with MAM. See this link: https://www.ejabberd.im/forum/25028/solved-how-configure-and-test-modmam-message-archive-management
I solved the problem change type 'set' to 'get'
Related
can you help me with my Twitch Ban Checker
it worked a few months ago, but something is wrong now
maybe someone can give me a tip why it doesn't work anymore
I wrote this Twitch Ban Checker which, after entering the username, gives an answer whether you were banned on Twitch or not
the app is also on codepen https://codepen.io/olthoffs/pen/zqxbWW
var check_user = function (user) {
$(".description").fadeOut(20)
$.getJSON('https://api.twitch.tv/kraken/users/' + encodeURIComponent(user) + '?callback=?').done(function (data) {
if (/.+is unavailable$/.test(data.message)) { // Ban Check
var message = 'It looks like you were banned from twitch, please open a ticket via the '
message += '<a target="_blank" href="https://help.twitch.tv/customer/portal/emails/new?interaction[name]=' + user + '">official twitch support</a> '
message += 'site in order to see why you were banned.<br />'
message += '<span>TwitchTips cannot and will not help with your appeal</span>'
form_result('fail', message)
} else if (/.+is not available on Twitch$/.test(data.message) || /.+does not exist$/.test(data.message)) { // JTV/Nonexistant Check
var message = 'That account is either not a Twitch account or it does not exist.'
form_result('warn', message)
} else {
var message = 'The account provided does not seem to be banned on Twitch. '
message += 'If you\'re seeing a message telling you that you\'re blocked from Twitch, '
message += 'try disabling any VPN, proxy, or extension which re-routes traffic from your browser.<br/><br/>'
message += 'Got multiple accounts? Try checking those too because Twitch bans can be IP based.<br/><br/>'
message += 'If after doing so you are still getting the same error, '
message += 'your ISP may have provided your modem with a previously banned IP address. '
message += 'You can <a style="color: #fff" href="https://help.twitch.tv/customer/portal/emails/new?interaction[name]=' + user + '" target="_blank"><strong>open a ticket</strong></a> with Twitch to check.'
form_result('success', message)
}
}).fail(function () {
form_result('warn', 'The Twitch API appears to have returned an invalid response. Twitch may be having issues at the moment.')
})
}
var form_result = function (type, message) {
if (type === 'success') {
var title = "All is well!"
} else if (type === 'warn') {
var title = "Hmm, That's not right!"
} else {
var title = "Oh dear!"
}
$('.result').attr('class', 'result')
$('.result').html('<h3>' + title + '</h3>' + message)
$('.result').addClass(type)
$(".result").fadeIn()
}
$(document).ready(function () {
$('#ban-check').submit(function (e) {
e.preventDefault()
})
$('#ban-check').keyup(function (e) {
if (e.keyCode !== 13) {
return
}
e.preventDefault()
var user = $('#ban-check input').val()
window.location.hash = '#' + user
check_user(user)
})
var hash = location.hash
if (hash) {
var user = hash.substr(1)
$('#ban-check input').val(user)
check_user(user)
}
})
GET https://api.twitch.tv/kraken/users
(with client-id in the header)
returns:
{
"error": "Gone",
"status": 410,
"message": "It's time to kick ass and serve v3... and I'm all outta v3. See https://dev.twitch.tv/docs"
}
You might need to switch to helix, and go through OAuth flow.
I'm doing a project for University where I have a login for a website and I have to implement some operations. My issue is to maintain user session when a user is logged; so, if I open the website in a new tab, I want to be logged with the account of the main tab.
This is my angularjs code for the loginController:
mainAngularModule
.controller('LoginCtrl', ['$scope', '$state', 'AuthFactory',
function ($scope, $state, AuthFactory) {
let ctrl = this;
ctrl.authRequest = {username: 'admin', password: 'password'};
ctrl.doLogin = doLoginFn;
ctrl.authMessage = '';
//check if user already logged
let logSession = localStorage.getItem(("authinfo"));
if(logSession == null){
console.log("logSession null");
}
if(logSession == undefined){
console.log("isundefined");
}
if(logSession != null){
console.log("not null");
console.log("usern: " + logSession.username);
//console.log("authinfo authorities: " + logSession.authorities)
AuthFactory.setJWTAuthInfo(logSession);
$state.go("dashboard.home");
}
console.log("login authinfo: " + localStorage.getItem("authinfo"));
let sessionStorage_transfer = function(event) {
if(!event) { event = window.event; } // ie suq
if(!event.newValue) return; // do nothing if no value to work with
if (event.key === 'getSessionStorage') {
// another tab asked for the sessionStorage -> send it
localStorage.setItem('sessionStorage', JSON.stringify(sessionStorage));
// the other tab should now have it, so we're done with it.
} else if (event.key === 'sessionStorage' && !sessionStorage.length) {
// another tab sent data <- get it
var data = JSON.parse(event.newValue);
for (var key in data) {
sessionStorage.setItem(key, data[key]);
}
}
};
// listen for changes to localStorage
if(window.addEventListener) {
window.addEventListener("storage", sessionStorage_transfer, false);
} else {
window.attachEvent("onstorage", sessionStorage_transfer);
}
function doLoginFn() {
console.log("doLoginFn");
var requiresLogin = $state.jwtToken;
console.log("requireLogin: " + requiresLogin);
AuthFactory.sendLogin(ctrl.authRequest, successCB, errorCB);
function successCB(response) {
let authInfo = response.data;
console.log("data = " + response.data.all);
let header = response.headers();
authInfo.jwtToken = header['authorization'];
console.log("authInfo", authInfo);
// AuthFactory.user.username = authInfo.username;
// AuthFactory.user.role = authInfo.role;
let debugJWT = true;
//if (debugJWT) {
if (true) {
console.log(authInfo);
console.log("username: " + authInfo.username);
console.log("roles: " + JSON.stringify(authInfo.authorities));
console.log("jwtToken: " + authInfo.jwtToken);
console.log("userType: " + authInfo.userRole);
console.log("ended.");
}
AuthFactory.setJWTAuthInfo(authInfo);
//console.log("authinfoo1234: " + authInfo);
// localStorage.setItem("authinfo",authInfo);
console.log("authorities: " + authInfo.authorities);
$state.go("dashboard.home");
}
function errorCB(response) {
let error = response.data;
if (error && error.status === 401) {
ctrl.authMessage = error.message;
}
else {
console.error(response);
ctrl.authMessage = 'No response from server';
}
}
}
}
]);
I have a very strange problem: I'm using Intellj, and it tells me in lines
console.log("roles: " + JSON.stringify(authInfo.authorities));
console.log("userType: " + authInfo.userRole);
but if I comment lines with localStorage.setItem and localStorage.getItem, console prints on output correct userType and userRole; if I add those lines, console prints out this message:
TypeError
columnNumber: 17
fileName: "http://localhost:63342/ISSSR_frontend/app/scripts/service/AuthFactory.js"
lineNumber: 59
message: "authInfo.authorities is undefined"
I really don't understand, why it says me that it cannot resolve variable, but it can print out it?
Unfortunately I could not deploy your code would you please prepare codepen or flickr.
Some points that I can mention is below:
instead of use console.log("username: " + authInfo.username); use : console.log('username : ',authInfo.username)
Instead of JSON.stringify(authInfo.authorities) use : angular.toJson(authInfo.authorities,true)
Also console.log(response) to see what it returns.
I'm using the samples for the MSAL and converting them to use MS Graph to read SharePoint but when it comes to reading list items it seems I am getting permissions issues.
To make sure I have my syntax correct, I use the Graph Explorer with my AD account and I am able to read list items and confirm the URI is correct. I am also able to read and get an array of lists. But as soon as I try to get the list items for a list nothing is returned.
The base code is here https://learn.microsoft.com/en-us/azure/active-directory/develop/tutorial-v2-javascript-spa
Here's the code I converted from the sample. If you update the variables and register in Azure you should be able to run against your SPO site.
<!DOCTYPE html>
<html>
<head>
<title>Quickstart for MSAL JS</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.3.4/bluebird.min.js"></script>
<script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.0/js/msal.js"></script>
</head>
<body>
<h2>Welcome to MSAL.js Quickstart</h2><br />
<h4 id="WelcomeMessage"></h4>
<button id="SignIn" onclick="signIn()">Sign In</button><br /><br />
<button id="btnAllLists" onclick="GetWithEndPoint()">Get All Lists</button><br /><br />
<button id="btnListItems" onclick="GetWithEndPoint()">Get List Items</button><br /><br />
<button id="btnListItemsAllFields" onclick="GetWithEndPoint()">Get List Items All Fields</button><br /><br />
<pre id="json"></pre>
<script>
var config = {
portalname: "yourportalname",
sitename: "yoursitename",
listid: "guidofalist"
}
var msalConfig = {
auth: {
clientId: "azureclientguid",
authority: "https://login.microsoftonline.com/yourportal.onmicrosoft.com"
},
cache: {
cacheLocation: "localStorage",
storeAuthStateInCookie: true
}
};
var graphConfig = {
graphMeEndpoint: "https://graph.microsoft.com/v1.0/me",
spShowAllListsEp: "https://graph.microsoft.com/v1.0/sites/" + config.portalname + ".sharepoint.com:/sites/" + config.sitename + ":/lists",
spShowListItemsEp: "https://graph.microsoft.com/v1.0/sites/" + config.portalname + ".sharepoint.com:/sites/" + config.sitename + ":/lists/" + config.listid + "/items",
spShowListItemsAllFieldsEp: "https://graph.microsoft.com/v1.0/sites/" + config.portalname + ".sharepoint.com:/sites/" + config.sitename + ":/lists/" + config.listid + "/items?expand=fields",
};
// this can be used for login or token request, however in more complex situations this can have diverging options
var requestObj = {
scopes: ["user.read"]
};
var myMSALObj = new Msal.UserAgentApplication(msalConfig);
// Register Callbacks for redirect flow
myMSALObj.handleRedirectCallback(authRedirectCallBack);
function callMSGraph(theUrl, accessToken, callback) {
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200)
callback(JSON.parse(this.responseText));
}
xmlHttp.open("GET", theUrl, true); // true for asynchronous
xmlHttp.setRequestHeader('Authorization', 'Bearer ' + accessToken);
xmlHttp.send();
}
function signIn() {
myMSALObj.loginPopup(requestObj).then(function (loginResponse) {
//Login Success
showWelcomeMessage();
acquireTokenPopupAndCallMSGraph();
}).catch(function (error) {
console.log(error);
});
}
function acquireTokenPopupAndCallMSGraph() {
//Always start with acquireTokenSilent to obtain a token in the signed in user from cache
myMSALObj.acquireTokenSilent(requestObj).then(function (tokenResponse) {
callMSGraph(graphConfig.graphMeEndpoint, tokenResponse.accessToken, graphAPICallback);
}).catch(function (error) {
console.log(error);
// Upon acquireTokenSilent failure (due to consent or interaction or login required ONLY)
// Call acquireTokenPopup(popup window)
if (requiresInteraction(error.errorCode)) {
myMSALObj.acquireTokenPopup(requestObj).then(function (tokenResponse) {
callMSGraph(graphConfig.graphMeEndpoint, tokenResponse.accessToken, graphAPICallback);
}).catch(function (error) {
console.log(error);
});
}
});
}
function graphAPICallback(data) {
document.getElementById("json").innerHTML = JSON.stringify(data, null, 2);
}
function showWelcomeMessage() {
var divWelcome = document.getElementById('WelcomeMessage');
divWelcome.innerHTML = 'Welcome ' + myMSALObj.getAccount().userName + "to Microsoft Graph API";
var loginbutton = document.getElementById('SignIn');
loginbutton.innerHTML = 'Sign Out';
loginbutton.setAttribute('onclick', 'signOut();');
var btn1 = document.getElementById('btnAllLists');
btn1.setAttribute('onclick', "GetWithEndPoint('" + graphConfig.spShowAllListsEp + "');");
var btn2 = document.getElementById('btnListItems');
btn2.setAttribute('onclick', "GetWithEndPoint('" + graphConfig.spShowListItemsEp + "');");
var btn3 = document.getElementById('btnListItemsAllFields');
btn3.setAttribute('onclick', "GetWithEndPoint('" + graphConfig.spShowListItemsAllFieldsEp + "');");
}
//This function can be removed if you do not need to support IE
function acquireTokenRedirectAndCallMSGraph() {
//Always start with acquireTokenSilent to obtain a token in the signed in user from cache
myMSALObj.acquireTokenSilent(requestObj).then(function (tokenResponse) {
callMSGraph(graphConfig.graphMeEndpoint, tokenResponse.accessToken, graphAPICallback);
}).catch(function (error) {
console.log(error);
// Upon acquireTokenSilent failure (due to consent or interaction or login required ONLY)
// Call acquireTokenRedirect
if (requiresInteraction(error.errorCode)) {
myMSALObj.acquireTokenRedirect(requestObj);
}
});
}
function authRedirectCallBack(error, response) {
if (error) {
console.log(error);
}
else {
if (response.tokenType === "access_token") {
callMSGraph(graphConfig.graphEndpoint, response.accessToken, graphAPICallback);
} else {
console.log("token type is:" + response.tokenType);
}
}
}
function requiresInteraction(errorCode) {
if (!errorCode || !errorCode.length) {
return false;
}
return errorCode === "consent_required" ||
errorCode === "interaction_required" ||
errorCode === "login_required";
}
function signOut() {
myMSALObj.logout();
}
// Browser check variables
var ua = window.navigator.userAgent;
var msie = ua.indexOf('MSIE ');
var msie11 = ua.indexOf('Trident/');
var msedge = ua.indexOf('Edge/');
var isIE = msie > 0 || msie11 > 0;
var isEdge = msedge > 0;
//If you support IE, our recommendation is that you sign-in using Redirect APIs
//If you as a developer are testing using Edge InPrivate mode, please add "isEdge" to the if check
// can change this to default an experience outside browser use
var loginType = isIE ? "REDIRECT" : "POPUP";
if (loginType === 'POPUP') {
if (myMSALObj.getAccount()) {// avoid duplicate code execution on page load in case of iframe and popup window.
showWelcomeMessage();
acquireTokenPopupAndCallMSGraph();
}
}
else if (loginType === 'REDIRECT') {
document.getElementById("SignIn").onclick = function () {
myMSALObj.loginRedirect(requestObj);
};
if (myMSALObj.getAccount() && !myMSALObj.isCallback(window.location.hash)) {// avoid duplicate code execution on page load in case of iframe and popup window.
showWelcomeMessage();
acquireTokenRedirectAndCallMSGraph();
}
} else {
console.error('Please set a valid login type');
}
</script>
<script>
function GetWithEndPoint(endpointString) {
myMSALObj.acquireTokenSilent(requestObj).then(function (tokenResponse) {
callMSGraph(endpointString, tokenResponse.accessToken, graphAPICallback);
}).catch(function (error) {
console.log(error);
if (requiresInteraction(error.errorCode)) {
myMSALObj.acquireTokenPopup(requestObj).then(function (tokenResponse) {
callMSGraph(endpointString, tokenResponse.accessToken, graphAPICallback);
}).catch(function (error) {
console.log(error);
});
}
});
}
</script>
</body>
</html>
Clicking either button that returns list items throws this message which I understand to mean is permissions.
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(microsoft.graph.list)('myid')/items",
"value": []
}
My expectation is that I would get the same results from the Graph Explorer. But this indicates I don't have permission. I've tried a few different lists and the results are always the same. I can get a list of all the lists. But trying to get the items from a list fails.
Can we not use the Graph API with JS to get list items?
Here are the Azure delegated permissions from Azure which I think should be all I need to get list items.
But this indicates I don't have permission
That's right, empty results usually indicates one of the following permissions (delegated permissions in your case) are missing for Get Items endpoint:
Sites.Read.All - read items in all site collections
Sites.ReadWrite.All - edit or delete items in all site collections
i created a login.php file where the user can will be navigated to instamojo payment page . After completing the transaction the user is getting the success message from instamojo , but i need to display the successful transaction in my domain or in own php file . so how can i get the transation related information to my webpage or to my login.php file
Ex: Redirecting from our login.php to instamojo(payment gateway)and response back (success message)to our login.php intimating the user that payment is success
var rootURL = "cgshealthcare.com/HealthCareSystem/";;
$(document).ready(function() {
$('#login').click(function() {
if ($('#username').val() == "" || $('#password').val() == "") {
alert("Please enter username or password");
return false;
}
cardloginUser($('#username').val(), $('#password').val());
});
});
function forwardtoRegister() {
window.location = "login.php?page=register";
}
function cardloginUser(userName, password) {
console.log('userName: ' + userName);
console.log('password: ' + password);
if (userName.length < 1) {
$('#errorlist').html("<font color='red'><b> Please enter User ID</b></font>");
return false;
}
if (password.length < 1) {
$('#errorlist').html(" <font color='red'><b> Please enter Password</b></font>");
return false;
}
console.log(rootURL + '/authenticate/' + userName + '/' + password);
$.ajax({
type: 'GET',
url: rootURL + '/authenticate/' + userName + '/' + password,
dataType: "json",
success: function(data) {
console.log("hello" + data.responseMessageDetails);
var list = data == null ? [] : (data.responseMessageDetails instanceof Array ? data.responseMessageDetails : [data.responseMessageDetails]);
console.log("List : " + list);
if ((list).length < 1) {
$('#errorlist').html("<font color='red'><b> Invalid User Name and Password Combination </b></font>");
$('#errorblock').css("visibility") == "visible";
}
$.each(list, function(index, responseMessageDetails) {
console.log("Status " + responseMessageDetails);
var message = responseMessageDetails.message;
if (message.indexOf("]:") > 0) message = message.substring(0, message.indexOf("]:") + 2);
console.log("message" + message);
console.log("USer Data" + responseMessageDetails.status);
console.log("USer Data" + responseMessageDetails.message);
if (responseMessageDetails.status == "Success") {
window.location = "imjo.in/NpKxN";;
} else if (responseMessageDetails.status == "Fail") {
window.location = "www.google.com";
console.log("Fail1");
$('#errorlist').html("<font color='red'><b>" + message + "</b></font>");
} else {
console.log("Fail111");
$('#errorlist').html("<font color='red'><b> We are sorry some intermittent Issue. Please try after some time. </b></font>");
}
});
},
error: function(data) {
console.log("data...." + data);
var list = data == null ? [] : (data.responseMessageDetails instanceof Array ? data.responseMessageDetails : [data.responseMessageDetails]);
console.log("data...." + data);
$.each(list, function(index, responseMessageDetails) {
console.log(responseMessageDetails);
var message = responseMessageDetails.message;
if (message.indexOf("]:") > 0) message = message.substring(0, message.indexOf("]:") + 2);
$('#errorlist').html("<font color='red'><b>" + message + "</b></font>");
});
}
});
}
function showLogin() {
window.location = "login.php";
}
Please look at the integration guide here.
After user enters payment information on instamojo, they are redirected to a redirect-url which you specify (and is a url on your website). Instamojo appends transaction results to this url. You can make it a php url on your website and read the results using GET method. Depending upon the results, you can process your payment and display results to the end-user. More on GET method here...
Instamojo also provides for webhooks, which are like silent POSTs in the background and can be used as backups in case redirect urls in front-end fail for some reason. This way if end-users' redirection failed for any reason, the webhook will still receive information in the background which can be used you to update your database for success/failure of transaction. Of course you webserver has to be up and running to receive webhooks notifications. If that's the point of failure, nothing will work :)
The API link I shared has all those details.
Thanks
I'm trying to show a notification using an image I receive over a socket as an arrayBuffer. The notification shows, but without the image supplied. The standard firefox logo/icon is used instead. Any help would be appreciated. The code seems to run without any errors, or rather, no errors are are thrown/stack trace printed when the notification is created.
Here is the code to create the notification:
ps_worker.port.on("notification", function(notification){
//DISPLAY LINK TO USER
var arrayBuffer_icon = notification.icon;
var arrayBuffer_largeicon = notification.largeicon;
var str = String.fromCharCode.apply(null,arrayBuffer_icon);
var base64String = utils.btoa(str).replace(/.{76}(?=.)/g,'$&\n');
var dataUri = "data:image/png;base64,"+ base64String;
notifications.notify({
title: notification.app + ": " + notification.title,
text: notification["subject"] + "\n" + notification.content,
data: "did gyre and gimble in the wabe", // data is a string passed through to the on click listener
iconURL: dataUri,
onClick: function (data) {
console.log(data);
}
});
});
the utils.btoa call is implemented as described here: https://developer.mozilla.org/en-US/Add-ons/SDK/Tutorials/Unit_testing
The relevant server code is (node.js):
function send_notification_to_socket(user, notification, target){
fs.readFile(notification.iconpath, function(err, buf){
if(socketstore.get_socket_by_id(user)){
socket = socketstore.get_socket_by_id(user);
notification["icon"] = buf;
socket.emit('notification', notification);
}else{
console.log("No socket for user " + user);
}
});
}
Any ideas on what I might be doing wrong?