Skip to content

Commit 4610320

Browse files
author
david
committed
github followers tool
1 parent 4194b2f commit 4610320

File tree

7 files changed

+289
-2
lines changed

7 files changed

+289
-2
lines changed

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,10 @@
1-
# github-followers
2-
If you follow a lot of other people on GitHub, you may find that some of them follow you back, but sometimes, they don't and that is sad. This little tool uses the GitHub API to look at your GitHub username and find discrepancies between who follows and who is followed.
1+
# GitHub Followers/Following Comparison Tool
2+
3+
A simple web application that uses the GitHub API to compare the followers and following lists of a GitHub user and highlights discrepancies between them. This tool helps you identify users who follow you but you don't follow back, and vice versa.
4+
5+
## Features
6+
7+
- **Compare Followers and Following**: Enter your GitHub username to see who follows you and who you follow.
8+
- **Identify Discrepancies**: Easily identify users who don't follow you back and users you don't follow back.
9+
- **Visual Statistics**: View the total number of followers, following, and the delta between them.
10+
- **Responsive Design**: A clean, modern, and responsive design that works well on all devices.

github.svg

Lines changed: 3 additions & 0 deletions
Loading

index.html

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>GitHub Followers/Following Comparison</title>
7+
<link rel="stylesheet" href="styles.css">
8+
</head>
9+
<body>
10+
<div class="content">
11+
<h1>GitHub Followers/Following Comparison</h1>
12+
<p class="description">
13+
If you follow a lot of other people on GitHub, you may find that some of them follow you back, but sometimes, they don't and that is sad. This little tool uses the GitHub API to look at your GitHub username and find discrepancies between who follows and who is followed. Then, if you wish, you can choose to rightsize those numbers...
14+
</p>
15+
<form id="github-form" class="centered-form">
16+
<label for="username">GitHub Username:</label>
17+
<input type="text" id="username" name="username" required>
18+
<button type="submit">Compare</button>
19+
</form>
20+
<p class="note">
21+
Note: It is normal to have discrepancies if you follow big projects or famous coding stars. However, for smaller accounts, there are fewer reasons for the follower/following count to be off-balance.
22+
</p>
23+
<div id="results">
24+
<h2>Results</h2>
25+
<div class="stats">
26+
<p id="followed-count">The number of users Followed = 0</p>
27+
<p id="following-count">The number of users Following = 0</p>
28+
<p id="delta-count">The delta is 0</p>
29+
</div>
30+
<div id="not-following-back">
31+
<h3>Not Following Back</h3>
32+
<ul></ul>
33+
</div>
34+
<div id="not-followed-back">
35+
<h3>Not Followed Back</h3>
36+
<ul></ul>
37+
</div>
38+
</div>
39+
</div>
40+
<footer>
41+
<div class="footer-row top-row">
42+
<a href="https://david-dickinson.com" target="_blank" class="footer-link">by David Dickinson</a>
43+
</div>
44+
<div class="footer-row bottom-row">
45+
<a href="https://www.linkedin.com/in/david-dickinson-b3704731" target="_blank" class="social-icon">
46+
<img src="linkedin.svg" alt="LinkedIn">
47+
</a>
48+
<a href="https://twitter.com/oneMore_David" target="_blank" class="social-icon">
49+
<img src="x.svg" alt="X">
50+
</a>
51+
<a href="https://github.com/rnddave" target="_blank" class="social-icon">
52+
<img src="github.svg" alt="GitHub">
53+
</a>
54+
</div>
55+
</footer>
56+
<script src="script.js"></script>
57+
</body>
58+
</html>

linkedin.svg

Lines changed: 3 additions & 0 deletions
Loading

script.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
document.getElementById('github-form').addEventListener('submit', async function(event) {
2+
event.preventDefault();
3+
const username = document.getElementById('username').value;
4+
const followers = await fetchGitHubUsers(`https://api.github.com/users/${username}/followers`);
5+
const following = await fetchGitHubUsers(`https://api.github.com/users/${username}/following`);
6+
7+
const followersSet = new Set(followers.map(user => user.login));
8+
const followingSet = new Set(following.map(user => user.login));
9+
10+
const notFollowingBack = Array.from(followingSet).filter(user => !followersSet.has(user));
11+
const notFollowedBack = Array.from(followersSet).filter(user => !followingSet.has(user));
12+
13+
displayResults(followers.length, following.length, following.length - followers.length, 'not-following-back', notFollowingBack);
14+
displayResults(followers.length, following.length, following.length - followers.length, 'not-followed-back', notFollowedBack);
15+
});
16+
17+
async function fetchGitHubUsers(url) {
18+
let users = [];
19+
let response = await fetch(url);
20+
while (response.ok) {
21+
let data = await response.json();
22+
users = users.concat(data);
23+
const linkHeader = response.headers.get('link');
24+
const nextLink = getNextLink(linkHeader);
25+
if (nextLink) {
26+
response = await fetch(nextLink);
27+
} else {
28+
break;
29+
}
30+
}
31+
return users;
32+
}
33+
34+
function getNextLink(linkHeader) {
35+
if (!linkHeader) return null;
36+
const links = linkHeader.split(',').map(link => link.trim());
37+
const nextLink = links.find(link => link.includes('rel="next"'));
38+
return nextLink ? nextLink.split(';')[0].slice(1, -1) : null;
39+
}
40+
41+
function displayResults(followersCount, followingCount, delta, elementId, users) {
42+
document.getElementById('followed-count').textContent = `The number of users Followed = ${followingCount}`;
43+
document.getElementById('following-count').textContent = `The number of users Following = ${followersCount}`;
44+
document.getElementById('delta-count').textContent = `The delta is ${delta}`;
45+
46+
const ul = document.getElementById(elementId).querySelector('ul');
47+
ul.innerHTML = '';
48+
users.forEach(user => {
49+
const li = document.createElement('li');
50+
li.textContent = user;
51+
ul.appendChild(li);
52+
});
53+
}

