nativescript-phone prevents Nativescript-contacts from returning - sms

I have an app where I want to select a person from contacts and then send a text to that person. It works as expected for the first user, but after that the app never receives control after the contact is selected. I've isolated the problem to the Nativescript-phone plugin. If you simply call phone.sms() to send a text, and then call contacts.getContact(), the problem occurs. I see this on both Android and iOS.
I've created a sample app that demos the problem at https://github.com/dlcole/contactTester. The sample app is Android only. I've spent a couple days on this and welcome any insights.
Edit 4/21/2020:
I've spent more time on this and can see what's happening. Both plugins have the same event handler and same request codes:
nativescript-phone:
var SEND_SMS = 1001;
activity.onActivityResult = function(requestCode, resultCode, data) {
nativescript-contacts:
var PICK_CONTACT = 1001;
appModule.android.on("activityResult", function(eventData) {
What happens is that after invoking phone.sms, calling contacts.getContact causes control to return to the phone plugin, and NOT the contacts plugin. I tried changing phone's request code to 1002 but had the same results.
So, the next step is to determine how to avoid the collision of the event handlers.

Instead of using activityResult event, nativescript-phone plugin overwrites the default activity result callback.
A workaround is to set the callback to it's original value after you are done with nativescript-phone.
exports.sendText = function (args) {
console.log("entering sendText");
const activity = appModule.android.foregroundActivity || appModule.android.startActivity;
const onActivityResult = activity.onActivityResult;
permissions.requestPermissions([android.Manifest.permission.CALL_PHONE],
"Permission needed to send text")
.then(() => {
console.log("permission granted");
phone.sms()
.then((result) => {
console.log(JSON.stringify(result, null, 4));
activity.onActivityResult = onActivityResult;
})
})
}

Related

Create Firefox Extension to Detect Push Notification Received from Any Site

I'd like to create a simple Firefox extension to write a simple message to the Javascript console when a push notification is received from any site. I see there is a notification show event that seems like it should work although I can't seem to find an example of it in use. Is this possible?
I'm not sure that that API would handle your use case because the event is not global. It is placed on the object e.g.
var notify = new Notification("Hi there!").addEventListener('show', e => console.log("We showed it! ", e));
I can't think of a better solution if you want to watch for global events than what is mentioned in https://stackoverflow.com/a/36868084/4875295 -- Monkey Patching!
Copying the code from that answer for posterity:
function setNotificationCallback(callback) {
const OldNotify = window.Notification;
const newNotify = (title, opt) => {
callback(title, opt);
return new OldNotify(title, opt);
};
newNotify.requestPermission = OldNotify.requestPermission.bind(OldNotify);
Object.defineProperty(newNotify, 'permission', {
get: () => {
return OldNotify.permission;
}
});
window.Notification = newNotify;
}

how do I program a slackbot to send a regular message automatically every week

I am building a slackbot that will remind people in my organisation to perform certain admin (hours expenses etc) every week. I know this can be very easily done by each person creating a recurring reminder. What i want is to create a bot that will send a preconfigured message to people every week. I've looked online extensively, and haven't yet found out how slackbot can send a message without an event or being otherwise prompted.
I'm currently testing this on a local ngrok server with the following backend:
const { WebClient } = require('#slack/web-api');
const { createEventAdapter } = require('#slack/events-api');
const slackSigningSecret = process.env.SLACK_SIGNING_SECRET;
const slackToken = process.env.SLACK_TOKEN;
const port = process.env.SLACK_PORT || 3000;
const slackEvents = createEventAdapter(slackSigningSecret);
const slackClient = new WebClient(slackToken);
slackEvents.on('app_mention', (event) => {
console.log(`Got message from user ${event.user}: ${event.text}`);
(async () => {
try {
await slackClient.chat.postMessage({ channel: event.channel, text: `Hello <#${event.user}>! Have you completed your Time sheets for this week yet?` })
} catch (error) {
console.log(error.data)
}
})();
});
slackEvents.on('error', console.error);
slackEvents.start(port).then(() => {
console.log(`Server started on port ${port}`)
});
Once this reminder is done, i intend to build upon it (more features, just need a beginning) so please don't recommend alternative ways my organisation can send reminders to people.
You can try using the chat.scheduleMessage method instead (https://api.slack.com/methods/chat.scheduleMessage). Since you won't rely on an event you may want to store the necessary conversations ids so that they're ready when the app needs to call the method.

How to manage user inputs in a short time interval?

i would like to implement a way of managing a user sending many messages in a time interval (for example 3 seconds), so that the chatbot only responds to the last one.
Example of inputs (in a gap of 3 seconds):
-Hi
-Hi
-Hi
-Help
Result: The chatbot only responds to the Help message.
Thanks in advance.
You can leverage Middleware feature to intercept every message, with which you can store every user's every message in cache, when your bot receive a new message, you can compaire with those info in cache, then dicide whether the flow needs to go forward.
Npde.js code snippet for quick test:
const moment = require('moment');
let lastMessage = null;
let lastMessageTime = null;
bot.use({
receive: (session, next) => {
let currentMessage = session
if (currentMessage.text !== lastMessage) {
lastMessage = currentMessage.text;
lastMessageTime = currentMessage.timestamp;
next();
} else {
if (moment(currentMessage.timestamp) - moment(lastMessageTime) >= 3000) {
lastMessageTime = currentMessage.timestamp;
next();
}
}
}
})
What needs you paying attention is that, in production env, you need to store the message with session/user id. E.G. Using session/user id as prefix of message and timesamp key in cache.
Please refer to https://learn.microsoft.com/en-us/bot-framework/dotnet/bot-builder-dotnet-middleware for how to intercept messages in C#,
and refer to https://learn.microsoft.com/en-us/bot-framework/nodejs/bot-builder-nodejs-intercept-messages for Node.js version.
Hope it helps.

How to use the library PushSharp to send push notifications to iOS?

I am using the latest PushSharp version to send push notification through APN. I am using the below code given in their Git wiki page to send the notifications:
// Configuration (NOTE: .pfx can also be used here)
var config = new ApnsConfiguration (ApnsConfiguration.ApnsServerEnvironment.Sandbox,
"push-cert.p12", "push-cert-pwd");
// Create a new broker
var apnsBroker = new ApnsServiceBroker (config);
// Wire up events
apnsBroker.OnNotificationFailed += (notification, aggregateEx) => {
aggregateEx.Handle (ex => {
// See what kind of exception it was to further diagnose
if (ex is ApnsNotificationException) {
var notificationException = (ApnsNotificationException)ex;
// Deal with the failed notification
var apnsNotification = notificationException.Notification;
var statusCode = notificationException.ErrorStatusCode;
Console.WriteLine ($"Apple Notification Failed: ID={apnsNotification.Identifier}, Code={statusCode}");
} else {
// Inner exception might hold more useful information like an ApnsConnectionException
Console.WriteLine ($"Apple Notification Failed for some unknown reason : {ex.InnerException}");
}
// Mark it as handled
return true;
});
};
apnsBroker.OnNotificationSucceeded += (notification) => {
Console.WriteLine ("Apple Notification Sent!");
};
// Start the broker
apnsBroker.Start ();
foreach (var deviceToken in MY_DEVICE_TOKENS) {
// Queue a notification to send
apnsBroker.QueueNotification (new ApnsNotification {
DeviceToken = deviceToken,
Payload = JObject.Parse ("{\"aps\":{\"badge\":7}}")
});
}
// Stop the broker, wait for it to finish
// This isn't done after every message, but after you're
// done with the broker
apnsBroker.Stop ();
The confusions -
I don't know if the method apnsBroker.QueueNotification sends the push at all, or just queues it up.
I don't know if I need to install the apple certificate in some way on my Windows machine.
There is no proper sample code available online with the latest version of PushSharp.
Just fire the above code in a console application and Pushsharp will send the notifications.
Apple allow a single push token for a push notification at a time.
The code works as it. But there are some uncertain points as you said.
First notification will be send right away when you queue it, it is just a async mechanism to not to wait the code there. So if anything goes wrong (or right) you can handle it via broker's events.
Second part is a little complicated. First of all you have create a certificate for pushnotifications on a macOS machine. Than you have to upload it to your developer account etc. You can find videos how to that via google. It is pretty long to describe it here. Than you have to export your "Apple Push Services" certificate from your macOSmachine to a p12 file. And get and put that .p12 file to your .net service folder for example to "App_Data" folder and load it like (i assume you are writing a web service):
var config = new ApnsConfiguration(ApnsConfiguration.ApnsServerEnvironment.Sandbox,
Path.Combine(HostingEnvironment.ApplicationPhysicalPath, "App_Data", "yourfileName.p12"),"yourFilePassword");
I hope that helps you.

can't seem to get progress events from node-formidable to send to the correct client over socket.io

So I'm building a multipart form uploader over ajax on node.js, and sending progress events back to the client over socket.io to show the status of their upload. Everything works just fine until I have multiple clients trying to upload at the same time. Originally what would happen is while one upload is going, when a second one starts up it begins receiving progress events from both of the forms being parsed. The original form does not get affected and it only receives progress updates for itself. I tried creating a new formidable form object and storing it in an array along with the socket's session id to try to fix this, but now the first form stops receiving events while the second form gets processed. Here is my server code:
var http = require('http'),
formidable = require('formidable'),
fs = require('fs'),
io = require('socket.io'),
mime = require('mime'),
forms = {};
var server = http.createServer(function (req, res) {
if (req.url.split("?")[0] == "/upload") {
console.log("hit upload");
if (req.method.toLowerCase() === 'post') {
socket_id = req.url.split("sid=")[1];
forms[socket_id] = new formidable.IncomingForm();
form = forms[socket_id];
form.addListener('progress', function (bytesReceived, bytesExpected) {
progress = (bytesReceived / bytesExpected * 100).toFixed(0);
socket.sockets.socket(socket_id).send(progress);
});
form.parse(req, function (err, fields, files) {
file_name = escape(files.upload.name);
fs.writeFile(file_name, files.upload, 'utf8', function (err) {
if (err) throw err;
console.log(file_name);
})
});
}
}
});
var socket = io.listen(server);
server.listen(8000);
If anyone could be any help on this I would greatly appreciate it. I've been banging my head against my desk for a few days trying to figure this one out, and would really just like to get this solved so that I can move on. Thank you so much in advance!
Can you try putting console.log(socket_id);
after form = forms[socket_id]; and
after progress = (bytesReceived / bytesExpected * 100).toFixed(0);, please?
I get the feeling that you might have to wrap that socket_id in a closure, like this:
form.addListener(
'progress',
(function(socket_id) {
return function (bytesReceived, bytesExpected) {
progress = (bytesReceived / bytesExpected * 100).toFixed(0);
socket.sockets.socket(socket_id).send(progress);
};
})(socket_id)
);
The problem is that you aren't declaring socket_id and form with var, so they're actually global.socket_id and global.form rather than local variables of your request handler. Consequently, separate requests step over each other since the callbacks are referring to the globals rather than being proper closures.
rdrey's solution works because it bypasses that problem (though only for socket_id; if you were to change the code in such a way that one of the callbacks referenced form you'd get in trouble). Normally you only need to use his technique if the variable in question is something that changes in the course of executing the outer function (e.g. if you're creating closures within a loop).

Resources