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.
282 lines
13 KiB
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;
|
|
}
|
|
|
|
}
|