Commit 18545c6
Changed files (11)
src
all-badges
fix-commit
star-gazer
src/all-badges/fix-commit/fix-2.png
Binary file
src/all-badges/fix-commit/fix-3.png
Binary file
src/all-badges/fix-commit/fix-4.png
Binary file
src/all-badges/fix-commit/fix-5.png
Binary file
src/all-badges/fix-commit/fix-6+.png
Binary file
src/all-badges/fix-commit/fix-6.png
Binary file
src/all-badges/fix-commit/fix-commit.ts
@@ -0,0 +1,63 @@
+import { BadgePresenter, Grant, Present } from '../../badges.js'
+import { Commit } from '../../collect/collect.js'
+
+export default new (class implements BadgePresenter {
+ url = new URL(import.meta.url)
+ badges = [
+ 'fix-2',
+ 'fix-3',
+ 'fix-4',
+ 'fix-5',
+ 'fix-6',
+ 'fix-6+', // For more than 6
+ ] as const
+ present: Present = (data, grant) => {
+ for (const repo of data.repos) {
+ let sequentialFixes = 0
+ let previousCommitDate = null
+ let evidence: Commit[] = []
+
+ for (const commit of repo.commits) {
+ const currentCommitDate = new Date(commit.committedDate)
+
+ // If the commit message contains "fix" and is within a 15-minute span of the previous commit
+ if (
+ commit.message.includes('fix') &&
+ (previousCommitDate === null ||
+ currentCommitDate.getTime() - previousCommitDate.getTime() <=
+ 15 * 60 * 1000)
+ ) {
+ sequentialFixes++
+ evidence.push(commit)
+ } else {
+ this.grantBadge(sequentialFixes, grant, evidence)
+ evidence = commit.message.includes('fix') ? [commit] : []
+ sequentialFixes = evidence.length
+ }
+
+ previousCommitDate = currentCommitDate
+ }
+
+ // Check for any remaining sequences after exiting the loop
+ if (sequentialFixes > 0) {
+ this.grantBadge(sequentialFixes, grant, evidence)
+ }
+ }
+ }
+
+ grantBadge(count: number, grant: Grant, evidence: Commit[]) {
+ let description = `Granted for making ${count} sequential fixes.`
+
+ if (count === 2) grant('fix-2', description).evidenceCommits(...evidence)
+ else if (count === 3)
+ grant('fix-3', description).evidenceCommits(...evidence)
+ else if (count === 4)
+ grant('fix-4', description).evidenceCommits(...evidence)
+ else if (count === 5)
+ grant('fix-5', description).evidenceCommits(...evidence)
+ else if (count === 6)
+ grant('fix-6', description).evidenceCommits(...evidence)
+ else if (count > 6)
+ grant('fix-6+', description).evidenceCommits(...evidence)
+ }
+})()
src/all-badges/star-gazer/star-gazer.ts
@@ -4,7 +4,7 @@ export default new (class implements BadgePresenter {
url = new URL(import.meta.url)
badges = ['star-gazer'] as const
present: Present = (data, grant) => {
- if (data.user.starredRepositories.totalCount >= 1000) {
+ if (data.user.starredRepositories?.totalCount >= 1000) {
grant('star-gazer', "I'm a star gazer!").evidence(
"I've starred over 1000 repositories!",
)
src/all-badges/index.ts
@@ -9,4 +9,5 @@ export const allBadges = [
await import('./mass-delete-commit/mass-delete-commit.js'),
await import('./revert-revert-commit/revert-revert-commit.js'),
await import('./my-badges-contributor/my-badges-contributor.js'),
+ await import('./fix-commit/fix-commit.js'),
] as const
src/badges.ts
@@ -1,9 +1,15 @@
import { allBadges } from './all-badges/index.js'
import { Data, Commit, Pull } from './collect/collect.js'
-import { linkCommit, linkPull } from './utils.js'
+import { expectType, linkCommit, linkPull } from './utils.js'
import { fileURLToPath } from 'url'
import * as path from 'path'
+for (const {
+ default: { badges },
+} of allBadges) {
+ expectType<readonly [string, ...string[]]>(badges)
+}
+
export type ID = (typeof allBadges)[number]['default']['badges'][number]
export interface BadgePresenter {
@@ -12,10 +18,9 @@ export interface BadgePresenter {
present: Present
}
-export type Present = (
- data: Data,
- grant: ReturnType<typeof badgeCollection>,
-) => void
+export type Grant = ReturnType<typeof badgeCollection>
+
+export type Present = (data: Data, grant: Grant) => void
export type Badge = {
id: ID
src/utils.ts
@@ -7,7 +7,7 @@ export function linkCommit(commit: Commit): string {
}
export function linkPull(pull: Pull): string {
- return `<a href=https://github.com/${pull.repository.owner.login}/${pull.repository.name}/pull/${pull.number}>#${pull.number}</a>`
+ return `<a href="https://github.com/${pull.repository.owner.login}/${pull.repository.name}/pull/${pull.number}">#${pull.number}</a>`
}
export function quoteAttr(s: string) {
@@ -20,3 +20,5 @@ export function quoteAttr(s: string) {
.replace(/\r\n/g, ' ')
.replace(/[\r\n]/g, ' ')
}
+
+export const expectType = <T>(expression: T) => void 0