mirror of
https://gitlab.com/vyla-entertainment/documentation.git
synced 2026-11-09 20:17:20 -05:00
154 lines
4.7 KiB
JavaScript
154 lines
4.7 KiB
JavaScript
var RELEASE_CACHE = {};
|
|
var RELEASE_REQUESTS = {};
|
|
var RELEASE_CACHE_TTL = 15 * 60 * 1000;
|
|
var RELEASE_BACKOFF = {};
|
|
var RELEASE_MAX_RETRIES = 3;
|
|
|
|
function fetchProjectReleases(project) {
|
|
var now = Date.now();
|
|
var cached = RELEASE_CACHE[project];
|
|
|
|
if (cached && now - cached.timestamp < RELEASE_CACHE_TTL) {
|
|
return Promise.resolve(cached.data);
|
|
}
|
|
|
|
if (RELEASE_REQUESTS[project]) {
|
|
return RELEASE_REQUESTS[project];
|
|
}
|
|
|
|
var backoff = RELEASE_BACKOFF[project];
|
|
|
|
if (backoff && now < backoff.until) {
|
|
return Promise.resolve(cached ? cached.data : []);
|
|
}
|
|
|
|
var url = "https://gitlab.com/api/v4/projects/vyla-entertainment%2F" +
|
|
encodeURIComponent(project) + "/releases";
|
|
|
|
var request = function (attempt) {
|
|
return fetch(url)
|
|
.then(function (res) {
|
|
if (res.status === 429) {
|
|
var retryAfter = Number(res.headers.get("Retry-After"));
|
|
var delay = retryAfter > 0
|
|
? retryAfter * 1000
|
|
: Math.min(5000 * Math.pow(2, attempt), 60000);
|
|
|
|
RELEASE_BACKOFF[project] = {
|
|
until: Date.now() + delay
|
|
};
|
|
|
|
if (attempt < RELEASE_MAX_RETRIES) {
|
|
return new Promise(function (resolve) {
|
|
setTimeout(resolve, delay);
|
|
}).then(function () {
|
|
return request(attempt + 1);
|
|
});
|
|
}
|
|
|
|
throw new Error("GitLab rate limit exceeded");
|
|
}
|
|
|
|
if (!res.ok) {
|
|
throw new Error("GitLab API returned " + res.status);
|
|
}
|
|
|
|
return res.json();
|
|
})
|
|
.then(function (data) {
|
|
if (!Array.isArray(data)) {
|
|
throw new Error("Invalid GitLab releases response");
|
|
}
|
|
|
|
RELEASE_CACHE[project] = {
|
|
data: data,
|
|
timestamp: Date.now()
|
|
};
|
|
|
|
delete RELEASE_BACKOFF[project];
|
|
|
|
return data;
|
|
});
|
|
};
|
|
|
|
RELEASE_REQUESTS[project] = request(0)
|
|
.catch(function () {
|
|
return cached ? cached.data : [];
|
|
})
|
|
.finally(function () {
|
|
delete RELEASE_REQUESTS[project];
|
|
});
|
|
|
|
return RELEASE_REQUESTS[project];
|
|
}
|
|
|
|
function findAssetInReleases(releases, ext) {
|
|
for (var r = 0; r < releases.length; r++) {
|
|
var rel = releases[r];
|
|
var tag = rel.tag_name || "";
|
|
var links = (rel.assets && rel.assets.links) || [];
|
|
|
|
for (var i = 0; i < links.length; i++) {
|
|
var l = links[i];
|
|
var name = (l.name || "").toLowerCase();
|
|
var url = (l.url || "").toLowerCase();
|
|
|
|
if (name.indexOf(ext.toLowerCase()) !== -1 ||
|
|
url.indexOf(ext.toLowerCase()) !== -1) {
|
|
return {
|
|
tag: tag,
|
|
url: l.direct_asset_url || l.url
|
|
};
|
|
}
|
|
}
|
|
|
|
if (rel.description) {
|
|
var escapedExt = ext.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
|
|
var reg = new RegExp(
|
|
"\\[([^\\]]+)\\]\\((https?:[^)]+\\." + escapedExt + "[^)]*)\\)",
|
|
"i"
|
|
);
|
|
|
|
var match = rel.description.match(reg);
|
|
|
|
if (match) {
|
|
return { tag: tag, url: match[2] };
|
|
}
|
|
|
|
var rawMatch = rel.description.match(
|
|
new RegExp("(https?:\\S+\\." + escapedExt + ")", "i")
|
|
);
|
|
|
|
if (rawMatch) {
|
|
return { tag: tag, url: rawMatch[1] };
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function findAssetInReleases(releases, ext) {
|
|
for (var r = 0; r < releases.length; r++) {
|
|
var rel = releases[r];
|
|
var tag = rel.tag_name || "";
|
|
var links = (rel.assets && rel.assets.links) || [];
|
|
for (var i = 0; i < links.length; i++) {
|
|
var l = links[i];
|
|
var name = (l.name || "").toLowerCase();
|
|
var url = (l.url || "").toLowerCase();
|
|
if (name.indexOf(ext) !== -1 || url.indexOf(ext) !== -1) {
|
|
return { tag: tag, url: l.direct_asset_url || l.url };
|
|
}
|
|
}
|
|
if (rel.description) {
|
|
var reg = new RegExp("\\[([^\\]]+)\\]\\((https?:[^)]+\\." + ext + "[^)]*)\\)", "i");
|
|
var match = rel.description.match(reg);
|
|
if (match) return { tag: tag, url: match[2] };
|
|
var rawMatch = rel.description.match(new RegExp("(https?:\\S+\\." + ext + ")", "i"));
|
|
if (rawMatch) return { tag: tag, url: rawMatch[1] };
|
|
}
|
|
}
|
|
return null;
|
|
} |