135 lines
3.6 KiB
JavaScript
135 lines
3.6 KiB
JavaScript
|
"use strict";
|
||
|
|
||
|
const fs = require("fs");
|
||
|
const { resolve } = require("path");
|
||
|
const zlib = require("zlib");
|
||
|
|
||
|
const { id } = require("../packages/hash");
|
||
|
const { fetchJson } = require("../packages/web");
|
||
|
|
||
|
const CacheDir = resolve(__dirname, "../github-cache/");
|
||
|
|
||
|
function addResponse(result, response) {
|
||
|
return { result, response };
|
||
|
}
|
||
|
|
||
|
function loadFile(filename) {
|
||
|
return JSON.parse(zlib.gunzipSync(fs.readFileSync(filename)).toString());
|
||
|
//return JSON.parse(fs.readFileSync(filename).toString());
|
||
|
}
|
||
|
|
||
|
// @TODO: atomic
|
||
|
function saveFile(filename, content) {
|
||
|
fs.writeFileSync(filename, zlib.gzipSync(JSON.stringify(content)));
|
||
|
//fs.writeFileSync(filename, JSON.stringify(content));
|
||
|
}
|
||
|
|
||
|
function mockFetchJson(url, body, headers) {
|
||
|
return {
|
||
|
result: null,
|
||
|
response: {
|
||
|
statusCode: 304
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async function _fetchGitHub(user, password, fetchJson, url) {
|
||
|
const result = [ ];
|
||
|
while (true) {
|
||
|
|
||
|
const filename = resolve(CacheDir, id(url).substring(2, 14));
|
||
|
|
||
|
const headers = {
|
||
|
"User-Agent": "ethers-io",
|
||
|
};
|
||
|
|
||
|
let items = null;
|
||
|
let link = null;
|
||
|
try {
|
||
|
const data = loadFile(filename);
|
||
|
headers["if-none-match"] = data.etag;
|
||
|
items = data.items;
|
||
|
link = data.link;
|
||
|
} catch (error) {
|
||
|
if (error.code !== "ENOENT") { throw error; }
|
||
|
}
|
||
|
|
||
|
const fetch = await fetchJson({
|
||
|
url: url,
|
||
|
user: user,
|
||
|
password: password,
|
||
|
headers: headers
|
||
|
}, null, addResponse);
|
||
|
|
||
|
// Cached response is good; use it!
|
||
|
if (fetch.response.statusCode !== 304) {
|
||
|
items = fetch.result;
|
||
|
if (fetch.response.headers) {
|
||
|
link = (fetch.response.headers.link || null);
|
||
|
}
|
||
|
if (fetch.response.headers.etag){
|
||
|
saveFile(filename, {
|
||
|
timestamp: (new Date()).getTime(),
|
||
|
url: url,
|
||
|
link: link,
|
||
|
etag: fetch.response.headers.etag,
|
||
|
items: items,
|
||
|
version: 1
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
items.forEach((item) => { result.push(item)});
|
||
|
|
||
|
url = null;
|
||
|
(link || "").split(",").forEach((item) => {
|
||
|
if (item.indexOf('rel="next"') >= 0) {
|
||
|
const match = item.match(/<([^>]*)>/);
|
||
|
if (match) { url = match[1]; }
|
||
|
}
|
||
|
});
|
||
|
|
||
|
if (!url) { break; }
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
async function fetchGitHub(user, password, url, cacheOnly) {
|
||
|
if (cacheOnly) {
|
||
|
return await _fetchGitHub("none", "none", mockFetchJson, url);
|
||
|
}
|
||
|
|
||
|
const results = await _fetchGitHub(user, password, fetchJson, url);
|
||
|
return results;
|
||
|
}
|
||
|
|
||
|
|
||
|
async function _getIssues(user, password) {
|
||
|
const cacheOnly = (user == null);
|
||
|
|
||
|
let issues = await fetchGitHub(user, password, "https://api.github.com/repos/ethers-io/ethers.js/issues?state=all&per_page=100", cacheOnly)
|
||
|
if (!cacheOnly) { console.log(`Found ${ issues.length } issues`); }
|
||
|
const result = [ ];
|
||
|
for (let i = 0; i < issues.length; i++) {
|
||
|
const issue = issues[i];
|
||
|
let comments = await fetchGitHub(user, password, issue.comments_url, cacheOnly);
|
||
|
result.push({ issue, comments});
|
||
|
if (!cacheOnly) { console.log(` Issue ${ issue.number }: ${ comments.length } comments`); }
|
||
|
}
|
||
|
result.sort((a, b) => (a.issue.number - b.issue.number));
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
function getIssues() {
|
||
|
return _getIssues();
|
||
|
}
|
||
|
|
||
|
function syncIssues(user, password) {
|
||
|
return _getIssues(user, password);
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
getIssues,
|
||
|
syncIssues,
|
||
|
}
|