Last active
January 2, 2019 12:27
-
-
Save cpojer/25a0c4af786360a81d9f508b3962e031 to your computer and use it in GitHub Desktop.
GitHub RN Issue Parser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
node_modules | |
comments.json | |
comments.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const {GraphQLClient} = require('graphql-request'); | |
const fs = require('fs'); | |
const path = require('path'); | |
const CACHE_PATH = path.join(__dirname, 'comments.json'); | |
const GITHUB_API = 'https://api.github.com/graphql'; | |
const GITHUB_TOKEN = '<YOUR TOKEN HERE>'; | |
const OUTPUT_FILE = path.join(__dirname, 'comments.md'); | |
const REACTIONS_FRAGMENT = variables => ` | |
reactions(first:100${variables ? ',' + variables : ''}) { | |
edges { | |
node { | |
content, | |
} | |
} | |
pageInfo { | |
endCursor, | |
hasNextPage | |
} | |
} | |
`; | |
const COMMENTS_FRAGMENT = () => ` | |
id, | |
body, | |
url, | |
author { | |
... on User { | |
name | |
} | |
} | |
${REACTIONS_FRAGMENT()} | |
`; | |
const COMMENT_FRAGMENT = id => variables => ` | |
{ | |
node(id:"${id}") { | |
... on IssueComment { | |
${REACTIONS_FRAGMENT(variables)} | |
} | |
} | |
} | |
`; | |
const ISSUE_QUERY = variables => ` | |
{ | |
repository(owner:"react-native-community", name:"discussions-and-proposals") { | |
issue(number:64) { | |
comments(first:100${variables ? ',' + variables : ''}) { | |
edges { | |
node { | |
${COMMENTS_FRAGMENT()} | |
} | |
} | |
pageInfo { | |
endCursor, | |
hasNextPage | |
} | |
} | |
} | |
} | |
} | |
`; | |
const REACTIONS_WEIGHT = { | |
CONFUSED: -1, | |
HEART: 1, | |
HOORAY: 1, | |
LAUGH: -1, | |
THUMBS_DOWN: -1, | |
THUMBS_UP: 1, | |
}; | |
const COMMENT_TITLE_MAP = { | |
'MDEyOklzc3VlQ29tbWVudDQ0NDk3MTIyNA==': 'react-native link issues', | |
'MDEyOklzc3VlQ29tbWVudDQ0NDg5NzU2NQ==': 'Native API Support', | |
'MDEyOklzc3VlQ29tbWVudDQ0NTAyODYwMg==': 'File System API', | |
'MDEyOklzc3VlQ29tbWVudDQ0NTEwNjUyOA==': 'AsyncStorage is broken', | |
'MDEyOklzc3VlQ29tbWVudDQ0NDk4NDM1OA==': 'Android Image Flickering', | |
'MDEyOklzc3VlQ29tbWVudDQ0NDk3NDE5Nw==': 'Debugging Style Issues', | |
'MDEyOklzc3VlQ29tbWVudDQ0NTA4NTc4Nw==': 'Official RN Navigation Solution', | |
'MDEyOklzc3VlQ29tbWVudDQ0NTAxOTYwNg==': 'Battery Usage', | |
'MDEyOklzc3VlQ29tbWVudDQ0NTAxNDE4Mw==': 'React Native Target Audience', | |
'MDEyOklzc3VlQ29tbWVudDQ0NDk4MzI4OQ==': 'Expo & Ejecting', | |
'MDEyOklzc3VlQ29tbWVudDQ0NTUwOTU1Nw==': 'TypeScript Support', | |
'MDEyOklzc3VlQ29tbWVudDQ0NTAxOTI5Ng==': 'Latex / MathML Support', | |
'MDEyOklzc3VlQ29tbWVudDQ0NTA2OTE0Ng==': 'Image URIs on iOS', | |
'MDEyOklzc3VlQ29tbWVudDQ0NDk4NTI4Mg==': 'Animated Flow Support', | |
}; | |
const IGNORED_COMMENTS = { | |
'MDEyOklzc3VlQ29tbWVudDQ0NDkxMzkwNQ==': | |
'This comment has few votes and lists many issues', | |
}; | |
const PRINT_COMMENT = ({ | |
body, | |
tags, | |
title, | |
upvotes, | |
url, | |
}) => `${title} [#](${url}) | |
${body} | |
* **Votes:** ${upvotes}${tags.length ? `\n* **Tags:** ${tags.join(', ')}` : ''} | |
* **Estimated time to fix:** | |
* **Point of contact:** | |
* **Comment by Facebook:** | |
`; | |
const fetchAll = async (client, queryFn, selector) => { | |
return fetchRemaining( | |
selector(await client.request(queryFn())), | |
client, | |
queryFn, | |
selector, | |
); | |
}; | |
const fetchRemaining = async (data, client, queryFn, selector) => { | |
while (data.pageInfo.hasNextPage) { | |
const {edges, pageInfo} = selector( | |
await client.request(queryFn(`after:"${data.pageInfo.endCursor}"`)), | |
); | |
data.edges.push(...edges); | |
data.pageInfo = pageInfo; | |
} | |
return data; | |
}; | |
const fetchAllComments = async () => { | |
try { | |
return JSON.parse(fs.readFileSync(CACHE_PATH, 'utf8')); | |
} catch (e) {} | |
const client = new GraphQLClient(GITHUB_API, { | |
headers: { | |
authorization: `bearer ${GITHUB_TOKEN}`, | |
}, | |
}); | |
const comments = await fetchAll( | |
client, | |
ISSUE_QUERY, | |
data => data.repository.issue.comments, | |
); | |
// Fetch all reactions for all comments | |
await Promise.all( | |
comments.edges.map(async edge => { | |
edge.node.reactions = await fetchRemaining( | |
edge.node.reactions, | |
client, | |
COMMENT_FRAGMENT(edge.node.id), | |
data => data.node.reactions, | |
); | |
return edge; | |
}), | |
); | |
fs.writeFileSync(CACHE_PATH, JSON.stringify(comments), 'utf8'); | |
return comments; | |
}; | |
const processComments = rawComments => { | |
// Flatten the data structure and sum up all the reactions | |
const comments = []; | |
rawComments.edges.forEach(({node: comment}) => { | |
const {id, body, author, reactions, url} = comment; | |
const upvotes = reactions.edges.reduce( | |
(count, {node: {content}}) => count + REACTIONS_WEIGHT[content], | |
0, | |
); | |
if ( | |
!IGNORED_COMMENTS[id] && | |
author.name !== 'Christoph Nakazawa' && | |
upvotes > 0 | |
) { | |
comments.push({ | |
id, | |
body, | |
upvotes, | |
url, | |
}); | |
} | |
}); | |
comments.sort((a, b) => b.upvotes - a.upvotes); | |
// Format comments | |
const allContent = comments.map(comment => { | |
const {id} = comment; | |
const content = comment.body.split('\n'); | |
content[0] = content[0].trim(); | |
if (content[0].startsWith('**')) { | |
content[0] = '## ' + content[0].replace(/\*\*/g, ''); | |
} else if (content[0].startsWith('##')) { | |
content[0] = '## ' + content[0].replace(/#/g, ''); | |
} else if (COMMENT_TITLE_MAP[id]) { | |
// upvotes-- :P | |
content.unshift('## ' + COMMENT_TITLE_MAP[id]); | |
} else { | |
throw new Error(`Comment ${id} has no title: ${body}`); | |
} | |
const [title, ...body] = content; | |
comment.title = title.trim(); | |
comment.body = | |
body | |
.join('\n') | |
.replace(/#([A-z\-]{2,})/g, '') | |
.trim() + '\n'; | |
comment.tags = []; | |
body | |
.join('\n') | |
.replace(/#([A-z\-]{2,})/g, (_, tag) => comment.tags.push(tag)); | |
return PRINT_COMMENT(comment); | |
}); | |
fs.writeFileSync(OUTPUT_FILE, allContent.join('\n'), 'utf8'); | |
}; | |
(async () => processComments(await fetchAllComments()))().catch(error => | |
console.log(error), | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "react-native-github-issue", | |
"version": "1.0.0", | |
"main": "index.js", | |
"license": "MIT", | |
"dependencies": { | |
"graphql-request": "^1.8.2", | |
"prettier": "^1.15.3" | |
}, | |
"scripts": { | |
"prettier": "prettier index.js --write --single-quote --trailing-comma=all --no-bracket-spacing" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. | |
# yarn lockfile v1 | |
[email protected]: | |
version "2.2.2" | |
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-2.2.2.tgz#a47ff4f7fc712daba8f6a695a11c948440d45723" | |
dependencies: | |
node-fetch "2.1.2" | |
whatwg-fetch "2.0.4" | |
graphql-request@^1.8.2: | |
version "1.8.2" | |
resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-1.8.2.tgz#398d10ae15c585676741bde3fc01d5ca948f8fbe" | |
dependencies: | |
cross-fetch "2.2.2" | |
[email protected]: | |
version "2.1.2" | |
resolved "http://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5" | |
prettier@^1.15.3: | |
version "1.15.3" | |
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.15.3.tgz#1feaac5bdd181237b54dbe65d874e02a1472786a" | |
[email protected]: | |
version "2.0.4" | |
resolved "http://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment