Open ephimoff opened 4 years ago
I think we should need to rewrite the https://slack.com/app_redirect
to the deeplink slack://open
format. I will give it a try during easter.
This at least rewrites the url to the correct one.
rewrite: [
{
// Redirect all https://slack.com/app_redirect?team=team=apegroup&channel=random
// to slack://channel?team=apegroup&id=random
match: ({ url }) => url.host.includes("slack.com") && url.pathname.includes("app_redirect"),
url({ url }) {
const team = url.search.split('&').filter(part => part.startsWith('team'));
var channel = "" + url.search.split('&').filter(part => part.startsWith('channel'));
var id = channel.replace("channel", "id");
return {
protocol: "slack",
username: "",
password: "",
host: "channel",
port: null,
pathname: "",
search : team + '&' + id,
hash: ""
}
}
}
]
Awesome!
Do I just put it into my .finicky.js
?
Yes. Still haven't figured out how to get it to actually open Slack in a correct way.
Spent some time starting with what @ovelindstrom posted and modified it for my use case. Managed to get most links to work that I use (not sure about others). There didn't appear to be any documentation on how to translate deep linked messages here, but eventually figured out through trial and error how to format the message identifier. Below is the config that I use, but be sure to populate the org map with the proper subdomains and team identifiers:
handlers: [
{
// Redirect all web links
// from: https://app.slack.com/client/<team id>/<channel>
// to: slack://channel?team=<team-id>&id=<channel-id>
//
// Redirect all deep linked messages
// from: https://<subdomain>.slack.com/archives/<channel-id>/p<16-digit-timestamp>
// to: slack://channel?team=<team-id>&id=<channel-id>&message=<10-digit-6-decimal-timestamp>
browser: "/Applications/Slack.app",
match: [
'*.slack.com/client/*',
'*.slack.com/archives/*'
],
url({ url }) {
const parts = url.pathname.split('/')
// Return input URL if no expected path is found
if (parts.length < 2) return url
let team
switch (parts[1]) {
// For direct web links
case 'client':
team = parts[2]
parts.splice(2, 1) // Remove team identifier to match archives format
break
// For deep links
case 'archives':
const org = url.host.split('.')[0]
switch (org) {
case '<org subdomain>':
// Starts with a T and can be found in the web app URL for any channel in your org
team = '<team id>'
break
default:
// Return input URL if no team lookup available
return url
}
}
search = `team=${team}`
let channel = parts[2]
if (parts.length === 3) {
// If this is a link to a channel/user
search = `${search}&id=${channel}`
// If this is a link to a message
} else if (parts.length === 4) {
const message = parts[3].slice(1, 11) + '.' + parts[3].slice(11)
search = `${search}&channel=${channel}&message=${message}`
}
return {
protocol: "slack",
username: "",
password: "",
host: "channel",
port: null,
pathname: "",
search: search,
hash: ""
}
}
}
]
Also, may be worth linking this response to another related issue: #158
I wrote a more robust version of this which supports team hosts, enterprise hosts, and the generic app.slack.com
host. It's also just regex matches so if more URL formats are discovered it should be easy to add them to the list. It works in two parts, first doing a rewrite to the slack://
URL then using a handler for the slack
protocol to send to the Slack app. This lets us fall back to using the browser if the conversion wasn't successful. I've tested it with all of the following URL formats I could find for our Slack Enterprise and they work as expected:
Note that I did not add support for app_redirect
URLs as they can sometimes work but not universally. Any of the following are valid and can be forwarded via the browser:
But deeplinks only support IDs rather than names, so only the first could actually be converted. It's possible a regex could be made to match only IDs, but I couldn't find much information about the endpoint or the ID formats it supports so I opted to ignore it.
Also JavaScript isn't my language of choice, so there may be bugs and the code probably isn't optimal.
module.exports = {
handlers: [
{
match: ({ url }) => url.protocol === "slack",
browser: "/Applications/Slack.app"
}
],
rewrite: [
{
match: [
'*.slack.com/*',
],
url: function({ url, urlString }) {
const subdomain = url.host.slice(0, -10)
const pathParts = url.pathname.split("/")
let team, patterns = {}
if (subdomain != 'app') {
switch (subdomain) {
case '<teamname>':
case '<corpname>.enterprise':
team = 'T00000000'
break
default:
finicky.notify(
`No Slack team ID found for ${url.host}`,
`Add the team ID to ~/.finicky.js to allow direct linking to Slack.`
)
return url
}
if (subdomain.slice(-11) == '.enterprise') {
patterns = {
'file': [/\/files\/\w+\/(?<id>\w+)/]
}
} else {
patterns = {
'file': [/\/messages\/\w+\/files\/(?<id>\w+)/],
'team': [/(?:\/messages\/\w+)?\/team\/(?<id>\w+)/],
'channel': [/\/(?:messages|archives)\/(?<id>\w+)(?:\/(?<message>p\d+))?/]
}
}
} else {
patterns = {
'file': [
/\/client\/(?<team>\w+)\/\w+\/files\/(?<id>\w+)/,
/\/docs\/(?<team>\w+)\/(?<id>\w+)/
],
'team': [/\/client\/(?<team>\w+)\/\w+\/user_profile\/(?<id>\w+)/],
'channel': [/\/client\/(?<team>\w+)\/(?<id>\w+)(?:\/(?<message>[\d.]+))?/]
}
}
for (let [host, host_patterns] of Object.entries(patterns)) {
for (let pattern of host_patterns) {
let match = pattern.exec(url.pathname)
if (match) {
let search = `team=${team || match.groups.team}`
if (match.groups.id) {
search += `&id=${match.groups.id}`
}
if (match.groups.message) {
let message = match.groups.message
if (message.charAt(0) == 'p') {
message = message.slice(1, 11) + '.' + message.slice(11)
}
search += `&message=${message}`
}
let output = {
protocol: "slack",
username: "",
password: "",
host: host,
port: null,
pathname: "",
search: search,
hash: ""
}
let outputStr = `${output.protocol}://${output.host}?${output.search}`
finicky.log(`Rewrote Slack URL ${urlString} to deep link ${outputStr}`)
return output
}
}
}
return url
}
}
]
}
Hi,
I was trying to use a handler to open the Slack links in the Slack.app client on mac but it didn't work. The app opens up but not on the right message. Any thoughts on how to achieve that?
Here is the code I used: