You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
FoxMagiskModuleManager/app/src/main/java/com/fox2code/mmm/repo/RepoUpdater.java

282 lines
13 KiB
Java

package com.fox2code.mmm.repo;
import com.fox2code.mmm.utils.io.Http;
import com.fox2code.mmm.utils.realm.ModuleListCache;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import io.realm.Realm;
import io.realm.RealmConfiguration;
import timber.log.Timber;
public class RepoUpdater {
public final RepoData repoData;
public byte[] indexRaw;
private List<RepoModule> toUpdate;
private Collection<RepoModule> toApply;
public RepoUpdater(RepoData repoData) {
this.repoData = repoData;
}
public int fetchIndex() {
if (!RepoManager.getINSTANCE().hasConnectivity()) {
this.indexRaw = null;
this.toUpdate = Collections.emptyList();
this.toApply = Collections.emptySet();
return 0;
}
if (!this.repoData.isEnabled()) {
this.indexRaw = null;
this.toUpdate = Collections.emptyList();
this.toApply = Collections.emptySet();
return 0;
}
try {
if (!this.repoData.prepare()) {
this.indexRaw = null;
this.toUpdate = Collections.emptyList();
this.toApply = this.repoData.moduleHashMap.values();
return 0;
}
this.indexRaw = Http.doHttpGet(this.repoData.getUrl(), false);
this.toUpdate = this.repoData.populate(new JSONObject(new String(this.indexRaw, StandardCharsets.UTF_8)));
// Since we reuse instances this should work
this.toApply = new HashSet<>(this.repoData.moduleHashMap.values());
this.toApply.removeAll(this.toUpdate);
// Return repo to update
return this.toUpdate.size();
} catch (
Exception e) {
Timber.e(e);
this.indexRaw = null;
this.toUpdate = Collections.emptyList();
this.toApply = Collections.emptySet();
return 0;
}
}
public List<RepoModule> toUpdate() {
return this.toUpdate;
}
public Collection<RepoModule> toApply() {
return this.toApply;
}
public boolean finish() {
boolean success = this.indexRaw != null;
// If repo is not enabled we don't need to do anything, just return true
if (!this.repoData.isEnabled()) {
return true;
}
if (this.indexRaw != null) {
try {
// iterate over modules, using this.supportedProperties as a template to attempt to get each property from the module. everything that is not null is added to the module
// use realm to insert to
// props avail:
File cacheRoot = this.repoData.cacheRoot;
RealmConfiguration realmConfiguration = new RealmConfiguration.Builder().name("ModuleListCache.realm").schemaVersion(1).deleteRealmIfMigrationNeeded().allowWritesOnUiThread(true).allowQueriesOnUiThread(true).directory(cacheRoot).build();
// array with module info default values
// supported properties for a module
//id=<string>
//name=<string>
//version=<string>
//versionCode=<int>
//author=<string>
//description=<string>
//minApi=<int>
//maxApi=<int>
//minMagisk=<int>
//needRamdisk=<boolean>
//support=<url>
//donate=<url>
//config=<package>
//changeBoot=<boolean>
//mmtReborn=<boolean>
// extra properties only useful for the database
//repoId=<string>
//installed=<boolean>
//installedVersionCode=<int> (only if installed)
//
// all except first six can be null
// this.indexRaw is the raw index file (json)
JSONObject modules = new JSONObject(new String(this.indexRaw, StandardCharsets.UTF_8));
JSONArray modulesArray;
// androidacy repo uses "data" key, others should use "modules" key. Both are JSONArrays
if (this.repoData.getName().equals("Androidacy Modules Repo")) {
// get modules from "data" key. This is a JSONArray so we need to convert it to a JSONObject
modulesArray = modules.getJSONArray("data");
} else {
// get modules from "modules" key. This is a JSONArray so we need to convert it to a JSONObject
modulesArray = modules.getJSONArray("modules");
}
// iterate over modules. pls dont hate me for this, its ugly but it works
for (int n = 0; n < modulesArray.length(); n++) {
// get module
JSONObject module = modulesArray.getJSONObject(n);
try {
// get module id
String id = module.getString("id");
// get module name
String name = module.getString("name");
// get module version
String version = module.getString("version");
// get module version code
int versionCode = module.getInt("versionCode");
// get module author
String author = module.getString("author");
// get module description
String description = module.getString("description");
// get module min api
String minApi;
if (module.has("minApi") && !module.getString("minApi").equals("")) {
minApi = module.getString("minApi");
} else {
minApi = "0";
}
// coerce min api to int
int minApiInt = Integer.parseInt(minApi);
// get module max api and set to 0 if it's "" or null
String maxApi;
if (module.has("maxApi") && !module.getString("maxApi").equals("")) {
maxApi = module.getString("maxApi");
} else {
maxApi = "0";
}
// coerce max api to int
int maxApiInt = Integer.parseInt(maxApi);
// get module min magisk
String minMagisk;
if (module.has("minMagisk") && !module.getString("minMagisk").equals("")) {
minMagisk = module.getString("minMagisk");
} else {
minMagisk = "0";
}
// coerce min magisk to int
int minMagiskInt = Integer.parseInt(minMagisk);
// get module need ramdisk
boolean needRamdisk;
if (module.has("needRamdisk")) {
needRamdisk = module.getBoolean("needRamdisk");
} else {
needRamdisk = false;
}
// get module support
String support;
if (module.has("support")) {
support = module.getString("support");
} else {
support = "";
}
// get module donate
String donate;
if (module.has("donate")) {
donate = module.getString("donate");
} else {
donate = "";
}
// get module config
String config;
if (module.has("config")) {
config = module.getString("config");
} else {
config = "";
}
// get module change boot
boolean changeBoot;
if (module.has("changeBoot")) {
changeBoot = module.getBoolean("changeBoot");
} else {
changeBoot = false;
}
// get module mmt reborn
boolean mmtReborn;
if (module.has("mmtReborn")) {
mmtReborn = module.getBoolean("mmtReborn");
} else {
mmtReborn = false;
}
// get module repo id
String repoId = this.repoData.id;
// get module installed
boolean installed = false;
// get module installed version code
int installedVersionCode = 0;
// insert module to realm
// first create a collection of all the properties
// then insert to realm
// then commit
// then close
Realm realm = Realm.getInstance(realmConfiguration);
if (realm.isInTransaction()) {
realm.cancelTransaction();
}
realm.executeTransaction(r -> {
// create the object
// if it already exists, it will be updated
// create a new module
ModuleListCache moduleListCache = r.createObject(ModuleListCache.class, id);
// set module name
moduleListCache.setName(name);
// set module version
moduleListCache.setVersion(version);
// set module version code
moduleListCache.setVersionCode(versionCode);
// set module author
moduleListCache.setAuthor(author);
// set module description
moduleListCache.setDescription(description);
// set module min api
moduleListCache.setMinApi(minApiInt);
// set module max api
moduleListCache.setMaxApi(maxApiInt);
// set module min magisk
moduleListCache.setMinMagisk(minMagiskInt);
// set module need ramdisk
moduleListCache.setNeedRamdisk(needRamdisk);
// set module support
moduleListCache.setSupport(support);
// set module donate
moduleListCache.setDonate(donate);
// set module config
moduleListCache.setConfig(config);
// set module change boot
moduleListCache.setChangeBoot(changeBoot);
// set module mmt reborn
moduleListCache.setMmtReborn(mmtReborn);
// set module repo id
moduleListCache.setRepoId(repoId);
// set module installed
moduleListCache.setInstalled(installed);
// set module installed version code
moduleListCache.setInstalledVersionCode(installedVersionCode);
});
realm.close();
} catch (
Exception e) {
e.printStackTrace();
Timber.w("Failed to get module info from module " + module + " in repo " + this.repoData.id + " with error " + e.getMessage());
}
}
} catch (
Exception e) {
e.printStackTrace();
}
this.indexRaw = null;
}
this.toUpdate = null;
this.toApply = null;
return success;
}
}