Skip to content

Instantly share code, notes, and snippets.

@Frityet
Last active June 21, 2021 08:15
Show Gist options
  • Save Frityet/d19b8e57963279a648e875f45a1146b0 to your computer and use it in GitHub Desktop.
Save Frityet/d19b8e57963279a648e875f45a1146b0 to your computer and use it in GitHub Desktop.
I made this project on a boring car ride. It gets the download information of important H3VR mods and prints them to the console
import Foundation;
import PlaygroundSupport;
//We use async in this program, it needs to go inf
PlaygroundPage.current.needsIndefiniteExecution = true;
///Struct for a Github Asset (file inside the release)
struct GithubReleaseAsset : Decodable {
///Name of the asset
let fileName: String;
///Number of downloads
let downloadCount: Int32;
enum CodingKeys : String, CodingKey {
case fileName = "name";
case downloadCount = "download_count";
}
}
///Struct for a GitHub release,
struct GithubReleaseTag : Decodable {
///Version of the tag, also known as the tagname
let tagVersion: String;
///Title of the release
let tagName: String;
///All of the assets (files) in this release
let assets: [GithubReleaseAsset];
enum CodingKeys : String, CodingKey {
case tagVersion = "tag_name";
case tagName = "name";
case assets = "assets";
}
}
///Data about a mod
class Mod {
///Name of the mod. I could extract this from the path but I am lazy
let name: String;
///GitHub repo path to the mod. Needs to be in format {USER/ORGANISATION}/{REPOSITORY NAME}
let path: String;
///Number of downloads the most downloaded asset of every release is
var downloads: Int32 = 0;
init (name: String, path: String) {
self.name = name;
self.path = path;
let url: String = "https://api.github.com/repos/" + path + "/releases";
var request = URLRequest(url: URL(string: url)!);
request.httpMethod = "GET";
var downloads: Int32 = 0;
//Because swift async breaks everything we run this in a Semaphore so its in sync
let sync = DispatchSemaphore(value: 0);
let task = URLSession.shared.dataTask(with: request) { data, response, error in
defer { sync.signal(); }
guard let data = data, error == nil else {
print("error=\(String(describing: error))");
return;
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
print("statusCode should be 200, but is (httpStatus.statusCode)");
print("response = \(String(describing: response))");
}
if let body_response = String(data: data, encoding: String.Encoding.utf8) {
//Deserialise the raw JSON from the GitHub API
let deserialised: [GithubReleaseTag] = try! JSONDecoder().decode([GithubReleaseTag].self, from: body_response.data(using: .utf8)!);
for release in deserialised {
//We make an array of integers to count every download count of each asset, to get the one with most downloads
//I am aware this is very inefficient
var assetDlCounts: [Int32] = [];
for asset in release.assets {
assetDlCounts.append(asset.downloadCount);
}
assetDlCounts.sort();
downloads += assetDlCounts.last!;
}
}
}
task.resume();
sync.wait();
self.downloads = downloads;
}
}
print("Getting H3VR Mod statistics...");
let mods: [Mod] = [
Mod(name: "Deli", path: "Deli-Collective/Deli"),
Mod(name: "BetterHands", path: "Maiq-The-Dude/BetterHands"),
Mod(name: "WurstMod", path: "WurstModders/WurstMod")
];
for mod in mods {
print("\(mod.name) has \(String(describing: mod.downloads)) downloads");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment