Which event type is triggered when a slack app is installed onto a workspace for the first time? - slack

I'm trying to build an app that does something when it is first installed onto a workspace, eg: Ping every team member.
I couldn't find an event type that gets triggered upon app install:
https://api.slack.com/events
Is there a way to make this happen?

I think there might be a misunderstanding of the events concepts here. Events are always directly linked to one specific Slack app and needs to be processed by that very app. There is no such thing as "general" events for things happening on a workplace, like a new app being installed. Ergo there is no event for app installation.
Nevertheless you can implement the functionality you mentioned with Slack, e.g. pinging all team members once an app is first installed. All you need to do is include this function in the installation process of your Slack app and e.g. start pinging after the installation process is complete and the app verified that it was the first installation to this workspace. You do not need an event for that.

This is a partial answer because I was wondering the same thing and wanted to share what I found. On this oauth tutorial, it has the following code snippet:
app.get('/auth', function(req, res){
if (!req.query.code) { // access denied
return;
}
var data = {form: {
client_id: process.env.SLACK_CLIENT_ID,
client_secret: process.env.SLACK_CLIENT_SECRET,
code: req.query.code
}};
request.post('https://slack.com/api/oauth.access', data, function (error, response, body) {
if (!error && response.statusCode == 200) {
// Get an auth token
let oauthToken = JSON.parse(body).access_token;
// OAuth done- redirect the user to wherever
res.redirect(__dirname + "/public/success.html");
}
})
});
I believe instead of the line res.redirect(__dirname + "/public/success.html"); at that point you can make a request to ping everyone or even call a function to do so directly there, and it will trigger immediately once the app has been installed.

Related

OneSignal registration fails after refresh

I am using OneSignal in my Laravel/Vue app. I have included it within <head> as stated in documentation:
<script src="https://cdn.onesignal.com/sdks/OneSignalSDK.js" async=""></script>
<script>
var OneSignal = window.OneSignal || [];
OneSignal.push(function() {
OneSignal.init({
appId: "{{ env('ONESIGNAL_APP_ID') }}"
});
OneSignal.showNativePrompt();
});
</script>
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/OneSignalSDKWorker.js')
.then(function () {
console.log('Service worker registered');
})
.catch(function (error) {
console.log('Service worker registration failed:', error);
});
} else {
console.log('Service workers are not supported.');
}
</script>
I also have a service worker of my own, so I've followed the documentation here as well.
What is happening after a hard reset is that service worker gets installed and it is all fine, however once I refresh the page I am getting:
OneSignalPageSDKES6.js?v=151102:1 Uncaught (in promise) InvalidStateError: The current environment does not support this operation.
at Function.getServiceWorkerHref (https://cdn.onesignal.com/sdks/OneSignalPageSDKES6.js?v=151102:1:41510)
at xe. (https://cdn.onesignal.com/sdks/OneSignalPageSDKES6.js?v=151102:1:144028)
at Generator.next ()
at r (https://cdn.onesignal.com/sdks/OneSignalPageSDKES6.js?v=151102:1:716)
And I have no idea what does that mean? What is "current environment"? Where to start debugging? I've tried putting console logs around it, however it led me nowhere...
You would start debugging by looking at the source code of the library.
In your case your library is the OneSignal SDK for browsers.
Let's do this!!!
We can see that this error is thrown by getServiceWorkerHref function (which is defined here) and the error message is driven by the InvalidStateReason enumeration:
case InvalidStateReason.UnsupportedEnvironment:
super(`The current environment does not support this operation.`);
break;
If you look at the first linked file, you will see the note on getServiceWorkerHref OneSignal developers left for the those who dare venture into their source code:
else if (workerState === ServiceWorkerActiveState.Bypassed) {
/*
if the page is hard refreshed bypassing the cache, no service worker
will control the page.
It doesn't matter if we try to reinstall an existing worker; still no
service worker will control the page after installation.
*/
throw new InvalidStateError(InvalidStateReason.UnsupportedEnvironment);
}
As you can see, the error is raised when the service worker has the "Bypassed" state. What is that, you may ask? Let's look at ServiceWorkerActiveState enumeration below, in the same file:
/**
* A service worker is active but not controlling the page. This can occur if
* the page is hard-refreshed bypassing the cache, which also bypasses service
* workers.
*/
Bypassed = 'Bypassed',
It seems, when the browser "hard-refreshes" the page, it bypasses the service worker and OneSignal can't properly initialize when that happens. Hard-refresh can happen for a number of reasons — here are some of them (to the best of my knowledge):
if you click the refresh button a bunch of times (usually seconds consecutive refresh within a short period of time may trigger this)
if you have caching disabled in your DevTools
if the server sets a no-cache header
What is happening after a hard reset
I don't know exactly what you mean by "hard reset", but that sounds like it would trigger this issue. I would suggest you close your browser and then visit the page you are working on without using "reset" functions — theoretically, the service worker should be used for caching on consecutive visits and that would ensure OneSignal can function.

Failed to connect (500) to bot framework using Direct Line

We have a bot running in Azure (Web App Bot) that I'm trying to embed on a website. The bot is based of the Bot Builder V4 SDK Tamplate CoreBot v4.9.2. At first I used the iframe to embed the bod. This worked but didn't provide the features we need, so now im changing it to use DirectLine.
My code on the webpage looks like this:
<script crossorigin="anonymous"
src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
<div id="webchat" role="main"></div>
<script>
(async function () {
const res = await fetch('https://[my bot name here].azurewebsites.net/.bot/v3/directline/tokens/generate',
{
method: 'POST',
headers: new Headers({
'Authorization': "Bearer [my token here]"
})
});
const { token } = await res.json();
window.WebChat.renderWebChat(
{
directLine: await window.WebChat.createDirectLineAppServiceExtension({
domain: 'https://[my bot name here].azurewebsites.net/.bot/v3/directline',
token
})
},
document.getElementById('webchat')
);
document.querySelector('#webchat > *').focus();
})().catch(err => console.error(err));
</script>
After some struggles I managed to fetch a token from https://[my bot name here].azurewebsites.net/.bot/v3/directline.
And I can see the chat window on my webpage, but is says connecting for a while then it changes to Taking longer than usual to connect, like this:
In the Chrome console there is an error saying Failed to connect Error: Connection response code 500. When I check Chrome's Network tab I can see that the token generated completed with status 200 and that the websocket connection is open, like this:
----------EDIT---------
I just noticed that when go to https://[my bot name here].azurewebsites.net/.bot using a webbrowser, the resulting json is
{"v":"1.0.0.0.55fa54091a[some key?]","k":true,"ib":false,"ob":false,"initialized":true}
ib and ob should be true but are false, maybe this is part of the problem.
----------EDIT 2---------
OK so now I'm starting to go crazy.
Ashish helped me and at some point the ib and ob were true. They were true for most of yesterday. At some point yesterday they turned false for a short while (no more than 2 hours). I checked if someone had triggered the release pipeline but no recent releases. After that ib and ob magically turned true again and connecting to the direct line worked again.
Now this morning ib and ob were false again. And again no recent releases. I don't know what is causing this.
Does anybody know what's going on here or how to fix this? How do I find what causes ib and ob to be false?
Any help is appreciated! Thanks in advance. If you need more information, just ask and I'll post it.
If the ib and ob values displayed by the *.bot endpoint are false this means the bot and the Direct Line app service extension are unable to connect to each other.
Make sure you verify below things:
Double check the code for using named pipes has been added to the
bot.
Confirm the bot is able to start up and run at all. Useful
tools are Test in WebChat, connecting an additional channel, remote
debugging, or logging.
Restart the entire Azure App Service the bot
is hosted within, to ensure a clean start up of all processes.
Please check troubleshooting guide, it seems updated today. (still old date reflected some how, not sure why)

NativeScript Firebase already initialized

I am using Firebase in my app and I've noticed when I am actively making changes and LiveSync updates the app it will sometimes say "firebase.init error: Firebase already initialized". This happens when the changes don't trigger a whole application restart (ex. an html file). It completely messes up my current authentication state and forces me to restart the app anyways.
Is there some way I can catch for this happening or prevent it? I can try to make a demo app for it, but I feel this might have happened to somebody already.
I am just using the standard firebase.init as shown in the documentation in my app.component, nothing special or different.
Instead of using on ngOnit of App.component, try to initlize firebase on app launch event.
applicationOn(launchEvent, (args: LaunchEventData) => {
firebase.init({
// Optionally pass in properties for database, authentication and cloud messaging,
// see their respective docs.
}).then(
function () {
console.log("firebase.init done");
},
function (error) {
console.log("firebase.init error: " + error);
}
);
});

Error sending message to WebChat via DirectLine

I have a bot deployed in Azure. Uses the latest >net bot framework, (v3).
The front-end uses the vanilla WebChat. I am trying to send an event from the BOT TO THE CLIENT, in order to trigger a wipe of the webchat visible history.
I'm getting the more than useless 502 error when my bot tries to send the event message.
The JS to setup the web chat and directline on my front end is:
var botConnection = new BotChat.DirectLine({
secret: {secret removed..becuase secret},
//token: params['t'],
//domain: params['domain'],
webSocket: "true" // defaults to true
});
BotChat.App({
bot: bot,
botConnection: botConnection,
resize: 'detect',
user: user,
chatTitle: false,
showUploadButton: false
}, document.getElementById('bot'));
//backchannel communication setup
botConnection.activity$
.filter(function (activity) {
return activity.type === 'event' && activity.name === 'clearChatHistory';
})
.subscribe(function (activity) {
console.log('"clearChatHistory" received');
clearChatHistory();
});
function clearChatHistory() {
$(".wc-message-wrapper").remove();
}
The idea here is that my bot code will create a message of type 'activity' with the value = 'clearChatHistory'. This fire the code on my client.
The code for sending this message is:
internal static async Task SendClearChatHistoryEvent(Activity activity)
{
Trace.TraceInformation($"Utility::SendClearChatHistoryEvent");
Activity clearMessage = activity.CreateReply();
clearMessage.Type = "event";
clearMessage.Value = "clearChatHistory";
Trace.TraceInformation(JsonConvert.SerializeObject(clearMessage));
Trace.TraceInformation($"Utility::SendClearChatHistoryEvent::ServiceURL:{activity.ServiceUrl}");
var connector = new ConnectorClient(new Uri(activity.ServiceUrl));
await connector.Conversations.SendToConversationAsync(clearMessage);
}
The bot fail is happening at the 'SendToConversationAsync' call
The closest thing I get to an error is on the client side
"https://directline.botframework.com/v3/directline/conversations/5OSJJILizNqGG4H7SaV6fQ/activities 502 (Bad Gateway)"
The Visual Studio output window displays
'Microsoft.Rest.TransientFaultHandling.HttpRequestWithStatusException'
and 'Microsoft.Bot.Connector.ErrorResponseException
exceptions
Any insights on what I might be doing wrong or whats happening otherwise here would be greatly appreciated.
You're setting the value on the event but checking the name. If you use this as the filter it should work:
.filter(activity => activity.type === 'event' && activity.value === 'clearChatHistory')
Regarding the bad gateway however, I am not sure, as I was not seeing this occur with your code on my system.
I figured out what the problem is. First, there was a bug in my code example which Mark B pointed out. However, that was not the source of the problem but it did help me to get to the real issue.
The Bad Gateway problem wasn't really a good indicator of the problem either. I had to do a lot of Trace writing and stepping through code to finally notice what was happening. I'll try to describe the problem so you all can learn from my boneheaded mistake.
The understand the problem, you need to understand what this line of code is doing
Activity clearMessage = activity.CreateReply();
CreateReply() creates a new Activiy from an existing one. When it does that, it swaps the values of From and Recipient. This is because you want to reply to the person the original message comes from. Make 100% total sense.
The problem, for me, was my original message was ALSO created by calling CreateReaply() in a previous dialog. SO, I basically created a new message to be sent to myself (or the bot in this case). I need the message to to to the chatbot user, not the bot.
When the bot framework attempted to send itself a message it excepted and failed. Why it got the bad gateway error I dont exactly know and will continue to research that.
To fix this, I changed my upstream code to use
var newMessage = context.MakeMessage()
instead of the CreateReaply(). This does not swap From and Recipient.
Everything is now flowing along very nicely. My code will now force a wipe of the visible chat history in my WebChat client.

Detect url the user is viewing in chrome/firefox/safari

How can you detect the url that I am browsing in chrome/safari/firefox via cocoa (desktop app)?
As a side but related note, are there any security restrictions when developing a desktop app that the user will be alerted and asked if they want to allow? e.g. if the app accesses their contact information etc.
Looking for a cocoa based solution, not javascript.
I would do this as an extension, and because you would like to target Chrome, Safari, and Firefox, I'd use a cross-browser extension framework like Crossrider.
So go to crossrider.com, set up an account and create a new extension. Then open the background.js file and paste in code like this:
appAPI.ready(function($) {
appAPI.message.addListener({channel: "notifyPageUrl"}, function(msg) {
//Do something, like send an xhr post somewhere
// notifying you of the pageUrl that the user visited.
// The url is contained within msg.pageUrl
});
var opts = { listen: true};
// Note: When defining the callback function, the first parameter is an object that
// contains the page URL, and the second parameter contains the data passed
// to the context of the callback function.
appAPI.webRequest.onBeforeNavigate.addListener(function(details, opaqueData) {
// Where:
// * details.pageUrl is the URL of the tab requesting the page
// * opaqueData is the data passed to the context of the callback function
if(opaqueData.listen){
appAPI.message.toBackground({
msg: details.pageUrl
}, {channel: "notifyPageUrl"});
}
}, opts ); // opts is the opaque parameter that is passed to the callback function
});
Then install the extension! In the example above, nothing is being done with the detected pageUrl that the user is visiting, but you can do whatever you like here - you could send a message to the user, you could restrict access utilizing the cancel or redirectTo return parameters, you could log it locally utilizing the crossrider appAPI.db API or you could send the notification elsewhere, cross-domain, to wherever you like utilizing an XHR request from the background directly.
Hope that helps!
And to answer the question on security issues desktop-side, just note that desktop applications will have the permissions of the user under which they run. So if you are thinking of providing a desktop app that your users will run locally, say something that will detect urls they access by tapping into the network stream using something like winpcap on windows or libpcap on *nix varieties, then just be aware of that - and also that libpcap and friends would have to have access to a network card that can be placed in promiscuous mode in the first place, by the user in question.
the pcap / installed desktop app solutions are pretty invasive - most folks don't want you listening in on literally everything and may actually violate some security policies depending on where your users work - their network administrators may not appreciate you "sniffing", whether that is the actual purpose or not. Security guys can get real spooky so-to-speak on these kinds of topics.
The extension via Crossrider is probably the easiest and least intrusive way of accomplishing your goal if I understand the goal correctly.
One last note, you can get the current tab urls for all tabs using Crossrider's tabs API:
// retrieves the array of tabs
appAPI.tabs.getAllTabs(function(allTabInfo) {
// Display the array
for (var i=0; i<allTabInfo.length; i++) {
console.log(
'tabId: ' + allTabInfo[i].tabId +
' tabUrl: ' + allTabInfo[i].tabUrl
);
}
});
For the tab API, refer to:
http://docs.crossrider.com/#!/api/appAPI.tabs
For the background navigation API:
http://docs.crossrider.com/#!/api/appAPI.webRequest.onBeforeNavigate
And for the messaging:
http://docs.crossrider.com/#!/api/appAPI.message
And for the appAPI.db stuff:
http://docs.crossrider.com/#!/api/appAPI.db
Have you looked into the Scripting Bridge? You could have an app that launches, say, an Applescript which verifies if any of the well known browser is opened and ask them which documents (URL) they are viewing.
Note: It doesn't necessarily need to be an applescript; you can access the Scripting Bridge through cocoa.
It would, however, require the browser to support it. I know Safari supports it but ignore if the others do.
Just as a quick note:
There are ways to do it via AppleScript, and you can easily wrap this code into NSAppleScript calls.
Here's gist with AppleScript commands for Safari and Chrome. Firefox seems to not support AE.
Well obviously this is what I had come across on google.
chrome.tabs.
getSelected
(null,
function
(tab) {
alert
(tab.url);
}) ;
in pure javascript we can use
alert(document.URL);
alert(window.location.href)
function to get current url

Resources