mirror of
https://github.com/status-im/status-github-bot.git
synced 2025-01-13 23:06:02 +00:00
Implement rudimentary version of dynamic Slack to GitHub ID username mapping. Part of #12
This commit is contained in:
parent
f3ad8d03b9
commit
dc250d6d52
@ -9,4 +9,7 @@ WEBHOOK_SECRET=development
|
|||||||
WEBHOOK_PROXY_URL=https://smee.io/ZyQCjZTDPT3pd4SD
|
WEBHOOK_PROXY_URL=https://smee.io/ZyQCjZTDPT3pd4SD
|
||||||
|
|
||||||
# The "Bot User OAuth Access Token" of your Slack App
|
# The "Bot User OAuth Access Token" of your Slack App
|
||||||
SLACK_BOT_TOKEN=
|
SLACK_BOT_TOKEN=
|
||||||
|
|
||||||
|
# A "User Legacy Token" of your Slack App, used to access the "users.profile.get" API
|
||||||
|
SLACK_USER_TOKEN=
|
12
index.js
12
index.js
@ -1,11 +1,21 @@
|
|||||||
module.exports = (robot) => {
|
var MemCache = require('mem-cache')
|
||||||
|
var SlackGitHubCacheBuilder = require('./lib/retrieve-slack-github-users')
|
||||||
|
|
||||||
|
module.exports = async (robot) => {
|
||||||
console.log('Yay, the app was loaded!')
|
console.log('Yay, the app was loaded!')
|
||||||
|
|
||||||
|
var slackGitHubCache = new MemCache({ timeoutDisabled: true })
|
||||||
|
var slackCachePromise = SlackGitHubCacheBuilder.build(robot, slackGitHubCache)
|
||||||
|
|
||||||
require('./scripts/assign-new-pr-to-review')(robot)
|
require('./scripts/assign-new-pr-to-review')(robot)
|
||||||
require('./scripts/assign-approved-pr-to-test')(robot)
|
require('./scripts/assign-approved-pr-to-test')(robot)
|
||||||
require('./scripts/assign-to-bounty-awaiting-for-approval')(robot)
|
require('./scripts/assign-to-bounty-awaiting-for-approval')(robot)
|
||||||
require('./scripts/greet-new-contributor')(robot)
|
require('./scripts/greet-new-contributor')(robot)
|
||||||
|
|
||||||
|
await slackCachePromise
|
||||||
|
|
||||||
|
// Add scripts which require using the Slack/GitHub cache after this comment
|
||||||
|
|
||||||
// For more information on building apps:
|
// For more information on building apps:
|
||||||
// https://probot.github.io/docs/
|
// https://probot.github.io/docs/
|
||||||
|
|
||||||
|
124
lib/retrieve-slack-github-users.js
Normal file
124
lib/retrieve-slack-github-users.js
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
// Description:
|
||||||
|
// Configuration-related functionality
|
||||||
|
//
|
||||||
|
// Dependencies:
|
||||||
|
// "mem-cache": "0.0.5"
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// PombeirP
|
||||||
|
|
||||||
|
const { WebClient } = require('@slack/client')
|
||||||
|
const token = process.env.SLACK_USER_TOKEN || ''
|
||||||
|
|
||||||
|
module.exports.build = async (robot, cache) => {
|
||||||
|
const web = new WebClient(token)
|
||||||
|
await populateCache(robot, web, cache)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.getGitHubIdFromSlackUsername = (slackUsername, cache) => {
|
||||||
|
return cache.get(getSlackCacheKeyName(slackUsername))
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.getSlackUsernameFromGitHubId = (gitHubId, cache) => {
|
||||||
|
return cache.get(getGitHubCacheKeyName(gitHubId))
|
||||||
|
}
|
||||||
|
|
||||||
|
async function populateCache (robot, web, cache) {
|
||||||
|
robot.log.info('Populating Slack username cache...')
|
||||||
|
|
||||||
|
try {
|
||||||
|
const usersList = await web.users.list() // TODO: This call should be paginated to avoid hitting limits (memory, API): https://api.slack.com/docs/pagination#cursors
|
||||||
|
const activeUsersList = usersList.members.filter(u => !u.deleted && !u.is_bot && u.id !== 'USLACKBOT')
|
||||||
|
|
||||||
|
let gitHubFieldId = null
|
||||||
|
let usersMissingGitHubInfo = []
|
||||||
|
let usersContainingGitHubInfo = []
|
||||||
|
let rateLimitWait = 10000
|
||||||
|
let profileFetchPreviousBatchCount = 3
|
||||||
|
let profileFetchBatchCount = 0
|
||||||
|
for (let i = 0; i < activeUsersList.length;) {
|
||||||
|
const user = activeUsersList[i]
|
||||||
|
|
||||||
|
try {
|
||||||
|
++profileFetchBatchCount
|
||||||
|
const { profile } = await web.users.profile.get({ user: user.id, include_labels: !gitHubFieldId })
|
||||||
|
const username = profile.display_name_normalized || profile.real_name_normalized
|
||||||
|
|
||||||
|
if (!gitHubFieldId) {
|
||||||
|
// Find the field ID for the field with the 'Github ID' label
|
||||||
|
gitHubFieldId = findGitHubLabelId(profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gitHubFieldId) {
|
||||||
|
robot.log.warn(`No GitHub ID field found in profile (@${username})!`)
|
||||||
|
++i
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (profile.fields && profile.fields[gitHubFieldId]) {
|
||||||
|
const gitHubUsername = profile.fields[gitHubFieldId].value
|
||||||
|
robot.log.debug(`@${username} -> ${gitHubUsername}`)
|
||||||
|
|
||||||
|
cache.set(getSlackCacheKeyName(username), gitHubUsername)
|
||||||
|
cache.set(getGitHubCacheKeyName(gitHubUsername), username)
|
||||||
|
usersContainingGitHubInfo = usersContainingGitHubInfo.concat(username)
|
||||||
|
} else {
|
||||||
|
robot.log.warn(`@${username} (${user.id}) has no GitHub ID set`)
|
||||||
|
usersMissingGitHubInfo = usersMissingGitHubInfo.concat(username)
|
||||||
|
}
|
||||||
|
|
||||||
|
++i
|
||||||
|
await sleep(1500)
|
||||||
|
} catch (e) {
|
||||||
|
if (e.name === 'Error' && e.message === 'ratelimited') {
|
||||||
|
robot.log.trace(`Rate-limited, waiting ${rateLimitWait / 1000}s...`)
|
||||||
|
await sleep(rateLimitWait)
|
||||||
|
if (profileFetchBatchCount < profileFetchPreviousBatchCount) {
|
||||||
|
// If we managed to fetch fewer profiles than the last time we got rate-limited, then try increasing the wait period
|
||||||
|
rateLimitWait += 5000
|
||||||
|
}
|
||||||
|
profileFetchPreviousBatchCount = profileFetchBatchCount
|
||||||
|
profileFetchBatchCount = 0
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
robot.log.info(`Populated Slack username cache with ${usersContainingGitHubInfo.length} users: ${usersContainingGitHubInfo.map(s => '@' + s).join(', ')}`)
|
||||||
|
if (usersMissingGitHubInfo) {
|
||||||
|
robot.log.warn(`The following ${usersMissingGitHubInfo.length} Slack users have no GitHub info in their profiles: ${usersMissingGitHubInfo.map(s => '@' + s).join(', ')}`)
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
robot.log.error(`Error while populating Slack username cache: ${e}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findGitHubLabelId (profile) {
|
||||||
|
if (profile.fields) {
|
||||||
|
for (const fieldId in profile.fields) {
|
||||||
|
const field = profile.fields[fieldId]
|
||||||
|
if (field.label === 'Github ID') {
|
||||||
|
return fieldId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSlackCacheKeyName (slackUsername) {
|
||||||
|
return `Slack-${slackUsername}`
|
||||||
|
}
|
||||||
|
|
||||||
|
function getGitHubCacheKeyName (gitHubUsername) {
|
||||||
|
return `GitHub-${gitHubUsername}`
|
||||||
|
}
|
||||||
|
|
||||||
|
function timeout (ms) {
|
||||||
|
return new Promise(resolve => setTimeout(resolve, ms))
|
||||||
|
}
|
||||||
|
|
||||||
|
async function sleep (timeoutMs) {
|
||||||
|
await timeout(timeoutMs)
|
||||||
|
}
|
5
package-lock.json
generated
5
package-lock.json
generated
@ -4542,6 +4542,11 @@
|
|||||||
"mimic-fn": "1.1.0"
|
"mimic-fn": "1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"mem-cache": {
|
||||||
|
"version": "0.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/mem-cache/-/mem-cache-0.0.5.tgz",
|
||||||
|
"integrity": "sha1-EUCWcbMQEXPY3PQgcK5nv1Dzd/8="
|
||||||
|
},
|
||||||
"merge": {
|
"merge": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz",
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"eslint": "^4.16.0",
|
"eslint": "^4.16.0",
|
||||||
|
"mem-cache": "0.0.5",
|
||||||
"probot": "^5.0.0",
|
"probot": "^5.0.0",
|
||||||
"probot-config": "^0.1.0",
|
"probot-config": "^0.1.0",
|
||||||
"probot-gpg-status": "^0.5.4",
|
"probot-gpg-status": "^0.5.4",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user