Skip to content

Commit f29fb56

Browse files
committed
Merge branch 'anuraghazra-master'
2 parents 7a067ba + 474229f commit f29fb56

File tree

6 files changed

+269
-205
lines changed

6 files changed

+269
-205
lines changed

readme.md

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -80,20 +80,43 @@ Visit <https://indiafightscorona.giveindia.org> and make a small donation to hel
8080

8181
# Features
8282

83-
- [GitHub Stats Card](#github-stats-card)
84-
- [GitHub Extra Pins](#github-extra-pins)
85-
- [Top Languages Card](#top-languages-card)
86-
- [Wakatime Week Stats](#wakatime-week-stats)
87-
- [Themes](#themes)
88-
- [Responsive Card Theme](#responsive-card-theme)
89-
- [Customization](#customization)
90-
- [Common Options](#common-options)
91-
- [Stats Card Exclusive Options](#stats-card-exclusive-options)
92-
- [Repo Card Exclusive Options](#repo-card-exclusive-options)
93-
- [Language Card Exclusive Options](#language-card-exclusive-options)
94-
- [Wakatime Card Exclusive Option](#wakatime-card-exclusive-options)
95-
- [Deploy Yourself](#deploy-on-your-own-vercel-instance)
83+
- [Features](#features)
84+
- [GitHub Stats Card](#github-stats-card)
85+
- [Hiding individual stats](#hiding-individual-stats)
86+
- [Adding private contributions count to total commits count](#adding-private-contributions-count-to-total-commits-count)
87+
- [Showing icons](#showing-icons)
88+
- [Themes](#themes)
89+
- [All inbuilt themes](#all-inbuilt-themes)
90+
- [Responsive Card Theme](#responsive-card-theme)
91+
- [Use the transparent theme](#use-the-transparent-theme)
92+
- [Add transparent alpha channel to a themes bg\_color](#add-transparent-alpha-channel-to-a-themes-bg_color)
93+
- [Use GitHub's theme context tag](#use-githubs-theme-context-tag)
94+
- [Use GitHub's new media feature](#use-githubs-new-media-feature)
95+
- [Customization](#customization)
96+
- [Common Options](#common-options)
97+
- [Gradient in bg\_color](#gradient-in-bg_color)
98+
- [Stats Card Exclusive Options](#stats-card-exclusive-options)
99+
- [Repo Card Exclusive Options](#repo-card-exclusive-options)
100+
- [Language Card Exclusive Options](#language-card-exclusive-options)
101+
- [Wakatime Card Exclusive Options](#wakatime-card-exclusive-options)
102+
- [GitHub Extra Pins](#github-extra-pins)
103+
- [Usage](#usage)
104+
- [Demo](#demo)
105+
- [Top Languages Card](#top-languages-card)
106+
- [Usage](#usage-1)
107+
- [Exclude individual repositories](#exclude-individual-repositories)
108+
- [Hide individual languages](#hide-individual-languages)
109+
- [Show more languages](#show-more-languages)
110+
- [Compact Language Card Layout](#compact-language-card-layout)
111+
- [Demo](#demo-1)
112+
- [Wakatime Week Stats](#wakatime-week-stats)
113+
- [Demo](#demo-2)
114+
- [All Demos](#all-demos)
115+
- [Quick Tip (Align The Repo Cards)](#quick-tip-align-the-repo-cards)
116+
- [Deploy on your own Vercel instance](#deploy-on-your-own-vercel-instance)
117+
- [:film\_projector: Check Out Step By Step Video Tutorial By @codeSTACKr](#film_projector-check-out-step-by-step-video-tutorial-by-codestackr)
96118
- [Keep your fork up to date](#keep-your-fork-up-to-date)
119+
- [:sparkling\_heart: Support the project](#sparkling_heart-support-the-project)
97120

98121
# GitHub Stats Card
99122

@@ -259,12 +282,12 @@ You can customize the appearance of your `Stats Card` or `Repo Card` however you
259282
- `bg_color` - Card's background color _(hex color)_ **or** a gradient in the form of _angle,start,end_. Default: `fffefe`
260283
- `hide_border` - Hides the card's border _(boolean)_. Default: `false`
261284
- `theme` - name of the theme, choose from [all available themes](./themes/README.md). Default: `default` theme.
262-
- `cache_seconds` - set the cache header manually _(min: 7200, max: 86400)_. Default: `14400 seconds (4 hours)`.
285+
- `cache_seconds` - set the cache header manually _(min: 14400, max: 86400)_. Default: `14400 seconds (4 hours)`.
263286
- `locale` - set the language in the card _(e.g. cn, de, es, etc.)_. Default: `en`.
264287
- `border_radius` - Corner rounding on the card. Default: `4.5`.
265288

266289
> **Warning**
267-
> We use caching to decrease the load on our servers (see https://github.com/anuraghazra/github-readme-stats/issues/1471#issuecomment-1271551425). Our cards have a default cache of 4 hours (14400 seconds). Also, note that the cache is clamped to a minimum of 4 hours and a maximum of 24 hours.
290+
> We use caching to decrease the load on our servers (see <https://github.com/anuraghazra/github-readme-stats/issues/1471#issuecomment-1271551425>). Our cards have a default cache of 4 hours (14400 seconds). Also, note that the cache is clamped to a minimum of 4 hours and a maximum of 24 hours.
268291
269292
##### Gradient in bg_color
270293

@@ -353,7 +376,7 @@ Use [show_owner](#customization) variable to include the repo's owner username
353376
The top languages card shows a GitHub user's most frequently used top language.
354377

355378
> **Note**
356-
> Top Languages does not indicate my skill level or anything like that; it's a GitHub metric to determine which languages have the most code on GitHub. It is a new feature of github-readme-stats._
379+
> Top Languages does not indicate my skill level or anything like that; it's a GitHub metric to determine which languages have the most code on GitHub. It is a new feature of github-readme-stats.
357380
358381
### Usage
359382

@@ -497,7 +520,7 @@ By default, GitHub does not lay out the cards side by side. To do that, you can
497520

498521
## Deploy on your own Vercel instance
499522

500-
#### [Check Out Step By Step Video Tutorial By @codeSTACKr](https://youtu.be/n6d4KHSKqGk?t=107)
523+
#### :film_projector: [Check Out Step By Step Video Tutorial By @codeSTACKr](https://youtu.be/n6d4KHSKqGk?t=107)
501524

502525
> **Warning**
503526
> If you are on the [hobby (i.e. free)](https://vercel.com/pricing) Vercel plan, please make sure you change the `maxDuration` parameter in the [vercel.json](https://github.com/anuraghazra/github-readme-stats/blob/master/vercel.json) file from `30` to `10` (see [#1416](https://github.com/anuraghazra/github-readme-stats/issues/1416#issuecomment-950275476) for more information).

src/common/retryer.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ const retryer = async (fetcher, variables, retries = 0) => {
4545
// prettier-ignore
4646
// also checking for bad credentials if any tokens gets invalidated
4747
const isBadCredential = err.response.data && err.response.data.message === "Bad credentials";
48-
const isAccountSuspended = err.response.data && err.response.data.message === "Sorry. Your account was suspended.";
48+
const isAccountSuspended =
49+
err.response.data &&
50+
err.response.data.message === "Sorry. Your account was suspended.";
4951

5052
if (isBadCredential || isAccountSuspended) {
5153
logger.log(`PAT_${retries + 1} Failed`);

src/fetchers/stats-fetcher.js

Lines changed: 103 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// @ts-check
22
import axios from "axios";
3+
import * as dotenv from "dotenv";
34
import githubUsernameRegex from "github-username-regex";
45
import { calculateRank } from "../calculateRank.js";
56
import { retryer } from "../common/retryer.js";
@@ -11,46 +12,74 @@ import {
1112
wrapTextMultiline,
1213
} from "../common/utils.js";
1314

15+
dotenv.config();
16+
17+
// GraphQL queries.
18+
const GRAPHQL_REPOS_FIELD = `
19+
repositories(first: 100, ownerAffiliations: OWNER, orderBy: {direction: DESC, field: STARGAZERS}, after: $after) {
20+
totalCount
21+
nodes {
22+
name
23+
stargazers {
24+
totalCount
25+
}
26+
}
27+
pageInfo {
28+
hasNextPage
29+
endCursor
30+
}
31+
}
32+
`;
33+
34+
const GRAPHQL_REPOS_QUERY = `
35+
query userInfo($login: String!, $after: String) {
36+
user(login: $login) {
37+
${GRAPHQL_REPOS_FIELD}
38+
}
39+
}
40+
`;
41+
42+
const GRAPHQL_STATS_QUERY = `
43+
query userInfo($login: String!, $after: String) {
44+
user(login: $login) {
45+
name
46+
login
47+
contributionsCollection {
48+
totalCommitContributions
49+
restrictedContributionsCount
50+
}
51+
repositoriesContributedTo(first: 1, contributionTypes: [COMMIT, ISSUE, PULL_REQUEST, REPOSITORY]) {
52+
totalCount
53+
}
54+
pullRequests(first: 1) {
55+
totalCount
56+
}
57+
openIssues: issues(states: OPEN) {
58+
totalCount
59+
}
60+
closedIssues: issues(states: CLOSED) {
61+
totalCount
62+
}
63+
followers {
64+
totalCount
65+
}
66+
${GRAPHQL_REPOS_FIELD}
67+
}
68+
}
69+
`;
70+
1471
/**
1572
* Stats fetcher object.
1673
*
1774
* @param {import('axios').AxiosRequestHeaders} variables Fetcher variables.
1875
* @param {string} token GitHub token.
19-
* @returns {Promise<import('../common/types').StatsFetcherResponse>} Stats fetcher response.
76+
* @returns {Promise<import('../common/types').Fetcher>} Stats fetcher response.
2077
*/
2178
const fetcher = (variables, token) => {
79+
const query = !variables.after ? GRAPHQL_STATS_QUERY : GRAPHQL_REPOS_QUERY;
2280
return request(
2381
{
24-
query: `
25-
query userInfo($login: String!) {
26-
user(login: $login) {
27-
name
28-
login
29-
contributionsCollection {
30-
totalCommitContributions
31-
restrictedContributionsCount
32-
}
33-
repositoriesContributedTo(contributionTypes: [COMMIT, ISSUE, PULL_REQUEST, REPOSITORY]) {
34-
totalCount
35-
}
36-
pullRequests {
37-
totalCount
38-
}
39-
openIssues: issues(states: OPEN) {
40-
totalCount
41-
}
42-
closedIssues: issues(states: CLOSED) {
43-
totalCount
44-
}
45-
followers {
46-
totalCount
47-
}
48-
repositories(ownerAffiliations: OWNER) {
49-
totalCount
50-
}
51-
}
52-
}
53-
`,
82+
query,
5483
variables,
5584
},
5685
{
@@ -60,39 +89,42 @@ const fetcher = (variables, token) => {
6089
};
6190

6291
/**
63-
* Fetch first 100 repositories for a given username.
92+
* Fetch stats information for a given username.
6493
*
65-
* @param {import('axios').AxiosRequestHeaders} variables Fetcher variables.
66-
* @param {string} token GitHub token.
67-
* @returns {Promise<import('../common/types').StatsFetcherResponse>} Repositories fetcher response.
94+
* @param {string} username Github username.
95+
* @returns {Promise<import('../common/types').StatsFetcher>} GraphQL Stats object.
96+
*
97+
* @description This function supports multi-page fetching if the 'FETCH_MULTI_PAGE_STARS' environment variable is set to true.
6898
*/
69-
const repositoriesFetcher = (variables, token) => {
70-
return request(
71-
{
72-
query: `
73-
query userInfo($login: String!, $after: String) {
74-
user(login: $login) {
75-
repositories(first: 100, ownerAffiliations: OWNER, orderBy: {direction: DESC, field: STARGAZERS}, after: $after) {
76-
nodes {
77-
name
78-
stargazers {
79-
totalCount
80-
}
81-
}
82-
pageInfo {
83-
hasNextPage
84-
endCursor
85-
}
86-
}
87-
}
88-
}
89-
`,
90-
variables,
91-
},
92-
{
93-
Authorization: `bearer ${token}`,
94-
},
95-
);
99+
const statsFetcher = async (username) => {
100+
let stats;
101+
let hasNextPage = true;
102+
let endCursor = null;
103+
while (hasNextPage) {
104+
const variables = { login: username, first: 100, after: endCursor };
105+
let res = await retryer(fetcher, variables);
106+
if (res.data.errors) return res;
107+
108+
// Store stats data.
109+
const repoNodes = res.data.data.user.repositories.nodes;
110+
if (!stats) {
111+
stats = res;
112+
} else {
113+
stats.data.data.user.repositories.nodes.push(...repoNodes);
114+
}
115+
116+
// Disable multi page fetching on public Vercel instance due to rate limits.
117+
const repoNodesWithStars = repoNodes.filter(
118+
(node) => node.stargazers.totalCount !== 0,
119+
);
120+
hasNextPage =
121+
process.env.FETCH_MULTI_PAGE_STARS === "true" &&
122+
repoNodes.length === repoNodesWithStars.length &&
123+
res.data.data.user.repositories.pageInfo.hasNextPage;
124+
endCursor = res.data.data.user.repositories.pageInfo.endCursor;
125+
}
126+
127+
return stats;
96128
};
97129

98130
/**
@@ -137,46 +169,6 @@ const totalCommitsFetcher = async (username) => {
137169
return 0;
138170
};
139171

140-
/**
141-
* Fetch all the stars for all the repositories of a given username.
142-
*
143-
* @param {string} username GitHub username.
144-
* @param {array} repoToHide Repositories to hide.
145-
* @returns {Promise<number>} Total stars.
146-
*/
147-
const totalStarsFetcher = async (username, repoToHide) => {
148-
let nodes = [];
149-
let hasNextPage = true;
150-
let endCursor = null;
151-
while (hasNextPage) {
152-
const variables = { login: username, first: 100, after: endCursor };
153-
let res = await retryer(repositoriesFetcher, variables);
154-
155-
if (res.data.errors) {
156-
logger.error(res.data.errors);
157-
throw new CustomError(
158-
res.data.errors[0].message || "Could not fetch user",
159-
CustomError.USER_NOT_FOUND,
160-
);
161-
}
162-
163-
const allNodes = res.data.data.user.repositories.nodes;
164-
const nodesWithStars = allNodes.filter(
165-
(node) => node.stargazers.totalCount !== 0,
166-
);
167-
nodes.push(...nodesWithStars);
168-
// hasNextPage =
169-
// allNodes.length === nodesWithStars.length &&
170-
// res.data.data.user.repositories.pageInfo.hasNextPage;
171-
hasNextPage = false; // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130.
172-
endCursor = res.data.data.user.repositories.pageInfo.endCursor;
173-
}
174-
175-
return nodes
176-
.filter((data) => !repoToHide[data.name])
177-
.reduce((prev, curr) => prev + curr.stargazers.totalCount, 0);
178-
};
179-
180172
/**
181173
* Fetch stats for a given username.
182174
*
@@ -203,7 +195,7 @@ const fetchStats = async (
203195
rank: { level: "C", score: 0 },
204196
};
205197

206-
let res = await retryer(fetcher, { login: username });
198+
let res = await statsFetcher(username);
207199

208200
// Catch GraphQL errors.
209201
if (res.data.errors) {
@@ -259,8 +251,15 @@ const fetchStats = async (
259251
stats.contributedTo = user.repositoriesContributedTo.totalCount;
260252

261253
// Retrieve stars while filtering out repositories to be hidden
262-
stats.totalStars = await totalStarsFetcher(username, repoToHide);
254+
stats.totalStars = user.repositories.nodes
255+
.filter((data) => {
256+
return !repoToHide[data.name];
257+
})
258+
.reduce((prev, curr) => {
259+
return prev + curr.stargazers.totalCount;
260+
}, 0);
263261

262+
// @ts-ignore // TODO: Fix this.
264263
stats.rank = calculateRank({
265264
totalCommits: stats.totalCommits,
266265
totalRepos: user.repositories.totalCount,

0 commit comments

Comments
 (0)