styles.css

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
body {
2+
display: flex;
3+
flex-direction: column;
4+
min-height: 100vh;
5+
margin: 0;
6+
font-family: 'Arial', sans-serif;
7+
background-color: #ecf0f1;
8+
color: #2c3e50;
9+
}
10+
11+
h1 {
12+
text-align: center;
13+
color: #3498db;
14+
margin-top: 20px;
15+
}
16+
17+
.description {
18+
text-align: center;
19+
font-size: 1.1em;
20+
margin: 20px auto;
21+
max-width: 600px;
22+
color: #2c3e50;
23+
}
24+
25+
.centered-form {
26+
display: flex;
27+
flex-direction: column;
28+
align-items: center;
29+
margin: 20px auto;
30+
padding: 20px;
31+
background-color: #fff;
32+
border-radius: 8px;
33+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
34+
max-width: 400px;
35+
}
36+
37+
#github-form label {
38+
font-size: 1.2em;
39+
margin-bottom: 10px;
40+
}
41+
42+
#github-form input {
43+
padding: 10px;
44+
font-size: 1em;
45+
margin-bottom: 10px;
46+
border: 1px solid #ccc;
47+
border-radius: 4px;
48+
width: 100%;
49+
box-sizing: border-box;
50+
}
51+
52+
#github-form button {
53+
padding: 10px 20px;
54+
font-size: 1em;
55+
color: #fff;
56+
background-color: #3498db;
57+
border: none;
58+
border-radius: 4px;
59+
cursor: pointer;
60+
transition: background-color 0.3s;
61+
}
62+
63+
#github-form button:hover {
64+
background-color: #2980b9;
65+
}
66+
67+
.note {
68+
text-align: center;
69+
font-size: 1em;
70+
margin: 20px auto;
71+
max-width: 600px;
72+
color: #7f8c8d;
73+
}
74+
75+
#results {
76+
text-align: center;
77+
margin: 20px auto;
78+
max-width: 600px;
79+
padding: 20px;
80+
background-color: #fff;
81+
border-radius: 8px;
82+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
83+
}
84+
85+
.stats {
86+
display: flex;
87+
flex-direction: column;
88+
gap: 10px;
89+
margin-bottom: 20px;
90+
}
91+
92+
.stats p {
93+
margin: 0;
94+
font-size: 1.2em;
95+
color: #3498db;
96+
}
97+
98+
#not-following-back, #not-followed-back {
99+
margin-top: 20px;
100+
}
101+
102+
footer {
103+
background-color: black;
104+
color: white;
105+
position: relative;
106+
width: 100%;
107+
text-align: center;
108+
padding: 10px 0;
109+
}
110+
111+
.footer-row {
112+
display: flex;
113+
justify-content: center;
114+
align-items: center;
115+
}
116+
117+
.top-row {
118+
font-size: 1.2em;
119+
margin-bottom: 10px;
120+
}
121+
122+
.footer-link {
123+
color: #ffffff;
124+
text-decoration: none;
125+
font-weight: bold;
126+
background: linear-gradient(90deg, red, orange, yellow, green, blue, indigo, violet);
127+
-webkit-background-clip: text;
128+
color: transparent;
129+
}
130+
131+
.footer-link:hover {
132+
text-decoration: underline;
133+
}
134+
135+
.bottom-row {
136+
display: flex;
137+
gap: 20px;
138+
}
139+
140+
.social-icon img {
141+
width: 30px;
142+
height: 30px;
143+
background-color: white;
144+
padding: 5px;
145+
border-radius: 4px;
146+
}
147+
148+
footer {
149+
position: fixed;
150+
bottom: 0;
151+
left: 0;
152+
right: 0;
153+
}
154+
155+
@media (max-height: 400px) {
156+
footer {
157+
position: static;
158+
}
159+
}

x.svg

Lines changed: 3 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)