${img_html}
${Math.ceil( ( iteration / total_results ) * 100)}%
complete
${text}
`;
68 | if(status !== true) cont.outerHTML = '';
69 | }
70 | function convertToTSV(params) {
71 | const {fileArray,file_name} = params;
72 | const transpose = (a)=> a[0].map((_, c)=> a.map(r=> r[c]));
73 | var unq = (arr) => arr.filter((e, p, a) => a.indexOf(e) == p);
74 | var firstLevel = fileArray.map(el => Object.entries(el));
75 | var lens = Math.max(...firstLevel.map(el => el.length));
76 | var header = unq(firstLevel.map(el => el.map(itm => itm[0])).flat());
77 | var table = [header];
78 | var str = (o) => typeof o == 'object' ? JSON.stringify(o).replace(/\n|\r/g, ' ') : o.toString().replace(/\n|\r/g, ' ');
79 | for (var i = 0; i < firstLevel.length; i++) {
80 | var arr = [];
81 | var row = [];
82 | for (var s = 0; s < firstLevel[i].length; s++) {
83 | var place = header.indexOf(firstLevel[i][s][0]);
84 | arr[place] = firstLevel[i][s][1];
85 | }
86 | for (var a = 0; a < arr.length; a++) {
87 | if (arr[a]) {
88 | row.push(arr[a]);
89 | } else {
90 | row.push('');
91 | }
92 | }
93 | table.push(row);
94 | }
95 |
96 | function downloadr(arr2D, filename) {
97 | var data = /\.json$|.js$/.test(filename) ? JSON.stringify(arr2D) : arr2D.map(el => el.reduce((a, b) => a + '\t' + b)).reduce((a, b) => a + '\r' + b);
98 | var type = /\.json$|.js$/.test(filename) ? 'data:application/json;charset=utf-8,' : 'data:text/plain;charset=utf-8,';
99 | var file = new Blob([data], {
100 | type: type
101 | });
102 | if (window.navigator.msSaveOrOpenBlob) {
103 | window.navigator.msSaveOrOpenBlob(file, filename);
104 | } else {
105 | var a = document.createElement('a'),
106 | url = URL.createObjectURL(file);
107 | a.href = url;
108 | a.download = filename;
109 | document.body.appendChild(a);
110 | a.click();
111 | setTimeout(() => {
112 | document.body.removeChild(a);
113 | window.URL.revokeObjectURL(url);
114 | }, 10);
115 | }
116 | }
117 | var output = table.map(el => el.map(itm => str(itm)));
118 | downloadr((output), file_name+'.tsv');
119 | }
120 | function ymdFormat(d){
121 | let date = new Date(d);
122 | let yr = date.getFullYear();
123 | let mo = date.getMonth()+1;
124 | let day = date.getDate();
125 | return `${yr}-${(mo < 10 ? '0'+mo.toString() : mo)}-${(day < 10 ? '0'+day.toString() : day)}`;
126 | }
127 | async function getContributors(path){
128 | console.log(path);
129 | var res = await fetch(`https://github.com/${path}/graphs/contributors-data`, {
130 | "headers": {
131 | "accept": "application/json",
132 | "accept-language": "en-US,en;q=0.9",
133 | "sec-ch-ua": "\" Not;A Brand\";v=\"99\", \"Microsoft Edge\";v=\"97\", \"Chromium\";v=\"97\"",
134 | "sec-ch-ua-mobile": "?0",
135 | "sec-ch-ua-platform": "\"Windows\"",
136 | "sec-fetch-dest": "empty",
137 | "sec-fetch-mode": "cors",
138 | "sec-fetch-site": "same-origin",
139 | "x-requested-with": "XMLHttpRequest"
140 | },
141 | "referrer": `https://github.com/${path}/graphs/contributors`,
142 | "referrerPolicy": "no-referrer-when-downgrade",
143 | "body": null,
144 | "method": "GET",
145 | "mode": "cors",
146 | "credentials": "include"
147 | });
148 | var d = await res.json();
149 |
150 | var top100 = d.map(r=> {
151 | let index_c = Math.max(...r.weeks?.map(i=> i.c));
152 |
153 | let info = {
154 | added:r.weeks?.map(i=> i.a).reduce((a,b)=> a+b),
155 | deleted:r.weeks?.map(i=> i.d).reduce((a,b)=> a+b),
156 | commits:r.weeks?.map(i=> i.c).reduce((a,b)=> a+b),
157 | last_commit_week:ymdFormat( Math.max(...r.weeks?.map(i=> i.w)) * 1000),
158 | peak_commit_week:ymdFormat( r.weeks[r.weeks?.findIndex(i=> i.c == index_c)].w * 1000 )
159 | }
160 | return {
161 |
162 | ...r.author,
163 | ...info
164 | }
165 | })
166 | return top100;
167 | }
168 |
169 |
170 |
171 |
172 | var cleanNumbers = (s)=> /k/.test(s) ? parseFloat(s.replace(/k/))* 1000 : /\d/.test(s) ? parseFloat(s) : s;
173 |
174 | var cleanObject = (ob) =>
175 | Object.entries(ob).reduce((r, [k, v]) => {
176 | if( v != null && v != undefined && v !== "" && ( ['string','number','boolean','function','symbol'].some(opt=> typeof v == opt) || (typeof v == 'object' && ((Array.isArray(v) && v.length) || (Array.isArray(v) != true) ) ) ) ) {
177 | r[k] = v;
178 | return r;
179 | } else {
180 | return r;
181 | }
182 | }, {});
183 |
184 |
185 | function topZIndexer(){
186 | let n = new Date().getTime() / 1000000;
187 | let r = (n - Math.floor(n)) * 100000;
188 | return (Math.ceil(n+r) * 10);
189 | }
190 |
191 | function inlineStyler(elm,css){
192 | Object.entries(JSON.parse(
193 | css.replace(/(?<=:)\s*(\b|\B)(?=.+?;)/g,'"')
194 | .replace(/(?<=:\s*.+?);/g,'",')
195 | .replace(/[a-zA-Z-]+(?=:)/g, k=> k.replace(/^\b/,'"').replace(/\b$/,'"'))
196 | .replace(/\s*,\s*\}/g,'}')
197 | )).forEach(kv=> { elm.style[kv[0]] = kv[1]});
198 | }
199 |
200 | async function getEmailFromProfile(url) {
201 | var res = await fetch(url + '?tab=repositories');
202 | var text = await res.text();
203 | var doc = new DOMParser().parseFromString(text, 'text/html');
204 | var repos = doc.getElementsByClassName('col-12 d-flex width-full py-4 border-bottom public source');
205 | var targetRepos = Array.from(repos).map(itm => itm.getElementsByTagName('a')[0].href + '/commit/master.patch');
206 | return await checkEmailPatch(targetRepos);
207 | }
208 |
209 | async function getPatches(link) {
210 | var res = await fetch(link);
211 | var html = await res.text();
212 | var email = /\b[\w\.\-\+]+@[\w\-]+\.[a-zA-Z]{2,13}(\.[a-zA-Z]{2,13}|\b)/i.exec(html)?.[0];
213 | return email;
214 | }
215 |
216 | async function checkEmailPatch(repos) {
217 | for (i = 0; i < repos.length; i++) {
218 | var email = await getPatches(repos[i]);
219 | if (email != '') {
220 | return email;
221 | }
222 | }
223 | }
224 |
225 | async function getProfileDetails(url) {
226 | var snakeCaser = (s) => s.split(/(?<=[a-z])\B(?=[A-Z])/).map(i=> i.toLowerCase()).reduce((a,b)=> a+'_'+b)
227 | var res = await fetch(url);
228 | var text = await res.text();
229 | var doc = new DOMParser().parseFromString(text, 'text/html');
230 | let follow_hrefs = Array.from(doc.getElementsByTagName('a'))?.filter(i=> /tab\=follow/.test(i.href));
231 | var email_check = await getEmailFromProfile(url);
232 | var email = email_check && /noreply/i.test(email_check) === false ? email_check : '';
233 | let vcards = Array.from(Array.from(doc.getElementsByTagName('ul')).filter(i=> i.getAttribute('class') == 'vcard-details')?.[0]?.getElementsByTagName('li'))?.filter(li=> li.getAttribute('itemprop'))?.map(li=> {
234 | return {
235 | [snakeCaser(li.getAttribute('itemprop'))]:li.innerText?.trim()?.replace(/^.+?\n/,'')?.trim()
236 | }
237 | });
238 |
239 | let output = cleanObject({
240 | ...{
241 | num_following:cleanNumbers(follow_hrefs?.filter(i=> /tab\=following/.test(i.href))?.[0]?.getElementsByTagName('span')?.[0]?.innerText?.trim()),
242 | num_followers:cleanNumbers(follow_hrefs?.filter(i=> /tab\=follower/.test(i.href))?.[0]?.getElementsByTagName('span')?.[0]?.innerText?.trim()),
243 | bio: doc.getElementsByClassName('user-profile-bio')?.[0]?.innerText?.trim()?.replace(/\t|\n|\r/g, ' '),
244 | fullname: doc.getElementsByClassName('vcard-fullname')?.[0]?.innerText?.trim()?.replace(/\t|\n|\r/g, ' '),
245 | email:email,
246 | },
247 | ...(vcards?.length ? vcards.reduce((a,b)=> {return {...a,...b}}) : {})
248 | })
249 | return output;
250 | }
251 | async function loopThroughUserProfiles(){
252 | var contain_arr = [];
253 | createDownloadHTML();
254 | let top_contributors = await getContributors(/(?<=\.\w+\/)\S+?\/\S+?(?=\/)/.exec(window.location.href)?.[0]);
255 | for(let i =0; i