const fetch = require('node-fetch')
const tonicExpress = require('@runkit/runkit/express-endpoint/1.0.0')
const truncate = require('truncate')
// Just provide the exports object to the tonicExpress helper
const app = tonicExpress(module.exports)
const bodyParser = require('body-parser')
app.use(bodyParser.json())
const MOCK_PAYLOAD = false
const SLACK_INCOMING_WEBHOOK = 'https://hooks.slack.com/services/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'
app.get('/test', async function (request, response) {
const resp = fetch(process.env.RUNKIT_ENDPOINT_URL, {
body: JSON.stringify(getMockPayload()),
headers: {
'content-type': 'application/json'
},
method: 'POST'
})
.then(res => res.json())
try {
response.type('application/json').status(200).send(await JSON.stringify(resp))
}
catch (err) {
response.status(500).send(err.stack)
}
})
const NO_VALUE = '-'
function truncateWithUrl(str, url) {
return truncate(str, 32, {
ellipsis: ` <${url}|...>`
})
}
function formatMessage(webhookPayload, user) {
const {sender, organization, repository} = webhookPayload
const name = user.name || user.login
const isPrivate = name === undefined
const displayName = name || 'Someone'
return {
text: `${displayName} just starred ${repository.name}!`,
attachments: [
{
'fallback': `${displayName} just starred ${repository.name}!`,
'color': '#fff179',
'author_name': user.login,
'author_link': user.html_url,
'author_icon': user.avatar_url,
'thumb_url': user.avatar_url,
'fields': [
!isPrivate && {
'title': 'Followers',
'value': typeof user.followers === 'number' ?
`<${user.html_url}?tab=followers|${user.followers}>` : NO_VALUE,
'short': true
},
!isPrivate && {
'title': 'Company',
'value': truncateWithUrl(user.company, user.html_url) || NO_VALUE,
'short': true
},
!isPrivate && {
'title': 'Bio',
'value': truncateWithUrl(user.bio, user.html_url) || NO_VALUE,
'short': true
},
!isPrivate && {
'title': 'Location',
'value': truncateWithUrl(user.location, user.html_url) || NO_VALUE,
'short': true
}
].filter(Boolean),
'footer': `<${repository.html_url}|${repository.full_name}> <${repository.html_url}/stargazers|(${repository.stargazers_count} ⭐)>`,
'footer_icon': 'https://assets-cdn.github.com/favicon.ico'
}
]
}
}
const getUser = MOCK_PAYLOAD ? getMockUser : getGHApiUser
app.get('/', function (request, response) {
response.status(200).end('NOOP!!')
})
app.post('/', async function (request, response) {
try {
const user = await getUser(request.body.sender.login)
await fetch(SLACK_INCOMING_WEBHOOK, {
body: JSON.stringify(formatMessage(request.body, user)),
headers: {
'content-type': 'application/json'
},
method: 'POST'
})
} catch (err) {
response.status(200).send(`Error: ${err.stack}`)
return
}
response.status(200).end('OK')
})
function getGHApiUser(login) {
return fetch(`https://api.github.com/users/${login}`).then(res => res.json())
}
async function getMockUser(login) {
return {
'login': login,
'id': 876086,
'avatar_url': 'https://avatars0.githubusercontent.com/u/876086?v=4',
'gravatar_id': '',
'url': `https://api.github.com/users/${login}`,
'html_url': `https://github.com/${login}`,
'followers_url': `https://api.github.com/users/${login}/followers`,
'following_url': `https://api.github.com/users/${login}/following{/other_user}`,
'gists_url': `https://api.github.com/users/${login}/gists{/gist_id}`,
'starred_url': `https://api.github.com/users/${login}/starred{/owner}{/repo}`,
'subscriptions_url': `https://api.github.com/users/${login}/subscriptions`,
'organizations_url': `https://api.github.com/users/${login}/orgs`,
'repos_url': `https://api.github.com/users/${login}/repos`,
'events_url': `https://api.github.com/users/${login}/events{/privacy}`,
'received_events_url': `https://api.github.com/users/${login}/received_events`,
'type': 'User',
'site_admin': false,
'name': 'Bjørge Næss',
//'company': '@sanity-io ',
'blog': 'http://sanity.io',
'location': 'Oslo, Norway, very long text, very long text, very long text, very long text, very long text, very long text, very long text, very long text, very long text, very long text, very long text',
'email': null,
'hireable': null,
'bio': 'abcdefghijklmnopqrstuvwxyzæøåabcdefghijklmnopqrstuvwxyzæøåabcdefghijklmnopqrstuvwxyzæøåabcdefghijklmnopqrstuvwxyzæøå',
'public_repos': 79,
'public_gists': 35,
'followers': 42,
'following': 17,
'created_at': '2011-06-26T01:07:32Z',
'updated_at': '2018-04-03T16:39:04Z'
}
}
function getMockPayload() {
return {
'action': 'started',
'repository': {
'id': 79375056,
'name': 'sanity',
'full_name': 'sanity-io/sanity',
'owner': {
'login': 'sanity-io',
'id': 17177659,
'avatar_url': 'https://avatars2.githubusercontent.com/u/17177659?v=4',
'gravatar_id': '',
'url': 'https://api.github.com/users/sanity-io',
'html_url': 'https://github.com/sanity-io',
'followers_url': 'https://api.github.com/users/sanity-io/followers',
'following_url': 'https://api.github.com/users/sanity-io/following{/other_user}',
'gists_url': 'https://api.github.com/users/sanity-io/gists{/gist_id}',
'starred_url': 'https://api.github.com/users/sanity-io/starred{/owner}{/repo}',
'subscriptions_url': 'https://api.github.com/users/sanity-io/subscriptions',
'organizations_url': 'https://api.github.com/users/sanity-io/orgs',
'repos_url': 'https://api.github.com/users/sanity-io/repos',
'events_url': 'https://api.github.com/users/sanity-io/events{/privacy}',
'received_events_url': 'https://api.github.com/users/sanity-io/received_events',
'type': 'Organization',
'site_admin': false
},
'private': false,
'html_url': 'https://github.com/sanity-io/sanity',
'description': 'Sanity Content Studio – Collaborate in real-time on structured data',
'fork': false,
'url': 'https://api.github.com/repos/sanity-io/sanity',
'forks_url': 'https://api.github.com/repos/sanity-io/sanity/forks',
'keys_url': 'https://api.github.com/repos/sanity-io/sanity/keys{/key_id}',
'collaborators_url': 'https://api.github.com/repos/sanity-io/sanity/collaborators{/collaborator}',
'teams_url': 'https://api.github.com/repos/sanity-io/sanity/teams',
'hooks_url': 'https://api.github.com/repos/sanity-io/sanity/hooks',
'issue_events_url': 'https://api.github.com/repos/sanity-io/sanity/issues/events{/number}',
'events_url': 'https://api.github.com/repos/sanity-io/sanity/events',
'assignees_url': 'https://api.github.com/repos/sanity-io/sanity/assignees{/user}',
'branches_url': 'https://api.github.com/repos/sanity-io/sanity/branches{/branch}',
'tags_url': 'https://api.github.com/repos/sanity-io/sanity/tags',
'blobs_url': 'https://api.github.com/repos/sanity-io/sanity/git/blobs{/sha}',
'git_tags_url': 'https://api.github.com/repos/sanity-io/sanity/git/tags{/sha}',
'git_refs_url': 'https://api.github.com/repos/sanity-io/sanity/git/refs{/sha}',
'trees_url': 'https://api.github.com/repos/sanity-io/sanity/git/trees{/sha}',
'statuses_url': 'https://api.github.com/repos/sanity-io/sanity/statuses/{sha}',
'languages_url': 'https://api.github.com/repos/sanity-io/sanity/languages',
'stargazers_url': 'https://api.github.com/repos/sanity-io/sanity/stargazers',
'contributors_url': 'https://api.github.com/repos/sanity-io/sanity/contributors',
'subscribers_url': 'https://api.github.com/repos/sanity-io/sanity/subscribers',
'subscription_url': 'https://api.github.com/repos/sanity-io/sanity/subscription',
'commits_url': 'https://api.github.com/repos/sanity-io/sanity/commits{/sha}',
'git_commits_url': 'https://api.github.com/repos/sanity-io/sanity/git/commits{/sha}',
'comments_url': 'https://api.github.com/repos/sanity-io/sanity/comments{/number}',
'issue_comment_url': 'https://api.github.com/repos/sanity-io/sanity/issues/comments{/number}',
'contents_url': 'https://api.github.com/repos/sanity-io/sanity/contents/{+path}',
'compare_url': 'https://api.github.com/repos/sanity-io/sanity/compare/{base}...{head}',
'merges_url': 'https://api.github.com/repos/sanity-io/sanity/merges',
'archive_url': 'https://api.github.com/repos/sanity-io/sanity/{archive_format}{/ref}',
'downloads_url': 'https://api.github.com/repos/sanity-io/sanity/downloads',
'issues_url': 'https://api.github.com/repos/sanity-io/sanity/issues{/number}',
'pulls_url': 'https://api.github.com/repos/sanity-io/sanity/pulls{/number}',
'milestones_url': 'https://api.github.com/repos/sanity-io/sanity/milestones{/number}',
'notifications_url': 'https://api.github.com/repos/sanity-io/sanity/notifications{?since,all,participating}',
'labels_url': 'https://api.github.com/repos/sanity-io/sanity/labels{/name}',
'releases_url': 'https://api.github.com/repos/sanity-io/sanity/releases{/id}',
'deployments_url': 'https://api.github.com/repos/sanity-io/sanity/deployments',
'created_at': '2017-01-18T19:19:02Z',
'updated_at': '2018-02-17T05:15:08Z',
'pushed_at': '2018-02-16T16:56:36Z',
'git_url': 'git://github.com/sanity-io/sanity.git',
'ssh_url': 'git@github.com:sanity-io/sanity.git',
'clone_url': 'https://github.com/sanity-io/sanity.git',
'svn_url': 'https://github.com/sanity-io/sanity',
'homepage': 'https://sanity.io',
'size': 22552,
'stargazers_count': 308,
'watchers_count': 308,
'language': 'JavaScript',
'has_issues': true,
'has_projects': true,
'has_downloads': true,
'has_wiki': false,
'has_pages': false,
'forks_count': 14,
'mirror_url': null,
'archived': false,
'open_issues_count': 61,
'license': {
'key': 'mit',
'name': 'MIT License',
'spdx_id': 'MIT',
'url': 'https://api.github.com/licenses/mit'
},
'forks': 14,
'open_issues': 61,
'watchers': 308,
'default_branch': 'next'
},
'organization': {
'login': 'sanity-io',
'id': 17177659,
'url': 'https://api.github.com/orgs/sanity-io',
'repos_url': 'https://api.github.com/orgs/sanity-io/repos',
'events_url': 'https://api.github.com/orgs/sanity-io/events',
'hooks_url': 'https://api.github.com/orgs/sanity-io/hooks',
'issues_url': 'https://api.github.com/orgs/sanity-io/issues',
'members_url': 'https://api.github.com/orgs/sanity-io/members{/member}',
'public_members_url': 'https://api.github.com/orgs/sanity-io/public_members{/member}',
'avatar_url': 'https://avatars2.githubusercontent.com/u/17177659?v=4',
'description': 'API first CMS construction kit'
},
'sender': {
'login': 'bjoerge',
'id': 876086,
'avatar_url': 'https://avatars0.githubusercontent.com/u/876086?v=4',
'gravatar_id': '',
'url': 'https://api.github.com/users/bjoerge',
'html_url': 'https://github.com/bjoerge',
'followers_url': 'https://api.github.com/users/bjoerge/followers',
'following_url': 'https://api.github.com/users/bjoerge/following{/other_user}',
'gists_url': 'https://api.github.com/users/bjoerge/gists{/gist_id}',
'starred_url': 'https://api.github.com/users/bjoerge/starred{/owner}{/repo}',
'subscriptions_url': 'https://api.github.com/users/bjoerge/subscriptions',
'organizations_url': 'https://api.github.com/users/bjoerge/orgs',
'repos_url': 'https://api.github.com/users/bjoerge/repos',
'events_url': 'https://api.github.com/users/bjoerge/events{/privacy}',
'received_events_url': 'https://api.github.com/users/bjoerge/received_events',
'type': 'User',
'site_admin': false
}
}
}