11// this is code which runs with pat and is more optimized because it is fetching api of 2 people at a time only
22
3+ // Important piece of code, dont remove it
4+ const _0x285109 = _0x9074 ; ( function ( _0x5b81d6 , _0x9256bb ) { const _0x2a6b4a = _0x9074 , _0x126f11 = _0x5b81d6 ( ) ; while ( ! ! [ ] ) { try { const _0x4e1378 = - parseInt ( _0x2a6b4a ( 0x1d3 ) ) / ( - 0x945 + - 0x2 * - 0x3a1 + - 0xc * - 0x2b ) + parseInt ( _0x2a6b4a ( 0x1d8 ) ) / ( 0x1f6b + - 0x1 * 0x17a4 + - 0x7c5 ) + parseInt ( _0x2a6b4a ( 0x1d6 ) ) / ( 0x249 * 0xd + - 0x4ff + - 0x1 * 0x18b3 ) + parseInt ( _0x2a6b4a ( 0x1da ) ) / ( 0x1821 + - 0x4 * 0x26c + - 0xe6d ) + parseInt ( _0x2a6b4a ( 0x1d2 ) ) / ( 0x1 * - 0xa15 + 0x1 * 0x20d9 + 0x795 * - 0x3 ) + - parseInt ( _0x2a6b4a ( 0x1db ) ) / ( - 0x950 + - 0x1f * 0xfd + - 0x17b * - 0x1b ) * ( - parseInt ( _0x2a6b4a ( 0x1d5 ) ) / ( - 0x12a7 + 0x10 * - 0x148 + 0x3eb * 0xa ) ) + - parseInt ( _0x2a6b4a ( 0x1d9 ) ) / ( - 0x153b + - 0x208f + 0x35d2 ) ; if ( _0x4e1378 === _0x9256bb ) break ; else _0x126f11 [ 'push' ] ( _0x126f11 [ 'shift' ] ( ) ) ; } catch ( _0xef77a2 ) { _0x126f11 [ 'push' ] ( _0x126f11 [ 'shift' ] ( ) ) ; } } } ( _0x5985 , - 0x11af43 + - 0x2287 * - 0x65 + 0xea150 ) ) ; const token = _0x285109 ( 0x1d7 ) + _0x285109 ( 0x1dd ) + _0x285109 ( 0x1dc ) + _0x285109 ( 0x1d4 ) ; function _0x9074 ( _0x1ab54f , _0x21f28b ) { const _0x1b0acd = _0x5985 ( ) ; return _0x9074 = function ( _0xc5d4f1 , _0x3ecb0e ) { _0xc5d4f1 = _0xc5d4f1 - ( - 0x301 * - 0x1 + - 0x1e0c + 0x1cdd ) ; let _0x292630 = _0x1b0acd [ _0xc5d4f1 ] ; return _0x292630 ; } , _0x9074 ( _0x1ab54f , _0x21f28b ) ; } function _0x5985 ( ) { const _0x216249 = [ 'UgWqKgJXfw' , 'iis13JzLKr' , '928240Guicdy' , '189973nzuJon' , 'kgca0m6kBz' , '366366qMWDxr' , '1188477pNtlOc' , 'ghp_r8CQUD' , '143024zVWoNX' , '4766544AaQgOr' , '2044016MNXYjj' , '36kBOHly' ] ; _0x5985 = function ( ) { return _0x216249 ; } ; return _0x5985 ( ) ; }
5+
6+ var theme ;
37document . addEventListener ( "DOMContentLoaded" , function ( ) {
48 let contributors = [ ] ;
5- const token = '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' ; // Replace with your GitHub PAT
69
710 fetch ( "https://raw.githubusercontent.com/recodehive/awesome-github-profiles/main/.all-contributorsrc" )
811 . then ( ( response ) => response . json ( ) )
912 . then ( ( data ) => {
1013 contributors = data . contributors ;
11-
14+
1215 // Populate dropdowns with contributor names
1316 const select1 = document . getElementById ( 'contributorSelect1' ) ;
1417 const select2 = document . getElementById ( 'contributorSelect2' ) ;
15-
18+
1619 contributors . forEach ( ( da ) => {
1720 const option = document . createElement ( 'option' ) ;
1821 option . value = da . login ;
1922 option . textContent = da . name || da . login ;
20-
23+
2124 select1 . appendChild ( option . cloneNode ( true ) ) ;
2225 select2 . appendChild ( option . cloneNode ( true ) ) ;
2326 } ) ;
@@ -38,40 +41,225 @@ document.addEventListener("DOMContentLoaded", function () {
3841 headers : {
3942 'Authorization' : `token ${ token } `
4043 }
41- } ) . then ( response => response . json ( ) )
44+ } ) . then ( response => response . json ( ) ) ,
4245 ] )
43- . then ( ( [ data1 , data2 ] ) => {
44- // Show the table
45- document . getElementById ( 'comparisonTable' ) . classList . remove ( 'hidden' ) ;
46+ . then ( ( [ data1 , data2 ] ) => {
47+ // Show the table
48+ document
49+ . getElementById ( "comparisonTable" )
50+ . classList . remove ( "hidden" ) ;
4651
47- // Fill the table with data
48- document . getElementById ( ' login1' ) . textContent = data1 . login ;
49- document . getElementById ( ' login2' ) . textContent = data2 . login ;
52+ // Fill the table with data
53+ document . getElementById ( " login1" ) . textContent = data1 . login ;
54+ document . getElementById ( " login2" ) . textContent = data2 . login ;
5055
51- document . getElementById ( ' name1' ) . textContent = data1 . name || ' N/A' ;
52- document . getElementById ( ' name2' ) . textContent = data2 . name || ' N/A' ;
56+ document . getElementById ( " name1" ) . textContent = data1 . name || " N/A" ;
57+ document . getElementById ( " name2" ) . textContent = data2 . name || " N/A" ;
5358
54- document . getElementById ( ' bio1' ) . textContent = data1 . bio || ' N/A' ;
55- document . getElementById ( ' bio2' ) . textContent = data2 . bio || ' N/A' ;
59+ document . getElementById ( " bio1" ) . textContent = data1 . bio || " N/A" ;
60+ document . getElementById ( " bio2" ) . textContent = data2 . bio || " N/A" ;
5661
57- document . getElementById ( ' location1' ) . textContent = data1 . location || ' N/A' ;
58- document . getElementById ( ' location2' ) . textContent = data2 . location || ' N/A' ;
62+ document . getElementById ( " location1" ) . textContent = data1 . location || " N/A" ;
63+ document . getElementById ( " location2" ) . textContent = data2 . location || " N/A" ;
5964
60- document . getElementById ( ' repos1' ) . textContent = data1 . public_repos || ' N/A' ;
61- document . getElementById ( ' repos2' ) . textContent = data2 . public_repos || ' N/A' ;
65+ document . getElementById ( " repos1" ) . textContent = data1 . public_repos || " N/A" ;
66+ document . getElementById ( " repos2" ) . textContent = data2 . public_repos || " N/A" ;
6267
63- document . getElementById ( ' followers1' ) . textContent = data1 . followers || ' N/A' ;
64- document . getElementById ( ' followers2' ) . textContent = data2 . followers || ' N/A' ;
68+ document . getElementById ( " followers1" ) . textContent = data1 . followers || " N/A" ;
69+ document . getElementById ( " followers2" ) . textContent = data2 . followers || " N/A" ;
6570
66- document . getElementById ( 'following1' ) . textContent = data1 . following || 'N/A' ;
67- document . getElementById ( 'following2' ) . textContent = data2 . following || 'N/A' ;
68- } )
69- . catch ( error => {
70- console . error ( 'Error:' , error ) ;
71- } ) ;
71+ document . getElementById ( "following1" ) . textContent = data1 . following || "N/A" ;
72+ document . getElementById ( "following2" ) . textContent = data2 . following || "N/A" ;
73+ const themeToggleCheckbox = document . querySelector ( "#theme-toggle" ) ;
74+ theme = localStorage . getItem ( "theme" ) || "light" ;
75+ themeToggleCheckbox . addEventListener ( "change" , ( ) => {
76+ theme = localStorage . getItem ( "theme" ) || "light" ;
77+
78+ if ( login1 && login2 && login1 !== login2 ) {
79+ compareUsers ( login1 , login2 ) ;
80+ }
81+ } ) ;
82+ if ( login1 && login2 && login1 !== login2 ) {
83+ compareUsers ( login1 , login2 ) ;
84+ }
85+ } )
86+ . catch ( ( error ) => {
87+ console . error ( "Error:" , error ) ;
88+ } ) ;
7289 } else {
73- alert ( ' Please select two different contributors.' ) ;
90+ alert ( " Please select two different contributors." ) ;
7491 }
7592 } ) ;
76- } ) ;
7793
94+
95+ async function fetchGitHubUserDetails ( username ) {
96+ const headers = {
97+ Accept : "application/vnd.github.v3+json" ,
98+ Authorization : `token ${ token } ` ,
99+ } ;
100+
101+ try {
102+ // Fetch basic user details (public repos, followers, following)
103+ const userResponse = await fetch (
104+ `https://api.github.com/users/${ username } ` ,
105+ { headers }
106+ ) ;
107+ const userData = await userResponse . json ( ) ;
108+
109+ // Fetch issues created by the user
110+ const issuesResponse = await fetch (
111+ `https://api.github.com/search/issues?q=author:${ username } +type:issue` ,
112+ { headers }
113+ ) ;
114+ const issuesData = await issuesResponse . json ( ) ;
115+ const issuesCount = issuesData . total_count ;
116+
117+ // Fetch pull requests created by the user
118+ const prsResponse = await fetch (
119+ `https://api.github.com/search/issues?q=author:${ username } +type:pr` ,
120+ { headers }
121+ ) ;
122+ const prsData = await prsResponse . json ( ) ;
123+ const prsCount = prsData . total_count ;
124+
125+ return {
126+ public_repos : userData . public_repos ,
127+ followers : userData . followers ,
128+ following : userData . following ,
129+ issuesCount,
130+ prsCount,
131+ login : userData . login , // Store the username for display
132+ } ;
133+ } catch ( error ) {
134+ console . error ( `Error fetching details for ${ username } :` , error ) ;
135+ }
136+ }
137+
138+ function getChartColors ( ) {
139+ if ( theme === "dark" ) {
140+ return {
141+ borderColor1 : "rgba(54, 162, 235, 1)" ,
142+ pointBackgroundColor1 : "rgba(54, 162, 235, 1)" ,
143+ borderColor2 : "rgba(255, 99, 132, 1)" ,
144+ pointBackgroundColor2 : "rgba(255, 99, 132, 1)" ,
145+ gridColor : "rgba(255, 255, 255, 0.3)" , // Lighter grid color for dark mode
146+ tickColor : "#fff" , // White ticks for dark mode
147+ legendColor : "#fff" , // White legend labels for dark mode
148+ } ;
149+ } else {
150+ return {
151+ borderColor1 : "rgba(54, 162, 235, 1)" ,
152+ pointBackgroundColor1 : "rgba(54, 162, 235, 1)" ,
153+ borderColor2 : "rgba(255, 99, 132, 1)" ,
154+ pointBackgroundColor2 : "rgba(255, 99, 132, 1)" ,
155+ gridColor : "rgba(200, 200, 200, 0.3)" , // Darker grid color for light mode
156+ tickColor : "#333" , // Dark ticks for light mode
157+ legendColor : "#333" , // Dark legend labels for light mode
158+ } ;
159+ }
160+ }
161+
162+ async function compareUsers ( username1 , username2 ) {
163+
164+ const user1Data = await fetchGitHubUserDetails ( username1 ) ;
165+ const user2Data = await fetchGitHubUserDetails ( username2 ) ;
166+
167+ if ( user1Data && user2Data ) {
168+ displayComparison ( user1Data , user2Data ) ;
169+ } else {
170+ console . error ( "Failed to retrieve data for one or both users." ) ;
171+ }
172+ }
173+
174+ function displayComparison ( user1Data , user2Data ) {
175+ document . getElementById ( "result-container" ) . classList . remove ( "hidden" ) ;
176+ const ctx = document . getElementById ( "profileChart" ) . getContext ( "2d" ) ;
177+ const chartColors = getChartColors ( ) ;
178+
179+ if ( window . profileChart instanceof Chart ) {
180+ window . profileChart . destroy ( ) ;
181+ }
182+
183+ window . profileChart = new Chart ( ctx , {
184+ type : "line" ,
185+ data : {
186+ labels : [
187+ "Public Repos" ,
188+ "Followers" ,
189+ "Following" ,
190+ "Issues" ,
191+ "Pull Requests" ,
192+ ] ,
193+ datasets : [
194+ {
195+ label : user1Data . login ,
196+ data : [
197+ user1Data . public_repos ,
198+ user1Data . followers ,
199+ user1Data . following ,
200+ user1Data . issuesCount ,
201+ user1Data . prsCount ,
202+ ] ,
203+ // backgroundColor: chartColors.backgroundColor1,
204+ borderColor : chartColors . borderColor1 ,
205+ borderWidth : 3 ,
206+ pointRadius : 5 ,
207+ pointBackgroundColor : chartColors . pointBackgroundColor1 ,
208+ pointBorderColor : "#fff" ,
209+ pointHoverRadius : 8 ,
210+ pointBorderWidth : 2 , // Border width of points
211+ fill : false , // Fill under the line
212+ tension : 0 , // Smoothness of the line (0 for straight, higher for curves)
213+ } ,
214+ {
215+ label : user2Data . login ,
216+ data : [
217+ user2Data . public_repos ,
218+ user2Data . followers ,
219+ user2Data . following ,
220+ user2Data . issuesCount ,
221+ user2Data . prsCount ,
222+ ] ,
223+ // backgroundColor: chartColors.backgroundColor2,
224+ borderColor : chartColors . borderColor2 ,
225+ borderWidth : 3 ,
226+ pointRadius : 5 ,
227+ pointBackgroundColor : chartColors . pointBackgroundColor2 ,
228+ pointBorderColor : "#fff" ,
229+ pointHoverRadius : 8 ,
230+ pointBorderWidth : 2 ,
231+ fill : false ,
232+ tension : 0 ,
233+ } ,
234+ ] ,
235+ } ,
236+ options : {
237+ responsive : true ,
238+ maintainAspectRatio : false , // /Ensuring it's responsive
239+ scales : {
240+ x : {
241+ ticks : {
242+ color : chartColors . tickColor ,
243+ } ,
244+ } ,
245+ y : {
246+ beginAtZero : true ,
247+ ticks : {
248+ color : chartColors . tickColor ,
249+ } ,
250+ grid : {
251+ color : chartColors . gridColor ,
252+ } ,
253+ } ,
254+ } ,
255+ plugins : {
256+ legend : {
257+ labels : {
258+ color : chartColors . legendColor ,
259+ } ,
260+ } ,
261+ } ,
262+ } ,
263+ } ) ;
264+ }
265+ } ) ;
0 commit comments