Bug fixing, JSON parsing more robust
This commit is contained in:
@@ -7,8 +7,8 @@ android {
|
||||
applicationId "de.sebse.fuplanner"
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 28
|
||||
versionCode 9
|
||||
versionName "1.2.1"
|
||||
versionCode 10
|
||||
versionName "1.2.2"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
@@ -32,7 +32,6 @@ dependencies {
|
||||
androidTestImplementation('androidx.test.espresso:espresso-core:3.1.0-beta02', {
|
||||
exclude group: 'com.android.support', module: 'support-annotations'
|
||||
})
|
||||
implementation 'androidx.appcompat:appcompat:1.0.0'
|
||||
implementation 'androidx.preference:preference:1.0.0'
|
||||
implementation 'com.google.android.material:material:1.0.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha2'
|
||||
@@ -42,7 +41,7 @@ dependencies {
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation 'androidx.appcompat:appcompat:1.0.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.0.2'
|
||||
implementation 'org.jbundle.util.osgi.wrapped:org.jbundle.util.osgi.wrapped.org.apache.http.client:4.1.2'
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
implementation 'org.jetbrains:annotations-java5:15.0'
|
||||
|
||||
@@ -231,6 +231,7 @@ class ModDetailOverviewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
|
||||
mText = view.findViewById(R.id.expand_text_view);//.findViewById(R.id.description);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + " '" + mText.getText() + "'";
|
||||
|
||||
@@ -34,22 +34,29 @@ public class KVVModulesAnnouncements extends ModulesPart<ArrayList<Announcement>
|
||||
|
||||
@Override
|
||||
protected void upgrade(final String ID, final NetworkCallback<ArrayList<Announcement>> callback, final NetworkErrorCallback errorCallback) {
|
||||
if (!login.isInOnlineMode() || login.getLoginToken() == null) {
|
||||
if (!mLogin.isInOnlineMode() || mLogin.getLoginToken() == null) {
|
||||
errorCallback.onError(new NetworkError(101204, 500, "Currently running in offline mode!"));
|
||||
return;
|
||||
}
|
||||
super.get(String.format("https://kvv.imp.fu-berlin.de/direct/announcement/site/%s.json?n=999999&d=999999999", ID), login.getLoginToken().getCookies(), response -> {
|
||||
super.get(String.format("https://kvv.imp.fu-berlin.de/direct/announcement/site/%s.json?n=999999&d=999999999", ID), mLogin.getLoginToken().getCookies(), response -> {
|
||||
String body = response.getParsed();
|
||||
if (body == null) {
|
||||
errorCallback.onError(new NetworkError(101201, 403, "No announcements retrieved!"));
|
||||
return;
|
||||
}
|
||||
ArrayList<Announcement> announcements = new ArrayList<>();
|
||||
JSONArray sites;
|
||||
try {
|
||||
JSONObject json = new JSONObject(body);
|
||||
JSONArray sites = json.getJSONArray("announcement_collection");
|
||||
sites = json.getJSONArray("announcement_collection");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
errorCallback.onError(new NetworkError(101202, 403, "Cannot parse announcements!"));
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < sites.length(); i++) {
|
||||
try {
|
||||
JSONObject site = sites.getJSONObject(i);
|
||||
String id = site.getString("announcementId");
|
||||
String title = site.getString("title");
|
||||
@@ -61,21 +68,21 @@ public class KVVModulesAnnouncements extends ModulesPart<ArrayList<Announcement>
|
||||
// Extract attachment links
|
||||
JSONArray attachments = site.getJSONArray("attachments");
|
||||
ArrayList<String> urls = new ArrayList<>();
|
||||
for (int j =0; j<attachments.length(); j++){
|
||||
urls.add(attachments.getJSONObject(j).optString("url",null));
|
||||
for (int j = 0; j < attachments.length(); j++) {
|
||||
urls.add(attachments.getJSONObject(j).optString("url", null));
|
||||
}
|
||||
|
||||
announcements.add(new Announcement(id, title, text, createdBy, createdOn, urls));
|
||||
}
|
||||
|
||||
} catch (JSONException e) {
|
||||
log.e(new NetworkError(101205, 403, "Cannot parse announcements!"));
|
||||
e.printStackTrace();
|
||||
errorCallback.onError(new NetworkError(101202, 403, "Cannot parse announcements!"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Empty announcements *may be* because token is invalid -> check
|
||||
if (announcements.size() == 0)
|
||||
login.testLoginToken(token -> callback.onResponse(announcements), errorCallback);
|
||||
mLogin.testLoginToken(token -> callback.onResponse(announcements), errorCallback);
|
||||
else
|
||||
callback.onResponse(announcements);
|
||||
}, error -> errorCallback.onError(new NetworkError(101203, error.networkResponse.statusCode, "Cannot get announcements!")));
|
||||
|
||||
@@ -35,22 +35,29 @@ public class KVVModulesAssignments extends ModulesPart<AssignmentList> {
|
||||
|
||||
@Override
|
||||
protected void upgrade(final String ID, final NetworkCallback<AssignmentList> callback, final NetworkErrorCallback errorCallback) {
|
||||
if (!login.isInOnlineMode() || login.getLoginToken() == null) {
|
||||
if (!mLogin.isInOnlineMode() || mLogin.getLoginToken() == null) {
|
||||
errorCallback.onError(new NetworkError(101304, 500, "Currently running in offline mode!"));
|
||||
return;
|
||||
}
|
||||
get(String.format("https://kvv.imp.fu-berlin.de/direct/assignment/site/%s.json", ID), login.getLoginToken().getCookies(), response ->{
|
||||
get(String.format("https://kvv.imp.fu-berlin.de/direct/assignment/site/%s.json", ID), mLogin.getLoginToken().getCookies(), response -> {
|
||||
String body = response.getParsed();
|
||||
if (body == null) {
|
||||
errorCallback.onError(new NetworkError(101301, 403, "No assignments retrieved!"));
|
||||
return;
|
||||
}
|
||||
AssignmentList assignments = new AssignmentList();
|
||||
JSONArray sites;
|
||||
try {
|
||||
JSONObject json = new JSONObject(body);
|
||||
JSONArray sites = json.getJSONArray("assignment_collection");
|
||||
sites = json.getJSONArray("assignment_collection");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
errorCallback.onError(new NetworkError(101302, 403, "Cannot parse assignments!"));
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < sites.length(); i++) {
|
||||
try {
|
||||
JSONObject site = sites.getJSONObject(i);
|
||||
String id = site.getString("id");
|
||||
String title = site.getString("title");
|
||||
@@ -61,19 +68,20 @@ public class KVVModulesAssignments extends ModulesPart<AssignmentList> {
|
||||
String gradeScale = site.getString("gradeScale");
|
||||
JSONArray attachments = site.getJSONArray("attachments");
|
||||
ArrayList<String> urls = new ArrayList<>();
|
||||
for (int j = 0; j<attachments.length(); j++){
|
||||
for (int j = 0; j < attachments.length(); j++) {
|
||||
urls.add(attachments.getJSONObject(j).getString("url"));
|
||||
}
|
||||
assignments.add(0, new Assignment(id, title, dueTime, gradebookItemName, gradeScale, urls, instructions));
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
log.e(new NetworkError(101305, 403, "Cannot parse assignments!"));
|
||||
e.printStackTrace();
|
||||
errorCallback.onError(new NetworkError(101302, 403, "Cannot parse announcements!"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Empty assignments *may be* because token is invalid -> check
|
||||
if (assignments.size() == 0)
|
||||
login.testLoginToken(token -> callback.onResponse(assignments), errorCallback);
|
||||
mLogin.testLoginToken(token -> callback.onResponse(assignments), errorCallback);
|
||||
else
|
||||
callback.onResponse(assignments);
|
||||
}, error -> errorCallback.onError(new NetworkError(101303, error.networkResponse.statusCode, "Cannot get announcements!")));
|
||||
|
||||
@@ -136,11 +136,10 @@ public class KVVModulesList extends HTTPService {
|
||||
}
|
||||
|
||||
private void upgrade(final NetworkCallback<Modules> callback, final NetworkErrorCallback errorCallback) {
|
||||
if (!mLogin.isInOnlineMode()) {
|
||||
if (!mLogin.isInOnlineMode() || mLogin.getLoginToken() == null) {
|
||||
errorCallback.onError(new NetworkError(101105, 500, "Currently running in offline mode!"));
|
||||
return;
|
||||
}
|
||||
// https://file.io/71sa2V
|
||||
get("https://kvv.imp.fu-berlin.de/direct/site.json", mLogin.getLoginToken().getCookies(), response -> {
|
||||
String body = response.getParsed();
|
||||
if (body == null) {
|
||||
@@ -148,37 +147,43 @@ public class KVVModulesList extends HTTPService {
|
||||
return;
|
||||
}
|
||||
Modules modules = new Modules(mLogin.getLoginToken().getUsername());
|
||||
JSONArray sites;
|
||||
try {
|
||||
JSONObject json = new JSONObject(body);
|
||||
JSONArray sites = json.getJSONArray("site_collection");
|
||||
|
||||
for (int i = 0; i < sites.length(); i++) {
|
||||
JSONObject site = sites.getJSONObject(i);
|
||||
String semester = site.getJSONObject("props").getString("term_eid");
|
||||
HashSet<String> lvNumbers = new HashSet<>();
|
||||
for (MatchResult matchResult : Regex.allMatches("[0-9]+", site.getJSONObject("props").getString("kvv_lvnumbers"))) {
|
||||
lvNumbers.add(matchResult.group());
|
||||
}
|
||||
String title = site.getString("entityTitle");
|
||||
HashSet<Lecturer> lecturers = new HashSet<>();
|
||||
for (String lecturer : site.getJSONObject("props").getString("kvv_lecturers").split("#")) {
|
||||
if (lecturer.length() > 2)
|
||||
lecturers.add(new Lecturer(lecturer));
|
||||
}
|
||||
String type = site.getJSONObject("props").getString("kvv_coursetype");
|
||||
String description = site.getString("description");
|
||||
description = String.valueOf(ModulesPart.fromHtml(description));
|
||||
String id = site.getString("id");
|
||||
modules.addModule(semester, lvNumbers, title, lecturers, type, description, id);
|
||||
}
|
||||
sites = json.getJSONArray("site_collection");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
errorCallback.onError(new NetworkError(101102, 403, "Cannot parse module list!"));
|
||||
return;
|
||||
} catch (NoSuchFieldException e) {
|
||||
}
|
||||
for (int i = 0; i < sites.length(); i++) {
|
||||
try {
|
||||
JSONObject site = sites.getJSONObject(i);
|
||||
String semester = site.getJSONObject("props").optString("term_eid", null);
|
||||
HashSet<String> lvNumbers = new HashSet<>();
|
||||
String kvv_lvnumbers = site.getJSONObject("props").optString("kvv_lvnumbers", null);
|
||||
if (kvv_lvnumbers != null) for (MatchResult matchResult : Regex.allMatches("[0-9]+", kvv_lvnumbers)) {
|
||||
lvNumbers.add(matchResult.group());
|
||||
}
|
||||
String title = site.getString("entityTitle");
|
||||
HashSet<Lecturer> lecturers = new HashSet<>();
|
||||
String kvv_lecturers = site.getJSONObject("props").optString("kvv_lecturers", null);
|
||||
if (kvv_lecturers != null) for (String lecturer : kvv_lecturers.split("#")) {
|
||||
if (lecturer.length() > 2)
|
||||
lecturers.add(new Lecturer(lecturer));
|
||||
}
|
||||
String type = site.getJSONObject("props").optString("kvv_coursetype", null);
|
||||
String description = site.optString("description", "");
|
||||
description = String.valueOf(ModulesPart.fromHtml(description));
|
||||
String id = site.getString("id");
|
||||
modules.addModule(semester, lvNumbers, title, lecturers, type, description, id);
|
||||
} catch (JSONException e) {
|
||||
log.e(new NetworkError(101103, 403, "Cannot parse module list!"));
|
||||
e.printStackTrace();
|
||||
errorCallback.onError(new NetworkError(101103, 403, "Cannot parse module list!"));
|
||||
return;
|
||||
} catch (NoSuchFieldException e) {
|
||||
log.e(new NetworkError(101106, 403, "Cannot parse module list!"));
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
// Empty module *may be* because token is invalid -> check
|
||||
if (modules.size() == 0)
|
||||
|
||||
@@ -11,7 +11,7 @@ import de.sebse.fuplanner.tools.network.NetworkCallback;
|
||||
import de.sebse.fuplanner.tools.network.NetworkErrorCallback;
|
||||
|
||||
abstract class ModulesPart<T> extends Part<Modules.Module> {
|
||||
private NewAsyncQueue queue = new NewAsyncQueue();
|
||||
private NewAsyncQueue mQueue = new NewAsyncQueue();
|
||||
|
||||
ModulesPart(KVVLogin login, KVVModulesList list, Context context) {
|
||||
super(login, list, context);
|
||||
@@ -19,28 +19,28 @@ abstract class ModulesPart<T> extends Part<Modules.Module> {
|
||||
|
||||
@Override
|
||||
protected void recv(final Modules.Module module, final NetworkCallback<Modules.Module> callback, final NetworkErrorCallback errorCallback, final boolean forceRefresh, final int retries) {
|
||||
queue.add(() -> {
|
||||
mQueue.add(() -> {
|
||||
if (getPart(module) != null && !forceRefresh) {
|
||||
callback.onResponse(module);
|
||||
queue.next();
|
||||
mQueue.next();
|
||||
return;
|
||||
}
|
||||
upgrade(module.getID(), success -> {
|
||||
if (setPart(module, success)) {
|
||||
this.list.store();
|
||||
this.mList.store();
|
||||
}
|
||||
callback.onResponse(module);
|
||||
queue.next();
|
||||
mQueue.next();
|
||||
}, error -> {
|
||||
if (retries >= 0 && (error.getHttpStatus() == 401 || error.getHttpStatus() == 403)) {
|
||||
login.refreshLogin(success -> {
|
||||
mLogin.refreshLogin(success -> {
|
||||
recv(module, callback, errorCallback, forceRefresh, retries-1);
|
||||
queue.next();
|
||||
mQueue.next();
|
||||
}, errorCallback);
|
||||
return;
|
||||
}
|
||||
errorCallback.onError(error);
|
||||
queue.next();
|
||||
mQueue.next();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,20 +3,19 @@ package de.sebse.fuplanner.services.NewKVV;
|
||||
import android.content.Context;
|
||||
|
||||
import de.sebse.fuplanner.services.NewKVV.types.Modules;
|
||||
import de.sebse.fuplanner.tools.NewAsyncQueue;
|
||||
import de.sebse.fuplanner.tools.network.HTTPService;
|
||||
import de.sebse.fuplanner.tools.network.NetworkCallback;
|
||||
import de.sebse.fuplanner.tools.network.NetworkErrorCallback;
|
||||
|
||||
public abstract class Part<T> extends HTTPService {
|
||||
static final int RETRY_COUNT = 1;
|
||||
protected final KVVLogin login;
|
||||
protected final KVVModulesList list;
|
||||
protected final KVVLogin mLogin;
|
||||
protected final KVVModulesList mList;
|
||||
|
||||
Part(KVVLogin login, KVVModulesList list, Context context) {
|
||||
super(context);
|
||||
this.login = login;
|
||||
this.list = list;
|
||||
this.mLogin = login;
|
||||
this.mList = list;
|
||||
}
|
||||
|
||||
public void recv(final String moduleID, final NetworkCallback<T> callback, final NetworkErrorCallback errorCallback) {
|
||||
@@ -24,7 +23,7 @@ public abstract class Part<T> extends HTTPService {
|
||||
}
|
||||
|
||||
public void recv(final String moduleID, final NetworkCallback<T> callback, final NetworkErrorCallback errorCallback, final boolean forceRefresh) {
|
||||
list.find(moduleID, success -> recv(success, callback, errorCallback, forceRefresh, RETRY_COUNT), errorCallback);
|
||||
mList.find(moduleID, success -> recv(success, callback, errorCallback, forceRefresh, RETRY_COUNT), errorCallback);
|
||||
}
|
||||
|
||||
abstract protected void recv(final Modules.Module module, final NetworkCallback<T> callback, final NetworkErrorCallback errorCallback, final boolean forceRefresh, final int retries);
|
||||
|
||||
@@ -2,6 +2,8 @@ package de.sebse.fuplanner.services.NewKVV.types;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -30,7 +32,7 @@ public class Modules implements Iterable<Modules.Module>, Serializable {
|
||||
this.list = new SortedListModule();
|
||||
}
|
||||
|
||||
public void addModule(String semester, HashSet<String> lvNumber, String title, HashSet<Lecturer> lecturer, String type, String description, String ID) {
|
||||
public void addModule(@Nullable String semester, HashSet<String> lvNumber, String title, HashSet<Lecturer> lecturer, String type, String description, String ID) {
|
||||
Module m = new Module(semester, lvNumber, title, lecturer, type, description, ID);
|
||||
this.list.add(m);
|
||||
}
|
||||
@@ -104,24 +106,19 @@ public class Modules implements Iterable<Modules.Module>, Serializable {
|
||||
}
|
||||
|
||||
public class Module implements Serializable {
|
||||
public final String semester;
|
||||
final HashSet<String> lvNumber;
|
||||
public final String title;
|
||||
final HashSet<Lecturer> lecturer;
|
||||
public final String type;
|
||||
public final String description;
|
||||
private final String ID;
|
||||
@Nullable public final String semester;
|
||||
@NotNull final HashSet<String> lvNumber;
|
||||
@NotNull public final String title;
|
||||
@NotNull final HashSet<Lecturer> lecturer;
|
||||
@Nullable public final String type;
|
||||
@Nullable public final String description;
|
||||
@NotNull private final String ID;
|
||||
@Nullable public ArrayList<Announcement> announcements;
|
||||
@Nullable public AssignmentList assignments;
|
||||
@Nullable public EventList events;
|
||||
@Nullable public ArrayList<Gradebook> gradebook;
|
||||
@Nullable public ArrayList<Resource> resources;
|
||||
|
||||
/*private Module() {
|
||||
this(null, null, null, null, null);
|
||||
throw new AssertionError("Do not use this constructor!");
|
||||
}*/
|
||||
|
||||
public float getGradebookPercent(){
|
||||
float maxPoint = 0;
|
||||
float userPoint = 0;
|
||||
@@ -136,9 +133,11 @@ public class Modules implements Iterable<Modules.Module>, Serializable {
|
||||
return userPoint/maxPoint;
|
||||
}
|
||||
|
||||
private Module(String semester, HashSet<String> lvNumber, String title, HashSet<Lecturer> lecturer, String type, String description, String ID) {
|
||||
private Module(@Nullable String semester, @NotNull HashSet<String> lvNumber, @NotNull String title, @NotNull HashSet<Lecturer> lecturer, @Nullable String type, @Nullable String description, @NotNull String ID) {
|
||||
if (semester != null) {
|
||||
semester = semester.replace("SS", "S");
|
||||
semester = semester.replaceAll("[0-9]{2}([0-9]{2})", "$1");
|
||||
}
|
||||
title = title.replaceAll("(.*?) (S[0-9]{2}|W[0-9/]{5})", "$1");
|
||||
|
||||
this.semester = semester;
|
||||
@@ -150,6 +149,7 @@ public class Modules implements Iterable<Modules.Module>, Serializable {
|
||||
this.ID = ID;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getID() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@@ -63,6 +63,6 @@ public class SortedListModule extends SortedList<Modules.Module, String, String>
|
||||
|
||||
@Override
|
||||
public boolean hasFilter(Modules.Module o1, String filter) {
|
||||
return o1.semester.equals(filter);
|
||||
return o1.semester != null && o1.semester.equals(filter);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user