Skip to content

Commit 881570c

Browse files
authored
Scrapping Good First Issues (#1010)
* initial setup * pseudo code added * pseudo code added for githubFunc.js * token and repos from user's starred list added * function to fetch issues added * display of issues added * formating added & method 3 done * repo from trending on github added * all 3 methods completed * readme file updated * token.js added * minor refactoring * package files from root removed and DB updated * README and DB updated
1 parent 965450e commit 881570c

File tree

7 files changed

+416
-0
lines changed

7 files changed

+416
-0
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
let repoDB = [
2+
{
3+
"owner": "TesseractCoding",
4+
"name": "NeoAlgo"
5+
},
6+
{
7+
"owner": "HarshCasper",
8+
"name": "Rotten-Scripts"
9+
10+
},
11+
]
12+
13+
module.exports = repoDB;
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
const prompt = require("prompt-sync")()
2+
const git = require("./githubFunc")
3+
const chalk = require("chalk")
4+
5+
const printIssues = (arr) => {
6+
for (let i = 0; i < arr.length; i++) {
7+
console.log(chalk.yellow(`\n\n${i + 1}. ${arr[i]["repoOwner"]}/${arr[i]["repoName"]} (${chalk.white(arr[i]["issues"].length)}) : `))
8+
9+
let issues = arr[i]["issues"]
10+
if (issues.length == 0) {
11+
console.log(chalk.red(" None found!!"))
12+
continue
13+
}
14+
for (let j = 0; j < issues.length; j++) {
15+
console.log(chalk.blue(`\n ${j + 1}. ${issues[j]["title"]} `))
16+
console.log(` URL: ${chalk.green(issues[j]["url"])} `)
17+
}
18+
}
19+
}
20+
21+
const init = async () => {
22+
23+
console.log("\n================================")
24+
console.log("----Github Good First Issues----")
25+
console.log("================================\n")
26+
27+
console.log("1. DB file in the folder")
28+
console.log("2. Trending page of Github")
29+
console.log("3. Starred repo of an user")
30+
let method = prompt("Choose method to fetch repo from: ")
31+
32+
let username = null;
33+
if (Number(method) == 3) {
34+
username = prompt("Enter github username : ")
35+
}
36+
37+
console.log("\n...Fetching Data....Please wait...\n");
38+
let repo = await git.getRepoViaMethod(method, username)
39+
let issues = await git.getIssues(repo)
40+
41+
console.log(`\nINFO : ${chalk.yellow(repo.length)} repository(s) found!`);
42+
printIssues(issues);
43+
44+
console.log("\n---END---\n");
45+
}
46+
47+
// entry function
48+
init();
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Github_Good_First_Issues
2+
3+
- **Github_Good_First_Issues** is a script to scrap `Good First Issues` from GitHub Repositories.
4+
- It uses Github API to fetch repo and issues.
5+
- Then displays them to the user.
6+
7+
## Methods to fetch repositories
8+
9+
There are 3 ways to fetch repositories
10+
1. `DB.js` file in the folder *(That can be overwritten by the user)*
11+
2. [Github Trending Page](https://github.com/trending)
12+
3. Starred repositories of a user *(User input)*
13+
14+
## Setup instructions
15+
16+
- Get your [`Github Developer Token`](https://dev.to/gr2m/github-api-authentication-personal-access-tokens-53kd) and follow the steps there to generate your **Token key**
17+
- In a file named `token.js` paste the token.
18+
- Open terminal and do the following :
19+
- `cd Rotten-Scripts\JavaScript\Github_Good_First_Issues`
20+
- Run `npm install` to install all necessary dependencies
21+
- Run `node Github_Good_First_Issues.js` and Voila! you are ready to go 😉
22+
23+
## Output
24+
25+
### Method 1: via DB
26+
27+
![ Method 1](https://i.imgur.com/eeAq9FN.png)
28+
29+
### Method 2: Github Trending
30+
31+
![ Method 2.1](https://i.imgur.com/HFlGh6j.png)
32+
![ Method 2.2](https://i.imgur.com/3u8hXnv.png)
33+
34+
### Method 3: Starred repo(s) from user
35+
36+
![ Method 3](https://i.imgur.com/WJaCm5F.png)
37+
38+
## Author(s)
39+
40+
Hi I'm [Madhav Jha](https://github.com/jhamadhav) author of this script.
41+
42+
## Disclaimer
43+
44+
### Why use the github token?
45+
46+
It is true that github api is freely available for use by public but it is restricted to 60 requests per hour and for repositories with large number of issues this will exceed it's limit.
47+
So do get your [`Github Developer Token`](https://dev.to/gr2m/github-api-authentication-personal-access-tokens-53kd) before running this script
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
const fetch = require("node-fetch")
2+
const githubToken = require("./token.js")
3+
const parser = require("node-html-parser")
4+
const db = require("./DB")
5+
6+
const makeRequest = async (url) => {
7+
let res = await fetch(url,
8+
{
9+
headers: {
10+
authorization: `token ${githubToken.token}`
11+
}
12+
}
13+
)
14+
return res.json()
15+
}
16+
17+
const fetchHtml = async () => {
18+
let res = await fetch("https://github.com/trending")
19+
let body = await res.text()
20+
return body
21+
}
22+
23+
const getRepoFromTrending = async () => {
24+
let htmlData = await fetchHtml()
25+
htmlData = parser.parse(htmlData);
26+
27+
let repoList = []
28+
let articles = htmlData.querySelectorAll("article")
29+
articles.forEach(element => {
30+
31+
let h1 = element.querySelectorAll("h1")[0]
32+
let a = h1.querySelectorAll("a")[0]
33+
34+
let repoStr = a.innerText.trim();
35+
repoStr = repoStr.split("/")
36+
37+
let owner = repoStr[0].trim()
38+
let name = repoStr[1].replace("\n", "").trim()
39+
let data = {
40+
"owner": owner,
41+
"name": name,
42+
"url": `https://github.com/${owner}/${name}`
43+
}
44+
repoList.push(data)
45+
46+
});
47+
48+
return repoList
49+
}
50+
51+
const getRepoFromStarred = async (username) => {
52+
let repoList = await makeRequest(`https://api.github.com/users/${username}/starred`)
53+
repoList = repoList.map(elem => {
54+
return {
55+
"owner": elem["owner"]["login"],
56+
"name": elem["name"],
57+
"url": elem["svn_url"]
58+
}
59+
})
60+
return await repoList
61+
}
62+
63+
const getRepoViaMethod = async (method, username) => {
64+
method = Number(method)
65+
if (method == 1) {
66+
return db
67+
} else if (method == 2) {
68+
return getRepoFromTrending()
69+
} else if (method == 3) {
70+
return await getRepoFromStarred(username)
71+
}
72+
return []
73+
}
74+
75+
const getIssues = async (arr) => {
76+
let list = []
77+
for (let i = 0; i < arr.length; i++) {
78+
79+
let url = `https://api.github.com/repos/${arr[i]["owner"]}/${arr[i]["name"]}/issues?labels=good first issue`
80+
81+
let issues = await makeRequest(url)
82+
issues = issues.map(issue => {
83+
return {
84+
"title": issue["title"],
85+
"url": issue["html_url"]
86+
}
87+
})
88+
89+
let data = {
90+
"repoOwner": arr[i]["owner"],
91+
"repoName": arr[i]["name"],
92+
"issues": issues
93+
}
94+
list.push(data)
95+
}
96+
return list
97+
}
98+
99+
module.exports = { getRepoViaMethod, getIssues }

JavaScript/Github_Good_First_Issues/package-lock.json

Lines changed: 188 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)