{"action":"created","comment":{"url":"https://api.github.com/repos/SpongePowered/SpongeAPI/pulls/comments/41492590","id":41492590,"diff_hunk":"@@ -0,0 +1,164 @@\n+/*\n+ * This file is part of SpongeAPI, licensed under the MIT License (MIT).\n+ *\n+ * Copyright (c) SpongePowered <https://www.spongepowered.org>\n+ * Copyright (c) contributors\n+ *\n+ * Permission is hereby granted, free of charge, to any person obtaining a copy\n+ * of this software and associated documentation files (the \"Software\"), to deal\n+ * in the Software without restriction, including without limitation the rights\n+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n+ * copies of the Software, and to permit persons to whom the Software is\n+ * furnished to do so, subject to the following conditions:\n+ *\n+ * The above copyright notice and this permission notice shall be included in\n+ * all copies or substantial portions of the Software.\n+ *\n+ * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n+ * THE SOFTWARE.\n+ */\n+package org.spongepowered.api.service.error;\n+\n+import com.google.common.base.Optional;\n+import com.google.common.util.concurrent.ListenableFuture;\n+import org.spongepowered.api.text.Text;\n+import org.spongepowered.api.util.command.CommandSource;\n+\n+import java.net.URL;\n+\n+/**\n+ * An error report. This object is mutable.\n+ */\n+public interface ErrorReport {\n+\n+    /**\n+     * Get the {@link Throwable} that was responsible for creating this error report, if any is present.\n+     *\n+     * @return The optional throwable for this error report\n+     */\n+    Optional<Throwable> getCause();\n+\n+    /**\n+     * Check if this error is the result of a misconfiguration on the user's part, or due to an error in programming.\n+     * This defaults to true only if the {@link #getCause()} is a {@link UserErrorException}.\n+     *\n+     * @return Whether or not this is a user error\n+     */\n+    boolean isUserError();\n+\n+    /**\n+     * Set whether or not this is user error.\n+     *\n+     * @param isUserError Whether or not this is a user error\n+     * @return this\n+     */\n+    ErrorReport setUserError(boolean isUserError);\n+\n+    /**\n+     * Get a description of the base cause of this error.\n+     *\n+     * @return The description of this error's base cause\n+     */\n+    String getCauseDescription();\n+\n+    /**\n+     * Get a section with the given title, creating and appending to the end of the error report as necessary.\n+     *\n+     * @param title The title to give the section\n+     * @return The correct section\n+     */\n+    Section appendSection(String title);\n+\n+    /**\n+     * Append a {@link Reportable} to this report. If this {@link Reportable} has already been added, it will not be added again.\n+     *\n+     * @param reportable The object to append information from\n+     * @return this\n+     */\n+    ErrorReport addReportable(Reportable reportable);\n+\n+    /**\n+     * Dispatch this error as a fatal error. Fatal means that the server will be stopped and a full crash report will be generated.\n+     *\n+     * An exception will be used to pass the result of this error up the call stack. This exception must be passed on.","path":"src/main/java/org/spongepowered/api/service/error/ErrorReport.java","position":88,"original_position":88,"commit_id":"909a1ca33701f9714e36df91ab948ce9bf233cd7","original_commit_id":"909a1ca33701f9714e36df91ab948ce9bf233cd7","user":{"login":"Phroa","id":6373176,"avatar_url":"https://avatars.githubusercontent.com/u/6373176?v=3","gravatar_id":"","url":"https://api.github.com/users/Phroa","html_url":"https://github.com/Phroa","followers_url":"https://api.github.com/users/Phroa/followers","following_url":"https://api.github.com/users/Phroa/following{/other_user}","gists_url":"https://api.github.com/users/Phroa/gists{/gist_id}","starred_url":"https://api.github.com/users/Phroa/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Phroa/subscriptions","organizations_url":"https://api.github.com/users/Phroa/orgs","repos_url":"https://api.github.com/users/Phroa/repos","events_url":"https://api.github.com/users/Phroa/events{/privacy}","received_events_url":"https://api.github.com/users/Phroa/received_events","type":"User","site_admin":false},"body":"This should probably have `<p>` tags wrapping it","created_at":"2015-10-08T09:22:13Z","updated_at":"2015-10-08T09:22:13Z","html_url":"https://github.com/SpongePowered/SpongeAPI/pull/793#discussion_r41492590","pull_request_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/pulls/793","_links":{"self":{"href":"https://api.github.com/repos/SpongePowered/SpongeAPI/pulls/comments/41492590"},"html":{"href":"https://github.com/SpongePowered/SpongeAPI/pull/793#discussion_r41492590"},"pull_request":{"href":"https://api.github.com/repos/SpongePowered/SpongeAPI/pulls/793"}}},"pull_request":{"url":"https://api.github.com/repos/SpongePowered/SpongeAPI/pulls/793","id":41851421,"html_url":"https://github.com/SpongePowered/SpongeAPI/pull/793","diff_url":"https://github.com/SpongePowered/SpongeAPI/pull/793.diff","patch_url":"https://github.com/SpongePowered/SpongeAPI/pull/793.patch","issue_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/issues/793","number":793,"state":"open","locked":false,"title":"Add API for generating error reports.","user":{"login":"zml2008","id":629092,"avatar_url":"https://avatars.githubusercontent.com/u/629092?v=3","gravatar_id":"","url":"https://api.github.com/users/zml2008","html_url":"https://github.com/zml2008","followers_url":"https://api.github.com/users/zml2008/followers","following_url":"https://api.github.com/users/zml2008/following{/other_user}","gists_url":"https://api.github.com/users/zml2008/gists{/gist_id}","starred_url":"https://api.github.com/users/zml2008/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zml2008/subscriptions","organizations_url":"https://api.github.com/users/zml2008/orgs","repos_url":"https://api.github.com/users/zml2008/repos","events_url":"https://api.github.com/users/zml2008/events{/privacy}","received_events_url":"https://api.github.com/users/zml2008/received_events","type":"User","site_admin":false},"body":"This service makes it easier for plugins to generate error reports that provide useful information for plugin developers.\r\n\r\n[Example error report](https://gist.github.com/anonymous/ae434617c550c176f219)\r\n\r\nThe implementation wraps Minecraft's CrashReport system, with the changes of:\r\n- Easily allowing sending the error report to a specific player\r\n- Outputting the error report in Markdown format\r\n- Posting the error report to an anonymous gist\r\n- Using Text to allow formatting certain sections\r\n\r\nThings to think about:\r\n- [ ] How to pass through fatal exceptions? I currently use MC's ReportedException in the impl, but the SimpleCommandService wraps these in another layer of error reporting. Ways to deal with this are exposing the ReportedException to the API somehow, allowing custom error handlers to pass them through, moving the SimpleCommandService into the implementation and capturing there, or making the ErrorReportService simply reuse the existing error report while allowing the command service to tack on its additional data\r\n- [ ] Should each Reportable be provided the entire error report, or its own section? \r\n- [ ] Additional pastebin services, authentication support? (would be configurable)","created_at":"2015-08-07T01:10:09Z","updated_at":"2015-10-08T09:22:13Z","closed_at":null,"merged_at":null,"merge_commit_sha":null,"assignee":{"login":"zml2008","id":629092,"avatar_url":"https://avatars.githubusercontent.com/u/629092?v=3","gravatar_id":"","url":"https://api.github.com/users/zml2008","html_url":"https://github.com/zml2008","followers_url":"https://api.github.com/users/zml2008/followers","following_url":"https://api.github.com/users/zml2008/following{/other_user}","gists_url":"https://api.github.com/users/zml2008/gists{/gist_id}","starred_url":"https://api.github.com/users/zml2008/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zml2008/subscriptions","organizations_url":"https://api.github.com/users/zml2008/orgs","repos_url":"https://api.github.com/users/zml2008/repos","events_url":"https://api.github.com/users/zml2008/events{/privacy}","received_events_url":"https://api.github.com/users/zml2008/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/pulls/793/commits","review_comments_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/pulls/793/comments","review_comment_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/pulls/comments{/number}","comments_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/issues/793/comments","statuses_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/statuses/909a1ca33701f9714e36df91ab948ce9bf233cd7","head":{"label":"SpongePowered:feature/errorreport","ref":"feature/errorreport","sha":"909a1ca33701f9714e36df91ab948ce9bf233cd7","user":{"login":"SpongePowered","id":8683473,"avatar_url":"https://avatars.githubusercontent.com/u/8683473?v=3","gravatar_id":"","url":"https://api.github.com/users/SpongePowered","html_url":"https://github.com/SpongePowered","followers_url":"https://api.github.com/users/SpongePowered/followers","following_url":"https://api.github.com/users/SpongePowered/following{/other_user}","gists_url":"https://api.github.com/users/SpongePowered/gists{/gist_id}","starred_url":"https://api.github.com/users/SpongePowered/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SpongePowered/subscriptions","organizations_url":"https://api.github.com/users/SpongePowered/orgs","repos_url":"https://api.github.com/users/SpongePowered/repos","events_url":"https://api.github.com/users/SpongePowered/events{/privacy}","received_events_url":"https://api.github.com/users/SpongePowered/received_events","type":"Organization","site_admin":false},"repo":{"id":23770421,"name":"SpongeAPI","full_name":"SpongePowered/SpongeAPI","owner":{"login":"SpongePowered","id":8683473,"avatar_url":"https://avatars.githubusercontent.com/u/8683473?v=3","gravatar_id":"","url":"https://api.github.com/users/SpongePowered","html_url":"https://github.com/SpongePowered","followers_url":"https://api.github.com/users/SpongePowered/followers","following_url":"https://api.github.com/users/SpongePowered/following{/other_user}","gists_url":"https://api.github.com/users/SpongePowered/gists{/gist_id}","starred_url":"https://api.github.com/users/SpongePowered/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SpongePowered/subscriptions","organizations_url":"https://api.github.com/users/SpongePowered/orgs","repos_url":"https://api.github.com/users/SpongePowered/repos","events_url":"https://api.github.com/users/SpongePowered/events{/privacy}","received_events_url":"https://api.github.com/users/SpongePowered/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/SpongePowered/SpongeAPI","description":"A Minecraft plugin API","fork":false,"url":"https://api.github.com/repos/SpongePowered/SpongeAPI","forks_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/forks","keys_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/keys{/key_id}","collaborators_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/teams","hooks_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/hooks","issue_events_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/issues/events{/number}","events_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/events","assignees_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/assignees{/user}","branches_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/branches{/branch}","tags_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/tags","blobs_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/git/refs{/sha}","trees_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/git/trees{/sha}","statuses_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/statuses/{sha}","languages_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/languages","stargazers_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/stargazers","contributors_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/contributors","subscribers_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/subscribers","subscription_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/subscription","commits_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/commits{/sha}","git_commits_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/git/commits{/sha}","comments_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/comments{/number}","issue_comment_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/issues/comments{/number}","contents_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/contents/{+path}","compare_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/compare/{base}...{head}","merges_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/merges","archive_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/downloads","issues_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/issues{/number}","pulls_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/pulls{/number}","milestones_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/milestones{/number}","notifications_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/labels{/name}","releases_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/releases{/id}","created_at":"2014-09-07T20:39:25Z","updated_at":"2015-10-01T12:17:50Z","pushed_at":"2015-10-08T05:48:24Z","git_url":"git://github.com/SpongePowered/SpongeAPI.git","ssh_url":"git@github.com:SpongePowered/SpongeAPI.git","clone_url":"https://github.com/SpongePowered/SpongeAPI.git","svn_url":"https://github.com/SpongePowered/SpongeAPI","homepage":"http://www.spongepowered.org/","size":28392,"stargazers_count":801,"watchers_count":801,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":347,"mirror_url":null,"open_issues_count":105,"forks":347,"open_issues":105,"watchers":801,"default_branch":"master"}},"base":{"label":"SpongePowered:master","ref":"master","sha":"c5859a10fcc96a58eebf23d274ae6a5ece525d8e","user":{"login":"SpongePowered","id":8683473,"avatar_url":"https://avatars.githubusercontent.com/u/8683473?v=3","gravatar_id":"","url":"https://api.github.com/users/SpongePowered","html_url":"https://github.com/SpongePowered","followers_url":"https://api.github.com/users/SpongePowered/followers","following_url":"https://api.github.com/users/SpongePowered/following{/other_user}","gists_url":"https://api.github.com/users/SpongePowered/gists{/gist_id}","starred_url":"https://api.github.com/users/SpongePowered/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SpongePowered/subscriptions","organizations_url":"https://api.github.com/users/SpongePowered/orgs","repos_url":"https://api.github.com/users/SpongePowered/repos","events_url":"https://api.github.com/users/SpongePowered/events{/privacy}","received_events_url":"https://api.github.com/users/SpongePowered/received_events","type":"Organization","site_admin":false},"repo":{"id":23770421,"name":"SpongeAPI","full_name":"SpongePowered/SpongeAPI","owner":{"login":"SpongePowered","id":8683473,"avatar_url":"https://avatars.githubusercontent.com/u/8683473?v=3","gravatar_id":"","url":"https://api.github.com/users/SpongePowered","html_url":"https://github.com/SpongePowered","followers_url":"https://api.github.com/users/SpongePowered/followers","following_url":"https://api.github.com/users/SpongePowered/following{/other_user}","gists_url":"https://api.github.com/users/SpongePowered/gists{/gist_id}","starred_url":"https://api.github.com/users/SpongePowered/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SpongePowered/subscriptions","organizations_url":"https://api.github.com/users/SpongePowered/orgs","repos_url":"https://api.github.com/users/SpongePowered/repos","events_url":"https://api.github.com/users/SpongePowered/events{/privacy}","received_events_url":"https://api.github.com/users/SpongePowered/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/SpongePowered/SpongeAPI","description":"A Minecraft plugin API","fork":false,"url":"https://api.github.com/repos/SpongePowered/SpongeAPI","forks_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/forks","keys_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/keys{/key_id}","collaborators_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/teams","hooks_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/hooks","issue_events_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/issues/events{/number}","events_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/events","assignees_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/assignees{/user}","branches_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/branches{/branch}","tags_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/tags","blobs_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/git/refs{/sha}","trees_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/git/trees{/sha}","statuses_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/statuses/{sha}","languages_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/languages","stargazers_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/stargazers","contributors_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/contributors","subscribers_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/subscribers","subscription_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/subscription","commits_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/commits{/sha}","git_commits_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/git/commits{/sha}","comments_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/comments{/number}","issue_comment_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/issues/comments{/number}","contents_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/contents/{+path}","compare_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/compare/{base}...{head}","merges_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/merges","archive_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/downloads","issues_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/issues{/number}","pulls_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/pulls{/number}","milestones_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/milestones{/number}","notifications_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/labels{/name}","releases_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/releases{/id}","created_at":"2014-09-07T20:39:25Z","updated_at":"2015-10-01T12:17:50Z","pushed_at":"2015-10-08T05:48:24Z","git_url":"git://github.com/SpongePowered/SpongeAPI.git","ssh_url":"git@github.com:SpongePowered/SpongeAPI.git","clone_url":"https://github.com/SpongePowered/SpongeAPI.git","svn_url":"https://github.com/SpongePowered/SpongeAPI","homepage":"http://www.spongepowered.org/","size":28392,"stargazers_count":801,"watchers_count":801,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":347,"mirror_url":null,"open_issues_count":105,"forks":347,"open_issues":105,"watchers":801,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/SpongePowered/SpongeAPI/pulls/793"},"html":{"href":"https://github.com/SpongePowered/SpongeAPI/pull/793"},"issue":{"href":"https://api.github.com/repos/SpongePowered/SpongeAPI/issues/793"},"comments":{"href":"https://api.github.com/repos/SpongePowered/SpongeAPI/issues/793/comments"},"review_comments":{"href":"https://api.github.com/repos/SpongePowered/SpongeAPI/pulls/793/comments"},"review_comment":{"href":"https://api.github.com/repos/SpongePowered/SpongeAPI/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/SpongePowered/SpongeAPI/pulls/793/commits"},"statuses":{"href":"https://api.github.com/repos/SpongePowered/SpongeAPI/statuses/909a1ca33701f9714e36df91ab948ce9bf233cd7"}}}}