Skip to content

Instantly share code, notes, and snippets.

@simonbs
Created October 26, 2018 22:56
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save simonbs/ab2f3de622a26077be2e383c03826ab7 to your computer and use it in GitHub Desktop.
Save simonbs/ab2f3de622a26077be2e383c03826ab7 to your computer and use it in GitHub Desktop.
Scriptable script that imports contacts from Slack. Existing contacts will also have their avatar and social profiles updated. The contacts must have their phone number set in Slack.
// In order to use the script,
// you must create a Slack bot
// with the user:read scope and
// generate an accesss token.
// The script will prompt you
// to copy the access token in.
// The token is stored securely
// in the keychain.
let containers = await ContactsContainer.all()
let contacts = await Contact.all(containers)
let users = await loadSlackUsers()
for (user of users) {
let profile = user["profile"]
let phone = trimPhone(profile["phone"])
if (phone.length <= 0) {
continue
}
let contact = contacts.find(e => {
return e.phoneNumbers
.filter(p => trimPhone(p.value) == phone)
.length > 0
})
let firstName = profile["first_name"]
if (firstName == null) {
continue
}
if (contact == null) {
let lastName = profile["last_name"]
contact = new Contact()
contact.givenName = firstName
contact.familyName = lastName
contact.phoneNumbers = [{
"label": "Work",
"value": phone
}]
await update(contact, user)
Contact.add(contact)
log("Added " + firstName)
} else {
await update(contact, user)
Contact.update(contact)
log("Updated " + firstName)
}
}
Contact.persistChanges()
async function update(contact, user) {
contact.image = await image(contact, user)
contact.socialProfiles = socialProfiles(contact, user)
}
function socialProfiles(contact, user) {
let all = contact.socialProfiles || []
let idx = all.findIndex(e => {
return e["label"] == "Slack"
})
let url = "slack://user?team="
+ user["team_id"]
+ "&id=" + user["id"]
let entry = {
"label": "Slack",
"service": "Slack",
"username": user["name"],
"url": url
}
if (idx != -1) {
all[idx] = entry
} else {
all.push(entry)
}
return all
}
async function image(contact, user) {
let profile = user["profile"]
let imgURL = profile["image_192"]
let imgReq = new Request(imgURL)
return await imgReq.loadImage()
}
async function loadSlackUsers() {
let token = await getToken()
let baseURL = "https://slack.com/api/users.list"
let url = baseURL + "?token=" + token
let req = new Request(url)
let json = await req.loadJSON()
let users = json["members"]
return users
}
async function getToken() {
let key = "import_contacts.slack.token"
if (Keychain.contains(key)) {
return Keychain.get(key)
} else {
let alert = new Alert()
alert.title = "Paste access token"
alert.message = "Create a Slack bot with the users:read scope, generate an access token and copy it here."
alert.addTextField("Token")
alert.addAction("Save in keychain")
alert.addCancelAction("Cancel")
let idx = await alert.present()
if (idx == -1) {
return null
}
let val = alert.textFieldValue(0)
if (val != null && val.length > 0) {
Keychain.set(key, val)
return val
} else {
return null
}
}
}
function trimPhone(phone) {
let result = phone
result = result.replace(/ /g, "")
if (result.startsWith("+45")) {
return result.slice(3)
} else {
return result
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment