From b10523ea6c5ac9bb1b5241b86fa3433ba040c66a Mon Sep 17 00:00:00 2001 From: Jan-Peter Klein Date: Tue, 9 May 2023 09:00:56 +0200 Subject: [PATCH 01/61] init commit --- .../cryptomator/ui/error/ErrorController.java | 184 +++++++++++++++++- .../cryptomator/ui/error/ErrorDiscussion.java | 31 +++ src/main/resources/fxml/error.fxml | 14 +- src/main/resources/i18n/strings.properties | 3 + 4 files changed, 226 insertions(+), 6 deletions(-) create mode 100644 src/main/java/org/cryptomator/ui/error/ErrorDiscussion.java diff --git a/src/main/java/org/cryptomator/ui/error/ErrorController.java b/src/main/java/org/cryptomator/ui/error/ErrorController.java index 422a44157..d3ac0f60f 100644 --- a/src/main/java/org/cryptomator/ui/error/ErrorController.java +++ b/src/main/java/org/cryptomator/ui/error/ErrorController.java @@ -1,10 +1,14 @@ package org.cryptomator.ui.error; +import com.google.common.reflect.TypeToken; +import com.google.gson.Gson; +import com.google.gson.JsonObject; import org.cryptomator.common.Environment; import org.cryptomator.common.ErrorCode; import org.cryptomator.common.Nullable; import org.cryptomator.ui.common.FxController; +import java.lang.reflect.Type; import javax.inject.Inject; import javax.inject.Named; import javafx.application.Application; @@ -16,13 +20,33 @@ import javafx.scene.Scene; import javafx.scene.input.Clipboard; import javafx.scene.input.ClipboardContent; import javafx.stage.Stage; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; import java.net.URLEncoder; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; +import com.google.gson.JsonParser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.InputStreamReader; +import java.util.Set; + public class ErrorController implements FxController { + private static final Logger LOG = LoggerFactory.getLogger(ErrorController.class); + private static final String ERROR_CODES_URL = "https://gist.githubusercontent.com/cryptobot/accba9fb9555e7192271b85606f97230/raw/errorcodes.json"; private static final String SEARCH_URL_FORMAT = "https://github.com/cryptomator/cryptomator/discussions/categories/errors?discussions_q=category:Errors+%s"; private static final String REPORT_URL_FORMAT = "https://github.com/cryptomator/cryptomator/discussions/new?category=Errors&title=Error+%s&body=%s"; private static final String SEARCH_ERRORCODE_DELIM = " OR "; @@ -47,6 +71,10 @@ public class ErrorController implements FxController { private final Environment environment; private BooleanProperty copiedDetails = new SimpleBooleanProperty(); + private BooleanProperty lookUpSolutionVisibility = new SimpleBooleanProperty(); + private final HttpClient httpClient; + + List errorDiscussionList; @Inject ErrorController(Application application, @Named("stackTrace") String stackTrace, ErrorCode errorCode, @Nullable Scene previousScene, Stage window, Environment environment) { @@ -56,6 +84,86 @@ public class ErrorController implements FxController { this.previousScene = previousScene; this.window = window; this.environment = environment; + this.httpClient = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).build(); + + + + HttpClient httpClient = HttpClient.newHttpClient(); + HttpRequest httpRequest = HttpRequest.newBuilder() + .uri(URI.create(ERROR_CODES_URL)) + .build(); + + CompletableFuture> future = httpClient.sendAsync(httpRequest, HttpResponse.BodyHandlers.ofString()); + + future.thenAcceptAsync(response -> { + int statusCode = response.statusCode(); + if (statusCode == 200) { + String jsonString = response.body(); + //LOG.debug("jpkED - jsonString : " + jsonString); + //System.out.println(jsonString); + + //JsonObject jsonObject = (JsonObject)new JsonParser().parse(jsonString); + + jsonString = "[{\"id\":\"D_kwDOAPryk84ASwC1\",\"upvoteCount\":4,\"title\":\"Error GH1B:GH1B:NJFJ\",\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2710\",\"answer\":{\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2710#discussioncomment-5191708\",\"upvoteCount\":3},\"comments\":8},{\"id\":\"D_kwDOAPryk84ASw_I\",\"upvoteCount\":1,\"title\":\"Error GH1B:GH1B:NJFJ\",\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2716\",\"answer\":null,\"comments\":2},{\"id\":\"D_kwDOAPryk84ASxAg\",\"upvoteCount\":1,\"title\":\"Error GH1B:GH1B:NJFJ\",\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2717\",\"answer\":{\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2717#discussioncomment-5181996\",\"upvoteCount\":2},\"comments\":3},{\"id\":\"D_kwDOAPryk84ASxDK\",\"upvoteCount\":1,\"title\":\"Error GH1B:GH1B:NJFJ\",\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2718\",\"answer\":null,\"comments\":0},{\"id\":\"D_kwDOAPryk84ATj-U\",\"upvoteCount\":1,\"title\":\"ErrorCode N05M:GEAO:GEAO\",\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2877\",\"answer\":null,\"comments\":1},{\"id\":\"D_kwDOAPryk84ATl2o\",\"upvoteCount\":1,\"title\":\"Error GH1B:GH1B:NJFJ\",\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2883\",\"answer\":{\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2883#discussioncomment-5769879\",\"upvoteCount\":1},\"comments\":1},{\"id\":\"D_kwDOAPryk84ATqCM\",\"upvoteCount\":1,\"title\":\"Error Code 4VHF:1S9S:5EOP\",\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2887\",\"answer\":null,\"comments\":0},{\"id\":\"D_kwDOAPryk84ATqDF\",\"upvoteCount\":1,\"title\":\"Error H1VR:OTAS:OTAS\",\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2888\",\"answer\":null,\"comments\":0},{\"id\":\"D_kwDOAPryk84ATrPD\",\"upvoteCount\":1,\"title\":\"Error S4DB:IV2H:I3UI\",\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2891\",\"answer\":{\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2891#discussioncomment-5797329\",\"upvoteCount\":1},\"comments\":1},{\"id\":\"D_kwDOAPryk84ATtJZ\",\"upvoteCount\":1,\"title\":\"Error 3MAT:BDUS:BDUS\",\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2894\",\"answer\":null,\"comments\":0},{\"id\":\"D_kwDOAPryk84ATuDc\",\"upvoteCount\":1,\"title\":\"Error QPDR:AFGD:AFGD\",\"url\":\"https://github.com/cryptomator/cryptomator/discussions/2895\",\"answer\":null,\"comments\":0}]"; + + Gson gson = new Gson(); + Type listType = new TypeToken>(){}.getType(); + errorDiscussionList = gson.fromJson(jsonString,listType); + + + + loadJsonToErrorDiscussionList(); + + + + + LOG.debug("jpkED - errorDiscussionList loaded | amount:"+errorDiscussionList.size()+""); + + //find exact matching + List newErrorDiscussionList = new ArrayList<>(); + newErrorDiscussionList.addAll(errorDiscussionList); + newErrorDiscussionList.removeIf(errorDiscussion -> !errorDiscussion.getErrorCode().contains(getErrorCode())); + if(newErrorDiscussionList.size()>0){ + errorDiscussionList.clear(); + errorDiscussionList.addAll(newErrorDiscussionList); + LOG.debug("jpkED - exact match | amount:"+errorDiscussionList.size()+""); + + lookUpSolutionVisibility.set(true); + } + else{ + //find method code matching + newErrorDiscussionList.clear(); + newErrorDiscussionList.addAll(errorDiscussionList); + newErrorDiscussionList.removeIf(errorDiscussion -> !errorDiscussion.getErrorCode().contains(getErrorCodeMethodCode())); + if(newErrorDiscussionList.size()>0){ + errorDiscussionList.clear(); + errorDiscussionList.addAll(newErrorDiscussionList); + LOG.debug("jpkED - method match | amount:"+errorDiscussionList.size()+""); + } + else{ + errorDiscussionList.clear(); + LOG.debug("jpkED - nothing found"); + + } + } + + if(errorDiscussionList.size()!=0){ + //answered + newErrorDiscussionList.clear(); + newErrorDiscussionList.addAll(errorDiscussionList); + newErrorDiscussionList.removeIf(errorDiscussion -> errorDiscussion.answer == null); + if(newErrorDiscussionList.size()>0){ + errorDiscussionList.clear(); + errorDiscussionList.addAll(newErrorDiscussionList); + LOG.debug("jpkED - answered | amount:"+errorDiscussionList.size()+""); + } + Collections.sort(errorDiscussionList, this::errorDiscussionComparator); + LOG.debug("jpkED - most upvote | id: " + errorDiscussionList.get(0).id + " | title: " + errorDiscussionList.get(0).title + " | upvoteCount:" + errorDiscussionList.get(0).upvoteCount); + } + } + }).join(); + + } @FXML @@ -70,6 +178,13 @@ public class ErrorController implements FxController { window.close(); } + @FXML + public void showSolution() { + if(errorDiscussionList.size()!=0) { + application.getHostServices().showDocument(errorDiscussionList.get(0).url); + } + } + @FXML public void searchError() { var searchTerm = URLEncoder.encode(getErrorCode().replace(ErrorCode.DELIM, SEARCH_ERRORCODE_DELIM), StandardCharsets.UTF_8); @@ -111,7 +226,11 @@ public class ErrorController implements FxController { } public String getErrorCode() { - return errorCode.toString(); + //return "GH1B:GH1B:NJFJ"; // 31 exact match - 4 answered + //return "GIJU:E215:E215"; // 1 exact match - 0 answered + //return "6PHE:UG0C:UG0C"; // 0 exact match - 8 method match - 3 answered + //return "0000:0000:0000"; // 0 match + return errorCode.toString(); // 0 exact match - 8 method match - 3 answered } public String getDetailText() { @@ -125,4 +244,65 @@ public class ErrorController implements FxController { public boolean getCopiedDetails() { return copiedDetails.get(); } -} + + public BooleanProperty lookUpSolutionVisibilityProperty() { + return lookUpSolutionVisibility; + } + + public boolean getLookUpSolutionVisibility() { + return lookUpSolutionVisibility.get(); + } + + public String getDetailTexts() { + return "```\nError Code " + getErrorCode() + "\n" + getStackTrace() + "\n```"; + } + + private void filterListByMethodCode(){ + List newErrorDiscussionList = new ArrayList<>(); + for (int i = 0; i < errorDiscussionList.size(); i++) { + ErrorDiscussion errorDiscussion = errorDiscussionList.get(i); + if(errorDiscussion.getMethodCode().equals(getErrorCodeMethodCode())){ + newErrorDiscussionList.add(errorDiscussion); + } + } + if(newErrorDiscussionList.size()!=0){ + errorDiscussionList = newErrorDiscussionList; + lookUpSolutionVisibility.set(true); + LOG.debug("jpkED - found matching method code | amount:"+errorDiscussionList.size()+""); + } + else{ + errorDiscussionList = newErrorDiscussionList; // to clear results + LOG.debug("jpkED - no matching method code found"); + } + } + + private int errorDiscussionComparator(ErrorDiscussion t, ErrorDiscussion t1) { + return Integer.compare(t1.upvoteCount, t.upvoteCount); + } + + private String getErrorCodeMethodCode(){ + return getErrorCode().substring(0,4); + } + + private void loadJsonToErrorDiscussionList(){ + String errorCodesUrl = "https://gist.githubusercontent.com/cryptobot/accba9fb9555e7192271b85606f97230/raw/errorcodes.json"; + try (InputStream is = new URL(errorCodesUrl).openStream()) { //TODO: HttpClient(){ async request + + JsonObject jsonObject = (JsonObject)new JsonParser().parse(new InputStreamReader(is,"UTF-8")); + + LOG.debug("jpkED - jsonObject | "+jsonObject.toString()); + + Set keys = jsonObject.keySet(); + errorDiscussionList = new ArrayList<>(); + for (int i = 0; i < jsonObject.size(); i++) { + errorDiscussionList.add(new Gson().fromJson(jsonObject.get(keys.stream().toList().get(i)),ErrorDiscussion.class)); + } + LOG.debug("jpkED - errorDiscussionList loaded | amount:"+errorDiscussionList.size()+""); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + + } +} \ No newline at end of file diff --git a/src/main/java/org/cryptomator/ui/error/ErrorDiscussion.java b/src/main/java/org/cryptomator/ui/error/ErrorDiscussion.java new file mode 100644 index 000000000..c6f568d70 --- /dev/null +++ b/src/main/java/org/cryptomator/ui/error/ErrorDiscussion.java @@ -0,0 +1,31 @@ +package org.cryptomator.ui.error; + +public class ErrorDiscussion { + + String id; + int upvoteCount; + String title; + String url; + int comments; + Answer answer; + + String getUpvoteCount(){return upvoteCount+"";} + + String getErrorCode(){return title.substring(6);} + String getMethodCode(){ + return title.substring(6,10); + } + String getRootCauseCode(){ + return title.substring(11,15); + } + + String getThrowableCode(){ + return title.substring(16,20); + } + + class Answer{ + private String url; + private int upvoteCount; + } + +} diff --git a/src/main/resources/fxml/error.fxml b/src/main/resources/fxml/error.fxml index ca0966a0a..857e6478d 100644 --- a/src/main/resources/fxml/error.fxml +++ b/src/main/resources/fxml/error.fxml @@ -31,13 +31,19 @@ -