master
1import { Commit, define, latest, User } from '#src'
2
3export default define({
4 url: import.meta.url,
5 badges: [
6 'midnight-commits',
7 'morning-commits',
8 'evening-commits',
9 'sleepy-coder',
10 ] as const,
11 present(data, grant) {
12 const morningCommits: Commit[] = []
13 const eveningCommits: Commit[] = []
14 const midnightCommits: Commit[] = []
15 const sleepycoderCommits: Commit[] = []
16
17 const timezoneOffset = guessTimezone(data.user)
18
19 for (const repo of data.repos) {
20 for (const commit of repo.commits) {
21 const date = new Date(commit.committedDate)
22
23 date.setUTCHours(date.getUTCHours() + timezoneOffset)
24
25 if (date.getUTCHours() >= 4 && date.getUTCHours() < 6) {
26 sleepycoderCommits.push(commit)
27 }
28 if (date.getUTCHours() >= 6 && date.getUTCHours() < 8) {
29 morningCommits.push(commit)
30 }
31 if (date.getUTCHours() >= 21) {
32 eveningCommits.push(commit)
33 }
34 if (date.getUTCHours() == 0 && date.getUTCMinutes() < 5) {
35 midnightCommits.push(commit)
36 }
37 }
38 }
39
40 if (sleepycoderCommits.length > 0) {
41 grant('sleepy-coder', 'I am a sleepy coder.').evidenceCommits(
42 ...sleepycoderCommits.sort(latest).slice(0, 6),
43 )
44 }
45 if (morningCommits.length > 0) {
46 grant('morning-commits', 'I commit in the morning.').evidenceCommits(
47 ...morningCommits.sort(latest).slice(0, 6),
48 )
49 }
50 if (eveningCommits.length > 0) {
51 grant('evening-commits', 'I commit in the evening.').evidenceCommits(
52 ...eveningCommits.sort(latest).slice(0, 6),
53 )
54 }
55 if (midnightCommits.length > 0) {
56 grant('midnight-commits', 'I commit at midnight.').evidenceCommits(
57 ...midnightCommits.sort(latest).slice(0, 6),
58 )
59 }
60 },
61})
62
63function guessTimezone(user: User) {
64 const location = user.location ? user.location.toLowerCase() : ''
65 const regexMapping = [
66 { pattern: /\bamsterdam\b|\bnetherlands\b/, offset: 2 },
67 { pattern: /\bantwerp\b|\bghent\b/, offset: 2 },
68 { pattern: /\bargentina\b|\bbuenos aires\b/, offset: -3 },
69 { pattern: /\bathens\b|\bgreece\b/, offset: 3 },
70 { pattern: /\bbangkok\b|\bthailand\b/, offset: 7 },
71 { pattern: /\bbarcelona\b|\bvalencia\b|\bseville\b/, offset: 2 },
72 { pattern: /\bbeijing\b|\bchina\b/, offset: 8 },
73 { pattern: /\bbelgrade\b|\bserbia\b/, offset: 2 },
74 { pattern: /\bberlin\b|\bgermany\b/, offset: 2 },
75 { pattern: /\bbilbao\b|\bzaragoza\b/, offset: 2 },
76 { pattern: /\bbordeaux\b|\bmarseille\b|\blyon\b/, offset: 2 },
77 { pattern: /\bboston\b|\bmassachusetts\b|\bma\b/, offset: -4 },
78 { pattern: /\bbratislava\b|\bslovakia\b/, offset: 2 },
79 { pattern: /\bbrazil\b|\bsao paulo\b|\brio de janeiro\b/, offset: -3 },
80 { pattern: /\bbrussels\b|\bbelgium\b/, offset: 2 },
81 { pattern: /\bbucharest\b|\bromania\b/, offset: 3 },
82 { pattern: /\bbudapest\b|\bhungary\b/, offset: 2 },
83 { pattern: /\bcairo\b|\begypt\b/, offset: 2 },
84 { pattern: /\bcasablanca\b|\bmorocco\b/, offset: 1 },
85 { pattern: /\bchicago\b|\billinois\b|\bil\b/, offset: -5 },
86 { pattern: /\bchile\b|\bsantiago\b/, offset: -3 },
87 { pattern: /\bchisinau\b|\bmoldova\b/, offset: 3 },
88 { pattern: /\bcolombia\b|\bbogota\b/, offset: -5 },
89 { pattern: /\bcopenhagen\b|\bdenmark\b/, offset: 2 },
90 { pattern: /\bcosta rica\b|\bsan jose\b/, offset: -6 },
91 { pattern: /\bcrete\b|\bthessaloniki\b/, offset: 3 },
92 { pattern: /\bdhaka\b|\bbangladesh\b/, offset: 6 },
93 { pattern: /\bdubai\b|\buae\b|\babu dhabi\b/, offset: 4 },
94 { pattern: /\bdublin\b|\bireland\b/, offset: 1 },
95 { pattern: /\becuador\b|\bquito\b/, offset: -5 },
96 { pattern: /\bfaro\b|\bevora\b/, offset: 1 },
97 { pattern: /\bfiji\b/, offset: 12 },
98 { pattern: /\bflorence\b|\bpalermo\b/, offset: 2 },
99 { pattern: /\bflorida\b|\bmiami\b/, offset: -4 },
100 { pattern: /\bgdansk\b|\bwroclaw\b/, offset: 2 },
101 { pattern: /\bgeneva\b|\bbern\b/, offset: 2 },
102 { pattern: /\bgenoa\b|\bturin\b/, offset: 2 },
103 { pattern: /\bglasgow\b|\bliverpool\b|\bmanchester\b/, offset: 0 },
104 { pattern: /\bgothenburg\b|\bmalmo\b/, offset: 2 },
105 { pattern: /\bhamburg\b|\bmunich\b|\bfrankfurt\b/, offset: 2 },
106 { pattern: /\bhawaii\b/, offset: -10 },
107 { pattern: /\bhelsinki\b|\bfinland\b/, offset: 3 },
108 { pattern: /\biraq\b|\bbaghdad\b/, offset: 3 },
109 { pattern: /\bisrael\b|\btel aviv\b/, offset: 3 },
110 { pattern: /\bjakarta\b|\bindonesia\b/, offset: 7 },
111 { pattern: /\bjohannesburg\b|\bsouth africa\b/, offset: 2 },
112 { pattern: /\bjordan\b|\bamman\b/, offset: 3 },
113 { pattern: /\bkathmandu\b|\bnepal\b/, offset: 5.75 },
114 { pattern: /\bkiev\b|\bukraine\b/, offset: 3 },
115 { pattern: /\bkuala lumpur\b|\bmalaysia\b/, offset: 8 },
116 { pattern: /\blagos\b|\bnigeria\b/, offset: 1 },
117 { pattern: /\bled\b|\bslovenia\b/, offset: 2 },
118 { pattern: /\bledz\b|\bkrakow\b/, offset: 2 },
119 { pattern: /\blisbon\b|\bportugal\b/, offset: 1 },
120 { pattern: /\bljubljana\b|\bslovenia\b/, offset: 2 },
121 { pattern: /\blondon\b|\buk\b/, offset: 0 },
122 { pattern: /\blos angeles\b|\bcalifornia\b|\bca\b/, offset: -7 },
123 { pattern: /\bluxembourg\b/, offset: 2 },
124 { pattern: /\blyon\b|\bnantes\b/, offset: 2 },
125 { pattern: /\bmadrid\b|\bspain\b/, offset: 2 },
126 { pattern: /\bmalta\b|\bvalletta\b/, offset: 2 },
127 { pattern: /\bmelbourne\b/, offset: 11 },
128 { pattern: /\bmexico\b|\bmexico city\b/, offset: -5 },
129 { pattern: /\bminsk\b|\bbelarus\b/, offset: 3 },
130 { pattern: /\bmonaco\b/, offset: 2 },
131 { pattern: /\bmontreal\b|\bquebec\b/, offset: -4 },
132 { pattern: /\bmoscow\b|\brussia\b/, offset: 3 },
133 { pattern: /\bmumbai\b|\bindia\b/, offset: 5.5 },
134 { pattern: /\bnairobi\b|\bkenya\b/, offset: 3 },
135 { pattern: /\bnaples\b|\bmilan\b|\bvenice\b/, offset: 2 },
136 { pattern: /\bnew delhi\b/, offset: 5.5 },
137 { pattern: /\bnew york\b|\bny\b/, offset: -4 },
138 { pattern: /\bnew zealand\b|\bauckland\b/, offset: 13 },
139 { pattern: /\bnice\b|\btoulouse\b/, offset: 2 },
140 { pattern: /\bnicosia\b|\bcyprus\b/, offset: 3 },
141 { pattern: /\bodessa\b|\blviv\b/, offset: 3 },
142 { pattern: /\boslo\b|\bnorway\b/, offset: 2 },
143 { pattern: /\bpakistan\b|\blahore\b|\bkarachi\b/, offset: 5 },
144 { pattern: /\bpanama\b|\bpanama city\b/, offset: -5 },
145 { pattern: /\bpapua new guinea\b|\bport moresby\b/, offset: 10 },
146 { pattern: /\bparis\b|\bfrance\b/, offset: 2 },
147 { pattern: /\bperu\b|\blima\b/, offset: -5 },
148 { pattern: /\bpodgorica\b|\bmontenegro\b/, offset: 2 },
149 { pattern: /\bporto\b|\bbraga\b/, offset: 1 },
150 { pattern: /\bprague\b|\bczech republic\b|\bczechia\b/, offset: 2 },
151 { pattern: /\breykjavik\b|\biceland\b/, offset: 0 },
152 { pattern: /\briga\b|\blatvia\b/, offset: 3 },
153 { pattern: /\brome\b|\bitaly\b/, offset: 2 },
154 { pattern: /\brotterdam\b|\butrecht\b/, offset: 2 },
155 { pattern: /\bsalzburg\b|\bgraz\b/, offset: 2 },
156 { pattern: /\bsarajevo\b|\bbosnia and herzegovina\b/, offset: 2 },
157 { pattern: /\bsaudi arabia\b|\briyadh\b/, offset: 3 },
158 { pattern: /\bseoul\b|\bsouth korea\b/, offset: 9 },
159 { pattern: /\bshanghai\b/, offset: 8 },
160 { pattern: /\bsheffield\b|\bleeds\b/, offset: 0 },
161 { pattern: /\bsingapore\b/, offset: 8 },
162 { pattern: /\bskopje\b|\bnorth macedonia\b/, offset: 2 },
163 { pattern: /\bsofia\b|\bbulgaria\b/, offset: 3 },
164 { pattern: /\bstockholm\b|\bsweden\b/, offset: 2 },
165 { pattern: /\bstuttgart\b|\bdusseldorf\b/, offset: 2 },
166 { pattern: /\bsydney\b|\baustralia\b/, offset: 11 },
167 { pattern: /\btallinn\b|\bestonia\b/, offset: 3 },
168 { pattern: /\btehran\b|\biran\b/, offset: 3.5 },
169 { pattern: /\btexas\b|\bhouston\b|\bdallas\b/, offset: -5 },
170 { pattern: /\btirana\b|\balbania\b/, offset: 2 },
171 { pattern: /\btokyo\b|\bjapan\b/, offset: 9 },
172 { pattern: /\btoronto\b|\bontario\b/, offset: -4 },
173 { pattern: /\btunisia\b|\btunis\b/, offset: 1 },
174 { pattern: /\bvalencia\b|\bmalaga\b/, offset: 2 },
175 { pattern: /\bvancouver\b|\bbritish columbia\b/, offset: -7 },
176 { pattern: /\bvenezuela\b|\bcaracas\b/, offset: -4 },
177 { pattern: /\bvienna\b|\baustria\b/, offset: 2 },
178 { pattern: /\bvilnius\b|\blithuania\b/, offset: 3 },
179 { pattern: /\bwarsaw\b|\bpoland\b/, offset: 2 },
180 { pattern: /\bzagreb\b|\bcroatia\b/, offset: 2 },
181 { pattern: /\bzurich\b|\bswitzerland\b/, offset: 2 },
182 { pattern: /\bturkey\b|\bistanbul\b|\bankara\b/, offset: 3 },
183 ]
184
185 for (const mapping of regexMapping) {
186 if (mapping.pattern.test(location)) {
187 return mapping.offset
188 }
189 }
190
191 return 0
192}