Commit 2545e00
Changed files (12)
.github
src
.github/screenshot.png
Binary file
src/all-badges/stars/stars.ts
@@ -0,0 +1,17 @@
+import {BadgePresenter, Present} from '../../badges.js'
+
+export default new class implements BadgePresenter {
+ url = new URL(import.meta.url)
+ badges = [
+ 'stars-100',
+ ] as const
+ present: Present = (data, grant) => {
+ let totalStars = 0
+ for (const repo of data.repos) {
+ totalStars += repo.stargazers_count || 0
+ }
+ if (totalStars >= 100) {
+ grant('stars-100', `I collected 100 stars.`)
+ }
+ }
+}
src/all-badges/index.ts
@@ -4,4 +4,5 @@ export const allBadges = [
await import('./fuck-commit/fuck-commit.js'),
await import('./mass-delete-commit/mass-delete-commit.js'),
await import('./revert-revert-commit/revert-revert-commit.js'),
+ //await import('./stars/stars.js'),
] as const
src/collect/collect.ts
@@ -4,11 +4,13 @@ import {PullsQuery} from './pulls.js'
import {CommitsQuery} from './commits.js'
import fs from 'node:fs'
import {fileURLToPath} from 'url'
+import {IssuesQuery} from './issues.js'
export type Data = {
user: User
repos: Repo[]
pulls: Pull[]
+ issues: Issues[]
}
export type User = Endpoints['GET /users/{username}']['response']['data']
export type Repo = Endpoints['GET /users/{username}/repos']['response']['data'][0] & {
@@ -16,6 +18,7 @@ export type Repo = Endpoints['GET /users/{username}/repos']['response']['data'][
}
export type Commit = CommitsQuery['repository']['defaultBranchRef']['target']['history']['nodes'][0]
export type Pull = PullsQuery['user']['pullRequests']['nodes'][0]
+export type Issues = IssuesQuery['user']['issues']['nodes'][0]
export async function collect(username: string, octokit: Octokit): Promise<Data> {
const user = (await octokit.request('GET /users/{username}', {username})).data
@@ -24,6 +27,7 @@ export async function collect(username: string, octokit: Octokit): Promise<Data>
user: user,
repos: [],
pulls: [],
+ issues: [],
}
const repos = octokit.paginate.iterator('GET /users/{username}/repos', {
@@ -55,7 +59,7 @@ export async function collect(username: string, octokit: Octokit): Promise<Data>
for await (const resp of commits) {
const {totalCount, nodes} = resp.repository.defaultBranchRef.target.history
- console.log(`| commits ${nodes.length}/${totalCount}`)
+ console.log(`| commits ${nodes.length}/${totalCount} (cost: ${resp.rateLimit.cost}, remaining: ${resp.rateLimit.remaining})`)
for (const commit of nodes) {
repo.commits.push(commit)
}
@@ -69,13 +73,23 @@ export async function collect(username: string, octokit: Octokit): Promise<Data>
const pulls = octokit.graphql.paginate.iterator<PullsQuery>(loadGraphql('./pulls.graphql'), {
username,
})
-
for await (const resp of pulls) {
+ console.log(`Loading pull requests ${data.pulls.length + resp.user.pullRequests.nodes.length}/${resp.user.pullRequests.totalCount} (cost: ${resp.rateLimit.cost}, remaining: ${resp.rateLimit.remaining})`)
for (const pull of resp.user.pullRequests.nodes) {
data.pulls.push(pull)
}
}
+ const issues = octokit.graphql.paginate.iterator<IssuesQuery>(loadGraphql('./issues.graphql'), {
+ username,
+ })
+ for await (const resp of issues) {
+ console.log(`Loading issues ${data.issues.length + resp.user.issues.nodes.length}/${resp.user.issues.totalCount} (cost: ${resp.rateLimit.cost}, remaining: ${resp.rateLimit.remaining})`)
+ for (const issue of resp.user.issues.nodes) {
+ data.issues.push(issue)
+ }
+ }
+
return data
}
src/collect/commits.graphql
@@ -27,4 +27,10 @@ query CommitsQuery(
}
}
}
+ rateLimit {
+ limit
+ cost
+ remaining
+ resetAt
+ }
}
src/collect/commits.ts
@@ -19,4 +19,10 @@ export type CommitsQuery = {
}
}
}
+ rateLimit: {
+ limit: number
+ cost: number
+ remaining: number
+ resetAt: string
+ }
}
src/collect/issues.graphql
@@ -0,0 +1,53 @@
+query IssuesQuery(
+ $username: String!,
+ $num: Int = 100,
+ $cursor: String
+) {
+ user(login: $username) {
+ issues(first: $num, after: $cursor, filterBy: { createdBy: $username }) {
+ totalCount
+ nodes {
+ createdAt
+ closedAt
+ closed
+ author {
+ login
+ }
+ number
+ title
+ labels(first: 10) {
+ totalCount
+ nodes {
+ name
+ }
+ }
+ body
+ comments(first: 1) {
+ totalCount
+ }
+ reactions(first: 10) {
+ totalCount
+ }
+ assignees(first: 3) {
+ totalCount
+ }
+ repository {
+ owner {
+ login
+ }
+ name
+ }
+ }
+ pageInfo {
+ hasNextPage
+ endCursor
+ }
+ }
+ }
+ rateLimit {
+ limit
+ cost
+ remaining
+ resetAt
+ }
+}
src/collect/issues.ts
@@ -0,0 +1,49 @@
+export type IssuesQuery = {
+ user: {
+ issues: {
+ totalCount: number
+ nodes: Array<{
+ createdAt: string
+ closedAt: string
+ closed: boolean
+ author: {
+ login: string
+ }
+ number: number
+ title: string
+ labels: {
+ totalCount: number
+ nodes: Array<{
+ name: string
+ }>
+ }
+ body: string
+ comments: {
+ totalCount: number
+ }
+ reactions: {
+ totalCount: number
+ }
+ assignees: {
+ totalCount: number
+ }
+ repository: {
+ owner: {
+ login: string
+ }
+ name: string
+ }
+ }>
+ pageInfo: {
+ hasNextPage: boolean
+ endCursor: string
+ }
+ }
+ }
+ rateLimit: {
+ limit: number
+ cost: number
+ remaining: number
+ resetAt: string
+ }
+}
src/collect/pulls.graphql
@@ -26,4 +26,10 @@ query PullsQuery(
}
}
}
+ rateLimit {
+ limit
+ cost
+ remaining
+ resetAt
+ }
}
src/collect/pulls.ts
@@ -22,4 +22,10 @@ export type PullsQuery = {
endCursor: string
}
}
+ rateLimit: {
+ limit: number
+ cost: number
+ remaining: number
+ resetAt: string
+ }
}
src/check-images.ts
@@ -14,6 +14,8 @@ void async function main() {
if (!fs.existsSync(image)) {
console.error(`Missing image for badge "${id}" at ${image}`)
foundMissing = true
+ } else {
+ console.log(`<img src="${image}" alt="${id}" width="100" height="100">`)
}
}
}
README.md
@@ -4,6 +4,28 @@
Generate badges for your profile.
+## Example
+
+Here is an example of how my badges look like in [my profile](https://github.com/antonmedv):
+
+<p align="center"><img src=".github/screenshot.png" alt="Example" width="600"></p>
+
+Here is all currently available badges:
+
+<img src="src/all-badges/abc-commit/a-commit.png" alt="a-commit" width="60">
+<img src="src/all-badges/abc-commit/ab-commit.png" alt="ab-commit" width="60">
+<img src="src/all-badges/abc-commit/abc-commit.png" alt="abc-commit" width="60">
+<img src="src/all-badges/abc-commit/abcd-commit.png" alt="abcd-commit" width="60">
+<img src="src/all-badges/abc-commit/abcde-commit.png" alt="abcde-commit" width="60">
+<img src="src/all-badges/abc-commit/abcdef-commit.png" alt="abcdef-commit" width="60">
+<img src="src/all-badges/dead-commit/dead-commit.png" alt="dead-commit" width="60">
+<img src="src/all-badges/fuck-commit/fuck-commit.png" alt="fuck-commit" width="60">
+<img src="src/all-badges/mass-delete-commit/mass-delete-commit.png" alt="mass-delete-commit" width="60">
+<img src="src/all-badges/mass-delete-commit/mass-delete-commit-10k.png" alt="mass-delete-commit-10k" width="60">
+<img src="src/all-badges/revert-revert-commit/revert-revert-commit.png" alt="revert-revert-commit" width="60">
+
+But we are planning on adding much more. You can even add your own badges too!
+
## Usage
Here is how to add my badges to your profile: