Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Twitter integration #34

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion AWS_SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,24 @@
8. Navigate to the [`Tokens`](https://github.com/settings/tokens) page in your `GitHub` account settings
9. Create a new API Token, and give it the `Repo` permissions. Make sure to save this token!

### Twitter

1. Visit [Twitter Apps console](https://apps.twitter.com/)
2. Click on `Create New App`
3. In Application Details, enter `Name` as `babel-bot`, enter `Description` as `babel-bot twitter app`.
4. For `Website` enter `http://localhost:3000`
5. For `Callback URL` enter `http://localhost:3000/cb`
6. Click on `Create your Twitter application`
7. Verify you were redirected to a page with `babel-bot` as header
8. Navigate to `Keys and Access Tokens`
9. Copy and `Consumer Key (API Key)`, `Consumer Secret (API Secret)`, `Access Token` and `Access Token Secret`

### Final Steps

1. Go back to the `Lambda` dashboard in `AWS`, and click on your function to edit it
2. For `Code entry type`, choose `Upload a .ZIP file`
3. Run `yarn run package` in the root of this repository (make sure you've run `yarn` first), then upload the `function.zip` file in the root
4. Under `Environment variables`, add a variable for `GITHUB_API_KEY` and `GITHUB_SECRET`, using the values you setup in the `GitHub` section of this document
4. Under `Environment variables`, add a variable for `GITHUB_API_KEY` and `GITHUB_SECRET`, using the values you setup in the `GitHub` section of this document and add `TWITTER_CONSUMER_KEY`, `TWITTER_CONSUMER_SECRET`, `TWITTER_ACCESS_TOKEN_KEY`, `TWITTER_ACCESS_TOKEN_SECRET` using the values you setup in the `Twitter Apps console`
5. Click `Save`

If everything was done correctly, your bot should now be live! To see the execution logs, you can click the `Monitoring` tab on your function page in `Lambda`, then click `View logs in CloudWatch`.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
"common-tags": "^1.4.0",
"got": "^6.6.3",
"parse-diff": "^0.4.0",
"timing-safe-equal": "^1.0.0"
"timing-safe-equal": "^1.0.0",
"twitter": "^1.7.1"
},
"devDependencies": {
"aws-sdk": "^2.95.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
{
"action": "labeled",
"issue": {
"url": "https://api.github.com/repos/DrewML/babel/issues/1",
"repository_url": "https://api.github.com/repos/DrewML/babel",
"labels_url": "https://api.github.com/repos/DrewML/babel/issues/1/labels{/name}",
"comments_url": "https://api.github.com/repos/DrewML/babel/issues/1/comments",
"events_url": "https://api.github.com/repos/DrewML/babel/issues/1/events",
"html_url": "https://github.com/DrewML/babel/issues/1",
"id": 196255164,
"number": 1,
"title": "Test issue",
"user": {
"login": "DrewML",
"id": 5233399,
"avatar_url": "https://avatars.githubusercontent.com/u/5233399?v=3",
"gravatar_id": "",
"url": "https://api.github.com/users/DrewML",
"html_url": "https://github.com/DrewML",
"followers_url": "https://api.github.com/users/DrewML/followers",
"following_url": "https://api.github.com/users/DrewML/following{/other_user}",
"gists_url": "https://api.github.com/users/DrewML/gists{/gist_id}",
"starred_url": "https://api.github.com/users/DrewML/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/DrewML/subscriptions",
"organizations_url": "https://api.github.com/users/DrewML/orgs",
"repos_url": "https://api.github.com/users/DrewML/repos",
"events_url": "https://api.github.com/users/DrewML/events{/privacy}",
"received_events_url": "https://api.github.com/users/DrewML/received_events",
"type": "User",
"site_admin": false
},
"labels": [
{
"id": 502778608,
"url": "https://api.github.com/repos/DrewML/babel/labels/beginner-friendly",
"name": "Needs Info",
"color": "fbca04",
"default": false
}
],
"state": "open",
"locked": false,
"assignee": null,
"assignees": [],
"milestone": null,
"comments": 1,
"created_at": "2016-12-18T02:59:51Z",
"updated_at": "2016-12-18T03:16:49Z",
"closed_at": null,
"body": ""
},
"label": {
"id": 502778608,
"url": "https://api.github.com/repos/DrewML/babel/labels/beginner-friendly",
"name": "beginner-friendly",
"color": "fbca04",
"default": false
},
"repository": {
"id": 76754829,
"name": "babel",
"full_name": "DrewML/babel",
"owner": {
"login": "DrewML",
"id": 5233399,
"avatar_url": "https://avatars.githubusercontent.com/u/5233399?v=3",
"gravatar_id": "",
"url": "https://api.github.com/users/DrewML",
"html_url": "https://github.com/DrewML",
"followers_url": "https://api.github.com/users/DrewML/followers",
"following_url": "https://api.github.com/users/DrewML/following{/other_user}",
"gists_url": "https://api.github.com/users/DrewML/gists{/gist_id}",
"starred_url": "https://api.github.com/users/DrewML/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/DrewML/subscriptions",
"organizations_url": "https://api.github.com/users/DrewML/orgs",
"repos_url": "https://api.github.com/users/DrewML/repos",
"events_url": "https://api.github.com/users/DrewML/events{/privacy}",
"received_events_url": "https://api.github.com/users/DrewML/received_events",
"type": "User",
"site_admin": false
},
"private": false,
"html_url": "https://github.com/DrewML/babel",
"description": ":tropical_fish: Babel is a compiler for writing next generation JavaScript.",
"fork": true,
"url": "https://api.github.com/repos/DrewML/babel",
"forks_url": "https://api.github.com/repos/DrewML/babel/forks",
"keys_url": "https://api.github.com/repos/DrewML/babel/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/DrewML/babel/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/DrewML/babel/teams",
"hooks_url": "https://api.github.com/repos/DrewML/babel/hooks",
"issue_events_url": "https://api.github.com/repos/DrewML/babel/issues/events{/number}",
"events_url": "https://api.github.com/repos/DrewML/babel/events",
"assignees_url": "https://api.github.com/repos/DrewML/babel/assignees{/user}",
"branches_url": "https://api.github.com/repos/DrewML/babel/branches{/branch}",
"tags_url": "https://api.github.com/repos/DrewML/babel/tags",
"blobs_url": "https://api.github.com/repos/DrewML/babel/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/DrewML/babel/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/DrewML/babel/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/DrewML/babel/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/DrewML/babel/statuses/{sha}",
"languages_url": "https://api.github.com/repos/DrewML/babel/languages",
"stargazers_url": "https://api.github.com/repos/DrewML/babel/stargazers",
"contributors_url": "https://api.github.com/repos/DrewML/babel/contributors",
"subscribers_url": "https://api.github.com/repos/DrewML/babel/subscribers",
"subscription_url": "https://api.github.com/repos/DrewML/babel/subscription",
"commits_url": "https://api.github.com/repos/DrewML/babel/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/DrewML/babel/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/DrewML/babel/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/DrewML/babel/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/DrewML/babel/contents/{+path}",
"compare_url": "https://api.github.com/repos/DrewML/babel/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/DrewML/babel/merges",
"archive_url": "https://api.github.com/repos/DrewML/babel/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/DrewML/babel/downloads",
"issues_url": "https://api.github.com/repos/DrewML/babel/issues{/number}",
"pulls_url": "https://api.github.com/repos/DrewML/babel/pulls{/number}",
"milestones_url": "https://api.github.com/repos/DrewML/babel/milestones{/number}",
"notifications_url": "https://api.github.com/repos/DrewML/babel/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/DrewML/babel/labels{/name}",
"releases_url": "https://api.github.com/repos/DrewML/babel/releases{/id}",
"deployments_url": "https://api.github.com/repos/DrewML/babel/deployments",
"created_at": "2016-12-18T00:27:53Z",
"updated_at": "2016-12-18T02:59:42Z",
"pushed_at": "2016-12-17T15:37:46Z",
"git_url": "git://github.com/DrewML/babel.git",
"ssh_url": "[email protected]:DrewML/babel.git",
"clone_url": "https://github.com/DrewML/babel.git",
"svn_url": "https://github.com/DrewML/babel",
"homepage": "https://babeljs.io/",
"size": 15672,
"stargazers_count": 0,
"watchers_count": 0,
"language": "JavaScript",
"has_issues": true,
"has_downloads": true,
"has_wiki": true,
"has_pages": false,
"forks_count": 0,
"mirror_url": null,
"open_issues_count": 1,
"forks": 0,
"open_issues": 1,
"watchers": 0,
"default_branch": "master"
},
"sender": {
"login": "DrewML",
"id": 5233399,
"avatar_url": "https://avatars.githubusercontent.com/u/5233399?v=3",
"gravatar_id": "",
"url": "https://api.github.com/users/DrewML",
"html_url": "https://github.com/DrewML",
"followers_url": "https://api.github.com/users/DrewML/followers",
"following_url": "https://api.github.com/users/DrewML/following{/other_user}",
"gists_url": "https://api.github.com/users/DrewML/gists{/gist_id}",
"starred_url": "https://api.github.com/users/DrewML/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/DrewML/subscriptions",
"organizations_url": "https://api.github.com/users/DrewML/orgs",
"repos_url": "https://api.github.com/users/DrewML/repos",
"events_url": "https://api.github.com/users/DrewML/events{/privacy}",
"received_events_url": "https://api.github.com/users/DrewML/received_events",
"type": "User",
"site_admin": false
}
}
16 changes: 15 additions & 1 deletion src/handlers/issues/__tests__/labeled.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import fs from 'fs';

const wrongLabelPayload = require('./__fixtures__/other-label-added.json');
const needsInfoPayload = require('./__fixtures__/info-label-added.json');
const beginnerFriendlyPayload = require('./__fixtures__/beginner-friendly-label-added.json');
jest.mock('../../../github');
jest.mock('../../../twitter');

describe('Issue Opened Handler', () => {
describe('Issue Labeled Handler', () => {
it('should not add a comment if label !== "Needs Info"', () => {
handler(wrongLabelPayload);
const github = require('../../../github');
Expand All @@ -19,4 +21,16 @@ describe('Issue Opened Handler', () => {
const github = require('../../../github');
expect(github.addIssueComment).toHaveBeenCalledTimes(1);
});

it('should not tweet if label !== "beginner-friendly"', () => {
handler(wrongLabelPayload);
const twitter = require('../../../twitter');
expect(twitter.tweet).toHaveBeenCalledTimes(0);
});

it('should tweet if label === "beginner-friendly"', () => {
handler(beginnerFriendlyPayload);
const twitter = require('../../../twitter');
expect(twitter.tweet).toHaveBeenCalledTimes(1);
});
});
6 changes: 6 additions & 0 deletions src/handlers/issues/labeled.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
// @flow

import github from '../../github';
import twitter from '../../twitter';
import messages from '../../messages';

type LabeledIssuePayload = {
issue: {
user: { login: string; };
html_url: string;
number: number;
},
label: {
Expand All @@ -19,11 +21,15 @@ type LabeledIssuePayload = {

export default function({ label, issue, repository }: LabeledIssuePayload) {
const issueSubmitter = issue.user.login;
const issueHtmlUrl = issue.html_url;
const { login: owner } = repository.owner;
const { name: repo } = repository;

if (label.name === 'Needs Info') {
const msg = messages.needsInfo(issueSubmitter);
github.addIssueComment(issue.number, owner, repo, msg);
} else if(label.name === 'beginner-friendly') {
const msg = messages.tweetIssue(issueHtmlUrl);
twitter.tweet(msg);
}
}
5 changes: 5 additions & 0 deletions src/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ exports.newIssue = (username: string) => stripIndent`
for an invite.
`;

exports.tweetIssue = (issueURL: string) => stripIndent`
If you're looking to contribute to Babel, we have another beginner-friendly issue for you ! 📄
${issueURL}
`;

exports.replPreview = (url: string) => stripIndent`
Build successful! You can test your changes in the REPL here: ${url}
`;
14 changes: 14 additions & 0 deletions src/twitter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// @flow

import Twitter from 'twitter';

const client = new Twitter({
consumer_key: process.env.TWITTER_CONSUMER_KEY,
consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
access_token_key: process.env.TWITTER_ACCESS_TOKEN_KEY,
access_token_secret: process.env.TWITTER_ACCESS_TOKEN_SECRET
});

exports.tweet = (msg: string) => {
return client.post('statuses/update', { status: msg }).then((tweet) => tweet);
}
Loading