111 lines
3.8 KiB
D
111 lines
3.8 KiB
D
|
module csgs.task;
|
||
|
|
||
|
import slf4d;
|
||
|
import scheduled;
|
||
|
|
||
|
import std.datetime;
|
||
|
import std.typecons;
|
||
|
import std.json;
|
||
|
import std.string;
|
||
|
import std.file;
|
||
|
import std.stdio;
|
||
|
|
||
|
import csgs.extract;
|
||
|
|
||
|
void startScheduledTasks() {
|
||
|
JobScheduler scheduler = new ThreadedJobScheduler();
|
||
|
Job cleanJob = new FunctionJob(&cleanOldExtracts);
|
||
|
scheduler.addJob(cleanJob, new FixedIntervalSchedule(days(1)));
|
||
|
Job updateCheckJob = new FunctionJob(&checkForExtractorUpdate);
|
||
|
scheduler.addJob(updateCheckJob, new FixedIntervalSchedule(hours(1)));
|
||
|
scheduler.start();
|
||
|
}
|
||
|
|
||
|
private void cleanOldExtracts() {
|
||
|
import std.file;
|
||
|
immutable MAX_AGE = days(5);
|
||
|
info("Cleaning old extracts.");
|
||
|
if (!exists(EXTRACTS_DIR)) return;
|
||
|
immutable SysTime now = Clock.currTime();
|
||
|
foreach (DirEntry entry; dirEntries(EXTRACTS_DIR, SpanMode.shallow, false)) {
|
||
|
if (entry.isDir) {
|
||
|
infoF!"Removing directory %s."(entry.name);
|
||
|
rmdirRecurse(entry.name);
|
||
|
} else if (entry.isFile) {
|
||
|
immutable Duration age = now - entry.timeLastModified();
|
||
|
if (age > MAX_AGE) {
|
||
|
infoF!"Removing extract %s because it's too old."(entry.name);
|
||
|
std.file.remove(entry.name);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void checkForExtractorUpdate() {
|
||
|
import requests;
|
||
|
import std.json;
|
||
|
import std.stdio;
|
||
|
import std.string;
|
||
|
import std.file;
|
||
|
info("Checking for MaterialsExtractor program updates.");
|
||
|
|
||
|
// First request the latest release from GitHub API:
|
||
|
Request req = Request();
|
||
|
req.addHeaders(["Accept": "application/vnd.github+json"]);
|
||
|
Response resp = req.get("https://api.github.com/repos/andrewlalis/MaterialsExtractor/releases/latest");
|
||
|
if (resp.code() != 200) {
|
||
|
warnF!"Failed to get the latest MaterialsExtractor release. Status code %d."(resp.code);
|
||
|
return;
|
||
|
}
|
||
|
JSONValue responseJson = parseJSON(resp.responseBody.toString());
|
||
|
|
||
|
// Get the release's version, compare it with our current version.
|
||
|
immutable string releaseVersion = responseJson.object["tag_name"].str;
|
||
|
infoF!"Found release version %s"(releaseVersion);
|
||
|
Nullable!string currentVersion = getCurrentExtractorVersion();
|
||
|
if (!currentVersion.isNull && currentVersion.get() >= releaseVersion) {
|
||
|
infoF!"Skipping this version since it's not newer than the current %s."(currentVersion.get);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Find the release's asset, and download it.
|
||
|
Nullable!JSONValue nullableAsset = findJarAsset(responseJson);
|
||
|
if (nullableAsset.isNull) {
|
||
|
warn("Latest release has no asset. Ignoring.");
|
||
|
return;
|
||
|
}
|
||
|
JSONValue asset = nullableAsset.get();
|
||
|
immutable string filename = asset.object["name"].str;
|
||
|
immutable string downloadUrl = asset.object["browser_download_url"].str;
|
||
|
infoF!"Found asset: %s. Downloading from %s."(filename, downloadUrl);
|
||
|
if (exists(filename)) {
|
||
|
std.file.remove(filename);
|
||
|
}
|
||
|
|
||
|
Request downloadRequest = Request();
|
||
|
downloadRequest.useStreaming = true;
|
||
|
Response downloadResponse = downloadRequest.get(downloadUrl);
|
||
|
File f = File(filename, "wb");
|
||
|
auto stream = downloadResponse.receiveAsRange();
|
||
|
while (!stream.empty) {
|
||
|
f.rawWrite(stream.front);
|
||
|
stream.popFront();
|
||
|
}
|
||
|
f.close();
|
||
|
infoF!"Downloaded file to %s"(f.name);
|
||
|
}
|
||
|
|
||
|
private Nullable!JSONValue findJarAsset(ref JSONValue response) {
|
||
|
foreach (JSONValue asset; response.object["assets"].array) {
|
||
|
immutable string name = asset.object["name"].str;
|
||
|
if (
|
||
|
startsWith(name, "materials-extractor") &&
|
||
|
endsWith(name, ".jar") &&
|
||
|
asset.object["content_type"].str == "application/java-archive"
|
||
|
) {
|
||
|
return nullable(asset);
|
||
|
}
|
||
|
}
|
||
|
return Nullable!JSONValue.init;
|
||
|
}
|